嵌入式Linux引導過程之1.5——從BootRom到Xloader
在開始看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之後,就是我們現在正在分析的代碼部分了。
後續部分我們將接著一步一步來分析。
最後更新:2017-04-03 16:48:40