代碼分析
在上一篇文章中,我們已經對barebox的編譯、燒寫和運作有了一個大緻的了解,
現在我們就要開始學習代碼了。
一般的bootloader都會以一個彙編檔案作為起始,但是barebox沒有這樣。
這個c函數作為了整個iamge的入口,關鍵是__section(.text_entry)和lds檔案起了作用。
lds檔案是arch/arm/lib/barebox.lds.S,它會被編譯成barebox.lds并最終參與連結。
*(.text_entry*)就相當于把start函數關聯進了lds檔案,然後ENTRY(start)又指定整個image的入口,于是start函數就成了整個image的入口。
而0x23e00000則是dram中的位址,後面barebox會把自己拷貝到這個位址并跳轉過去。
我們繼續來看代碼,
這兩個函數都是inline函數,是以代碼都會被内嵌到start函數中去。
于是c函數start其實就變成了一個彙編函數。
我們可以看到,在彙編代碼的最前端,連續的8個跳轉,其實是模仿arm的8個異常向量。
但在這裡其實并沒有什麼作用,隻是簡單的做了下跳轉到2,并在中間留了一些空間儲存了一些資料。
先是一個8個位元組大小的字元串barebox,然後是兩個4位元組變量,一個儲存的是barebox的連結位址,還有個是barebox的大小,最後則是連續8個0x55555555。
從我們之前dump的barebox.bin可以看出,這和我們想的完全一緻。
這裡連結位址是0x23e00000,大小是0x13fe8。
接下來,程式就會調用arch/arm/boards/friendlyarm-tiny210/lowlevel.c中的barebox_arm_reset_vector函數。
arm_cpu_lowlevel_init隻是預留了一個接口,暫時并沒有實作什麼功能。
是以第一步做的事情是配置pll。
然後判斷目前代碼的運作位置。
假設程式是通過rom code加載到sram運作的話,其pc值必定是從0xD0020000起,外加16個位元組的校驗,是以就是0xD0020010了。
如果已經是在dram中的話,那就沒有必要再初始化dram以及把barebox加載到dram了。
當然,在我們這種正常啟動情況下,代碼會順序往下走,進行dram的初始化配置。
dram配置完畢後,就把整個barebox從sd卡讀取到dram中去。
這裡又要用到s5pv210的一個特殊功能,它的rom code提供了從sd卡讀取資料的函數
是以隻要直接調用這個位址就可以實作barebox的加載了。
最後一步就是通過jump_sdram跳轉到dram中去,這之後運作的barebox_arm_entry函數,就是運作在dram中的了。
這裡還有一點需要注意,我們可以發現,在跳轉到dram之前運作的函數都是有__bare_init的
在lds檔案中是緊随*(.text_entry*)之後的。
估計是因為barebox的連結位址是dram中的位址,是以剛開始在sram中運作時被調用的函數都需要靠近以保證跳轉時使用的是相對偏移而不是絕對位址。
有嘗試過去掉某一函數的__bare_init修飾符,會直接導緻barebox無法正常運作。