標籤:blog http 使用 檔案 art 問題
--by FeCen
在開始看Xloader_Entry的代碼之前,我想先總結一下從晶片上電到開始運行Xloader的代碼的過程,這是我目前理解的一個過程,可能有所出入,待以後繼續完善。
當系統上電之後,首先會將PC寄存器設定成BootRom裡面的代碼對應的一個地址。BootRom是晶片內部整合的一塊很小的儲存區,裡面一般會固化一段啟動代碼。至於BootRom所佔用的地址空間,每個晶片的定義可能會有所不同,具體的可以參考晶片的使用者手冊中的Memory Map部分的說明。在spearplus中,BootRom位於從0xFF000000到0xFFFFFFFF的16M大小的地址區間。當然,BootRom的大小不一定要那麼大,這隻是說,這些地方給你用了,具體你用了多少隨你自己,夠用就行。在spearplus裡面是32k。
那麼BootRom有那麼大的一片地址地區可以用,具體系統上電的時候會跳轉到哪一個地址去執行代碼呢?這就取決於CPU的定義了。對於spearplus裡面使用的ARM926EJS來說,它是這麼定義的:Following reset, the ARM core starts to fetch instructions either from 0x00000000 or 0xFFFF0000 depending on the signal level of VINITHI* input signal to ARM core. If after reset VINITHI signal level is LOW then ARM core will start fetching code from address 0x00000000 otherwise ARM core will start fetching code from 0xFFFF0000. So there must be some executable code accessible from either of this address. In an embedded system, this requires some nonvolatile memory usually ROM or Flash to be present.
也就是說,ARM核在reset之後取得的第一條指令的地址取決於給ARM核輸入的一個訊號VINITHI,如果在設計的時候給ARM輸入的VINITHI訊號是低電平,那麼ARM核將從0x00000000這個地址來擷取它要執行的第一條指令,反之,如果給ARM輸入的VINITHI訊號是高電平,那麼它將從0xFFFF0000地址處擷取它要執行的第一條指令。
spearplus系統中(由於spearplus系統含有兩個ARM核,而在系統初始啟動的時候系統的控制權完全在ARM1上,此時的ARM2核是停用,因此在後面,我們所說的ARM核都是指ARM1核),在系統reset之後,輸送給ARM核的VINITHI訊號是一個高電平,因此,在我們的系統中,系統在上電之後將會去地址0xFFFF0000處擷取它所要執行的第一條指令。
我們發現,0xFFFF0000正好位於上面所說的BootRom的地址區間之內,因此,我們BootRom中的第一條代碼肯定是位於0xFFFF0000處的。這樣在系統啟動之後,就將從0xFFFF0000處取得所需要執行的第一條指令。之後就將按照BootRom預先定義好的過程往下走了。由於BootRom處的代碼(我們稱之為firmware,也就是在晶片出廠的時候就固化在晶片中的)我們是看不到的,因此我們只能根據文檔中的描述來進行說明。
在spearplus的BootRom中,主要提供了三個功能(其他的板子或者晶片中的bootrom提供的功能應該也是類似的):
1、從NOR serial Flash引導系統
2、從NAND Flash引導系統
3、從USB引導或者更新系統
在這三個功能中,其中第3個功能我們暫且不說,因為這個是最主要使用來在最初的時候(除了BootRom之外既沒有Xloader也沒有U-Boot的情況時),用來將Xloader image或者uboot image燒寫到相應的Flash中的。
我們這裡關心的主要是第1個和第2個功能。而從本質上來說,從NAND Flash引導和從NOR serial Flash引導應該是沒有差別的,最主要的是這兩種Flash的讀寫方式不同(另外,它們之間還有一個很重要的區別那就是NOR可以按位元組定址,也就是可以直接在NOR上面運行程式,而不必拷貝到RAM中,但是NAND是按塊定址的,無法直接在其上運行程式。但是對於spearplus來說,不管是NOR還是NAND,它的做法都是先將相應的代碼拷貝到RAM中),因此在將Flash中的內容載入到記憶體中的相應的地址中執行的時候的載入過程可能會有所區別。而對於我們的系統來說,使用的是NOR Flash,因此,這裡重點分析從NOR serial Flash引導系統的情況。具體的NOR Flash和NAND Flash的差別可以參考文末的參考文章。
BootRom在開始執行程式的時候,如果被設定成從NOR引導(可以通過向spearplus晶片提供幾個訊號,這幾個訊號的組合能夠指定BootRom的功能,具體參考晶片手冊),那麼BootRom會首先在flash的首個sector也就是第0號sector處檢查是否有uboot存在,如果存在就直接跳轉到uboot的代碼處執行(因為在NOR上是可以直接運行程式的)。由此可見,我們甚至可以不需要Xloader,而直接就從BootRom跳轉到uboot執行代碼(方法是直接將uboot image燒寫到flash的第0號sector)。但是我們沒有這麼做,我們在uboot之前又放置了一層Xloader,這麼做能夠提高系統的靈活性。
話說到這裡,那麼BootRom是怎麼來判斷到底在flash的第0號sector中有沒有uboot image的呢?其實方法很簡單,整個uboot image有兩部分組成,一個部分就是由uboot原始碼編譯產生的目標檔案(elf檔案),另一部分就是一個64位元組的image header,在這個image header中,有這個image的name屬性、magic number屬性、load address屬性等等,具體的我們將在後續的文章中詳細分析。這部分image header就是通過一個叫做mkimage的工具程式與之前編譯連結產生的目標elf檔案組合,最終產生uboot image的。而image header就位於這個uboot image的開頭64個位元組處,緊接著的就是elf目標檔案。而BootRom就是通過這個64個位元組大小的image header中的某個或者某幾個欄位來判斷在某一個位置是否存在某一個image的。對於判斷在flash的第0號sector,BootRom會首先讀取頭64個位元組的內容,然後判斷其中的name屬性是不是約定的值("UBOO"或者"UBOOT"取決於實現時的約定),如果經判斷確實是約定的值,那麼說明在sector 0上存在uboot image,否則則認為不存在。
顯然,在我們的實現方案中,是不存在uboot的,因為我們在其上還放置了一層Xloader。
因此,當BootRom發現在flash的sector 0中不存在uboot的時候,它會用同樣的方法來判斷其中是否存在Xloader image(同樣,Xloader image也會有一個image header,事實上,Xloader image的image header的結構和uboot image的image header的結構是完全相同的),如果它判斷存在Xloader image的時候,它就會將Xloader image載入到指定的SRAM的地址中(因為此時外部記憶體SDRAM還沒有進行初始化,因此不可用,還記得我們之前分析的在Xloader中的ddr_init嗎?對,SDRAM就是在那裡初始化的,因此Xloader都還沒有起來呢,SDRAM就更不可能被初始化了。由於每個人使用的SDRAM可能是不相同的,所以對SDRAM的初始化是不能夠放在BootRom裡面執行的。因此,此時只有晶片內部整合的8k的SRAM可用,因此Xloader代碼必須非常短小),然後跳轉到該地址執行,將控制權交給了Xloader。從這裡開始,就開始執行Xloader的代碼了,也就是我們最初分析的_start標號處的代碼了。那麼BootRom是如何知道Xloader image該載入到SRAM的哪個地址上的呢?又是如何在載入完之後跳轉到這個地址的呢?問題的答案還是在那個image header身上,剛才我們說過,在header的屬性裡面,有一個叫做load address的屬性,這個屬性就是BootRom和Xloader約定的那個地址。BootRom在讀取到Xloader header中的load address這個屬性之後,就會將xloader elf部分載入到該地址,然後跳轉到load address指定的地址上執行代碼。而這個load address則是由Xloader指定的,具體體現在Xloader的Makefile中的TEXT_BASE這個參數,這個參數在Xloader使用ld進行連結的時候作為ld的參數將覆蓋xloader.ldr檔案中指定的代碼運行起始地址,用以說明xloader指令的執行開始地址(通過ld的參數-T xloader.lds -Ttext $(TEXT_BASE)來指定),另外,這個TEXT_BASE同時還會傳遞給mkimage這個工具程式,使得在最作Xloader image的時候,能夠正確的設定image header中的load address這個屬性。這樣,整個過程也就完美了。
當然,如果BootRom在flash的sector 0處沒有找到xloader image,那麼它就會試圖從NAND flash引導(前提是在設定BootRom的功能模式的時候同時還設定了允許從NAND引導)。如果再找不到,那麼系統就會進入一個死迴圈。
在將程式的控制權成功交給Xloader之後,就是我們現在正在分析的代碼部分了。
後續部分我們將接著一步一步來分析。
參考文章:
NOR/NAND
http://blog.sina.com.cn/s/blog_53d5935e010006fl.html
參考:
1,嵌入式Linux引導過程之1.5——從BootRom到Xloader
http://blog.csdn.net/ffee/article/details/3092973