做實驗時我們是把 bin 文件燒入SD卡,比如前面做的匯編流水燈實驗。
問:是誰把這些指令從 SD 卡讀出來執行?
答:是固化在芯片內部ROM上的代碼---它被稱為iROM ,iROM是廠家事先燒寫在芯片上的,無源碼。
iROM把啟動設備上特定位置處的程序讀入片內存 (iRAM) ,並執行它。這個程序被稱為 ,並執行它。這個程序被稱為 BL1(Bootloader 1) ,BL1 是三星公司提供的,無源碼。
BL1又把啟動設備上另一個特定位置處的程序讀入片內內存,並執行它。這個被稱為 BL2(Bootloader 2) ,是我們編寫的源碼。
在匯編流水燈程序中我們通過mkbl2工具制作的BL2,當時也做了比較詳細的講解,執行如下命令:
./mkbl2 leds_on.bin bl2.bin 14336
iROM 、BL1更細致的啟動過程如下圖所示(摘自Android_Exynos4412_iROM_Secure_Booting_Guide_Ver.1.00.00.pdf):
(1) iROM :下圖是 iROM 啟動流程圖
由上圖可以看出,首先關閉看門狗,關閉中斷及MMU,關閉數據緩存,打開指令緩存,清除TLB,然後將其他核進入IDLE模式,只留CPU0,這裡有了第一個跳轉分支,IROM判斷當前啟動模式,是冷啟動還是喚醒,如果是喚醒模式,那麼就是直接跳轉到BL1,在BL1裡面我們會再次判斷是否是喚醒模式,如果是就直接跳轉到喚醒函數,一般都是linux內核的喚醒句柄。當然在裸機裡都是冷啟動的,休眠喚醒一般是不需要關注的,當然如果你的裸機程序需要支持休眠喚醒,就需要增加相應的代碼了。
繼續分析,設置IRQ及SVC模式的棧空間,這個時間,棧地址是其內部的一片IRAM,這小片RAM是IROM運行的外部隨機存儲器,沒有這片小內存,IROM是無法運行的。接下了就是初始化IROM裡面所使用的各種變量,初始化只讀數據段,未初始化數據段清零,導出部分核心函數,這個函數可以在BL1中使用,獲取當前復位的狀態,設置系統時鐘分頻,獲取OM管腳配置模式,這裡可以從多種外設啟動,具體啟動模式如下表:
我們整個裸機教程都是從外部SD卡啟動,根據OM啟動模式,從SD卡拷貝前8K代碼,如果拷貝成功,就驗證校驗和,BL1的前16個字節就是提供給IROM用來標識BL1相關信息的,具體信息如下(後面的教程我們會自己寫一個BL1,現階段先用三星提供的):
/* * bl1 header infomation for irom * * 0x0 - bl1 size * 0x4 - reserved (should be 0) * 0x8 - check sum * 0xc - reserved (should be 0) */ .word 0x2000 .word 0x0 .word 0x0 .word 0x0
首先是描述BL1的大小,然後還有一個BL1的校驗和,那我們怎麼知道BL1的校驗和呢,這個是在編譯生成最終的二進制文件後,通過mk4412程序制作的
簡單地說,iROM就是先設置程序運行環境 (比如關看門狗、關中斷、關MMU 、設置棧 、設置棧 、啟動 PLL 等 );然後根據OM引腳確定啟動設備 (NAND Flash/SD 卡/其他 ),把 BL1 從裡面讀出存入iRAM;最後啟動 BL1 。
(2) BL1 :下圖是 BL1 的啟動過程
簡單地說,也是設置程序運行環境(初始化中斷、設置棧等 );然後從啟動設備上把 BL2讀入iRAM;最後啟動它。
有幾個問題需要解決:
① 在啟動設備上哪個位置存放 BL1、BL2?
② 把BL1 BL2 讀到 iRAM哪個位置?
③ BL1 、BL2 大小是多少?
④ 怎麼保證 BL1 、BL2 程序的完整性(即讀出程序時沒有錯誤 )?
假設啟動備為 SD 卡, 如下圖所示(這裡只分析SD卡啟動):
BL1 位於SD卡偏移地址 512字節處(即從第一個扇區開始,前面有一個扇區保留,每個扇區512字節,為什麼保留第一個扇區,如果有同學對DOS分區表有過研究,就能明白其中的道理了,第一個扇區是分區表的配置區),iROM從這個位置讀入8K 字節的數據,存在iRAM地址 0x02021400位置處。 所以 BL1不能大於8K 。
IROM計算校驗和且驗證通過後並解密BL1成功後就可以跳轉到BL1了,至此IROM已執行完備,權限已交由BL1了,補充說明一下,解密BL1是加密模式啟動時才需要的,非加密模式啟動是無需解密BL1的。
BL2 位於 SD 卡偏移地址 (512 +8K)字節處,BL1從這個位置讀入14K 字節的數據,存在iRAM 地址 0x02023400 處。 BL2 不能大於(14K – 4) 字節,最後 4字節用於存放較驗碼(在匯編流水燈試驗中我們用mkbl2工具制作的BL2,其中mkbl2工具最主要的作用就是計算出校驗碼)。
如果我們的程序大於 (14K – 4) 字節,那麼需要截取前面 (14K – 4) 字節用來制作BL2並燒入SD卡偏移地址 (512 +8K) 字節處。當BL2啟動後,由它來將存放在SD卡另外位置的、完整程序讀入內存。