摘 要:詳細介紹Bootloader的操作模式以及其與主機之間的通信,說明Bootloader的兩階段任務——匯編語言編寫的固化代碼執行部分和C語言編寫的基于RAM執行部分,并通過對Blob源代碼的分析,介紹Blob所實現的功能,并找出其中的規律和原理,從而對Bootloader有更深刻的理解,并且能夠使得Bootloader運行于各種不同的硬件平臺。實際應用中已經完成了對系統的修改。
關鍵詞:Bootloader;Blob;ARM;初始化
中圖分類號:TP311 文獻標識碼:B
文章編號:1004-373X(2008)10-070-03
Design of Embedded Bootloader Software
WANG Qingping
(Hubei University of Education,Wuhan,430205,China)
Abstract:In this paper,the operation mode of Bootloader and the communication with HOST are introduced.The Bootloader includs two stages,one is the solidified code written in assemble language,the other is the executable binary code,which is written originated from C language and stored in RAM.This paper can also make apprehend Bootloader by analyzing the original Blob code and introducing the function of Blob,the rule of Blob,the principle of Blob,which gets Bootloader cross in all different kinds of hardware plateform.In our work,we have modify the Bootloader system for ARM system.
Keywords:Bootloader;Blob;ARM;initializing
任何計算機系統都有自己的引導程序,在嵌入式系統中,采用Bootloader引導程序。所謂Bootloader,就是在操作系統內核運行之前的一段小程序。通過這段小程序,可以初始化硬件設備、建立內存空間的映射圖,從而將系統的軟硬件環境帶到一個合適的狀態,以便為調用操作系統內核準備好正確的環境。
不同的 CPU有不同的 Bootloader。即使他們是基于同一種 CPU 而構建的,要想讓運行在一塊目標板上的 Bootloader 程序也能運行在另一塊板子上,通常也都需要修改 Bootloader 的源程序。因此,對Bootloader進行分析,并找出其中的規律和原理,使得Bootloader運行于各種不同的硬件平臺。
1 Bootloader的基本特征
1.1 階段性
多階段的Bootloader能提供更為復雜的功能,以及更好的可移植性。從固態存儲設備上啟動的Bootloader大多都是2階段的啟動過程,也即啟動過程可以分為stage 1和stage 2兩部分。其中stage 1用匯編語言編寫,是在FLASH執行,stage 2用C語言編寫,是在RAM中執行的。
1.2 多種操作模式
大多數Bootloader都包含2種不同的操作模式:啟動加載模式和下載模式。
(1) 啟動加載(Boot loading)模式:這種模式也稱為自主(Autonomous)模式。也即 Bootloader 從目標機上的某個固態存儲設備上將操作系統加載到 RAM 中運行,整個過程并沒有用戶的介入。這種模式是Bootloader的正常工作模式,因此在嵌入式產品發布時,Bootloader 顯然必須工作在這種模式下。
(2) 下載(Downloading)模式:在這種模式下,目標機上的 Bootloader 將通過串口連接或網絡連接等通信手段從主機(Host)下載文件,比如:下載內核映像和根文件系統映像等。從主機下載的文件通常首先被 Bootloader 保存到目標機的 RAM 中,然后再被 Bootloader 寫到目標機上的FLASH 類固態存儲設備中。Bootloader 的這種模式通常在第一次安裝內核與根文件系統時被使用;此外,以后的系統更新也會使用 Bootloader 的這種工作模式。工作于這種模式下的 Bootloader 通常都會向他的終端用戶提供一個簡單的命令行接口。
功能強大的Bootloader 通常同時支持這2種工作模式,而且允許用戶在這2種工作模式之間進行切換。比如,Blob在啟動時處于正常的啟動加載模式,但是他會延時10 s等待終端用戶按下任意鍵而將Blob切換到下載模式。如果在10 s內沒有用戶按鍵,則 Blob 繼續啟動 Linux 內核,下面將要具體介紹Blob。
1.3 Bootloader與主機之間的傳輸
最常見的情況是目標機上的 Bootloader 通過串口與主機之間進行文件傳輸,傳輸協議通常是xmodem/ymodem/zmodem協議中的一種。但是,串口傳輸的速度是有限的,因此通過以太網連接并借助 TFTP 協議來下載文件是個更好的選擇。如果對于一個裸機,可以采用JTAG進行燒寫,如燒寫ppcboot.bin文件等。
2 Bootloader的初始化過程
大多數 Bootloader 都分為 stage 1 和 stage 2 兩大部分。依賴于 CPU 體系結構的代碼,比如設備初始化代碼等,通常都放在 stage 1 中,而且通常都用匯編語言實現,以達到短小精悍的目的。而 stage 2 則通常用C語言來實現,這樣可以實現給復雜的功能,而且代碼會具有更好的可讀性和可移植性。
(1) Bootloader 的 stage 1 通常包括以下步驟(以執行的先后順序):
① 硬件設備初始化;
② 為加載 Bootloader 的 stage 2 準備 RAM 空間;
③ 拷貝 Bootloader 的 stage 2 到 RAM 空間中;
④ 設置好堆棧;
⑤ 跳轉到 stage 2 的 C 入口點。
(2) Bootloader 的 stage 2 通常包括以下步驟(以執行的先后順序):
① 初始化本階段要使用到的硬件設備;
② 檢測系統內存映射(memory map);
③ 將 kernel 映像和根文件系統映像從 FLASH 上讀到 RAM 空間中;
④ 為內核設置啟動參數;
⑤ 調用內核。
3 基本引導/裝入程序[CD2]Blob的分析和設計
3.1 Blob的第一階段
Blob也分為2階段執行引導/裝入程序,第一階段是引導程序。Blob直接從閃存芯片將操作系統裝入RAM,并轉到入口,完成操作系統的引導;如果使用者按下鍵盤,則放棄對操作系統的引導,改為進入Blob的監控程序。
3.1.1 開頭部分
引導裝入程序的代碼至少有一部分是必須在ROM或FLASH中執行的,Blob的star-ld-script文件開始提供連接程序用的一個連接/定位說明,他不是代碼,而是用來介紹目標映像中的各個段放在什么位置上。下面該程序的意思是,如果從地址0x0開始執行,就直接jump [CD#*2]start。
ENTRY([CD#*2]start)
{
.=0x00000000;
.=ALIGN(4);
………
}
這些信息告訴系統代碼段的入口為[CD#*2]start,放在地址0x0,可以根據實際芯片結構,修改這個物理地址。
3.1.2 [CD#*2]start程序
下面代碼開始就直接進入reset程序中,代碼中,除了第一條指令是正常執行之外,其他的指令都是不正常的情況下執行的,他們將CPU引入一個blinky程序段,在blinky程序段中,LED不斷的閃爍,提示重啟。
.global [CD#*2]start:
[CD#*2]start:
breset
bundefined[CD#*2]instruction
bsoftware[CD#*2]interrupt
bprefetch[CD#*2]abort
bdata[CD#*2]abort
bnot[CD#*2]used
birq
bfiq
3.1.3 閃存中執行reset
(1) 屏蔽所有的中斷,設置CPU的速度;
(2) 配置內存空間,設置內存控制器,啟動DRAM刷新;
(3) 對LED燈進行初始化,通過GPIO寄存器點亮LED,標志著RAM可以投入運行;
(4) 判斷ARM是否從睡眠(由于長期執行空操作而進入省電狀態)狀態喚醒,如果是則讀出PSPR寄存器的內容,這里保存的是ARM進入睡眠時候程序斷點地址,如果不是則進入(5);
(5) 執行一般的引導程序,前面雖然啟動了內存,但是還沒有啟動快速緩存,需要啟動快速緩存;
(6) 測試內存RAM的開頭1 MB空間,看內存空間可否讀、寫以及保存數據的功能;如果測試失敗,則進入blinky程序,閃燈,讓用戶重啟;
(7) 在完成內存、緩存的設置以及測試之后,需要快速執行,因此需要將余下Blob的余下代碼復制到RAM中去執行,如果LED指示燈熄滅則表示復制結束結束,準備跳轉到RAM中執行余下的程序。
3.2 Blob的第二階段
在第一階段結束的時候,有一條指令(mov pc,r0),這條指令中r0保存的是0x400,因此第二階段將從0x400這個地址開始執行,為了跟第一階段進行聯系,在第二階段也有這樣一個文件。
3.2.1 第二階段的開頭部分
下面為一個RAM映像入口-trampoline的連接程序,因為PC存放的是0x400這一個地址,而主程序在[CD#*2]trampoline中,因此需要將0x400和[CD#*2]trampoline連接起來。直接jump [CD#*2]trampoline。
在執行完以上連接之后,[CD#*2]trampoline中采用指令bl main,進入main程序。強調的是,在C中程序直接進入main函數執行主程序,但是匯編無法識別main,因此通過bl指令進入main函數,然后再采用C語言完成第二階段的設置。
ENTRY([CD#*2]trampoline)
{
.=0x00000400;
.=ALIGN(4);
………
}
3.2.2 main部分
(1) 執行RAM的測試,相對于閃存中執行的測試操作,這一部分是對整個RAM空間進行測試,檢查RAM空間的大小;
(2) 初始化一些Blob參數,使得他能夠位加載服務,加載的程序包括blob本身,要執行的內核kernel以及映像ramdisk,復制的數據來自于FLASH閃存中。有的系統中,這一步是采用一邊復制一邊解壓縮的辦法。這些kernel和ramdisk只是復制到RAM中,但是并不馬上執行,而是根據外部響應來選擇的執行;
(3) 在完成blob的一些加載之后,系統并不是立即啟動Linux,而是判斷用戶在規定時間之內是否通過串口將鍵盤某個值(有的規定是回車鍵)發送數據到緩存中,如果是,則暫時不啟動Linux,而是進入(4),執行Blob的程序,否則啟動Linux代碼,進入(5);啟動Linux代碼;
(4) 進入Blob的程序,實際上執行的是將(2)裝入RAM中的Blob,這部分實現的指令功能主要有:引導Linux內核的Boot指令,設置始終的clock指令,從串口行下載映像到內存的download指令,燒寫內核和ramdisk的FLASH指令,幫助的help指令,從RAM中重啟動的reblob指令,重新引導的reboot指令,重新實現步驟(2)功能的的reload指令,恢復初始控制臺的reset指令,設置串口下載速率的speed指令以及顯示狀態的status指令。關于這些指令,每個Bootloader都有與之功能類似的指令,可以通過help命令查看這些指令的說明;
(5) 進入Linux代碼,實際上執行的是前面裝入RAM的kernel以及ramdisk程序。
4 結 語
計算機系統都有一個Bootloader,這是因為現代計算機的內存在掉電的情況下數據都會丟失,因此現代計算機都把操作系統的內核首先固化到一個不容易丟失的設備上,一旦掉電,通過一個引導程序將操作系統引入到內存,然后再執行操作系統。根據不同的系統,方案不同,比如PC機器是通過BIOS來引導的,而DSP可以直接從EPROM或者其他的處理器加載操作系統到DSP上執行。這些都是Bootloader的多樣性的表現,因此設計一個Bootloader程序是一個復雜的過程,要根據具體的硬件,軟件需求分析來進行設計。在完成本文之前,根據項目的需要,對Bootloader系統進行修改,使得Bootloader能夠運行于自己的ARM系統。
參 考 文 獻
[1]華恒科技.HHARM2410開發平臺技術手冊\\[Z\\].2005.
[2]Sumsung Electronics S3C2410X 32 b Risc Microprocessor User′s Manual Revision 1.2.2003.
[3]毛德操,胡希明.嵌入式系統采用公開源代碼和StrongARM/Xscale處理器\\[M\\].杭州:浙江大學出版社,2003.[4]孫天澤,袁文菊,張海峰.嵌入式設計及Linux驅動開發指南[CD2]基于ARM 9處理器\\[M\\].北京:電子工業出版社,2005.
作者簡介
王青萍 女,1980年出生,助教。研究方向為信號與信息系統。