天天看點

[mystery]-bootloader與u-boot詳解

         很多人在剛接觸這兩個東西的時候,可能和我一樣,對這兩個東東有不少疑惑,于是我查閱了相關資料,整理如下

------------------------------------------------------------------

Bootloader的引入 

在系統上電之後,需要一段程式來進行初始化:關閉WATCHDOG、改變系統時鐘、初始化存儲控制器、将更多的代碼複制到記憶體中等等。如果它能将作業系統核心(無論從本地,比如Flash;還是從遠端,比如通過網絡)複制到記憶體中運作,就稱這段程式為Bootloader。 

簡單地說,Bootloader就是這麼一小段程式,它在系統上電時開始執行,初始化硬體裝置、準備好軟體環境,最後調用作業系統核心。 

Bootloader的實作嚴重依賴于具體硬體,在嵌入式系統中硬體配置千差萬别,即使是相同的CPU,它的外設(比如Flash)也可能不同,是以不可能有一個Bootloader支援所有的CPU、所有的電路闆。即使是支援CPU架構比較多的U-Boot,也不是一拿來就可以使用的(除非裡面的配置剛好與你的闆子相同),需要進行一些移植。 

-----------------------------------------------------------------------

U-Boot與Bootloader的關系

我們可以增強Bootloader的功能,比如增加網絡功能、從PC上通過序列槽或網絡下載下傳檔案、燒寫檔案、将Flash上壓縮的檔案解壓後再運作等──這就是一個功能更為強大的Bootloader,也稱為Monitor。U-boot就是這樣一種bootloader,全功能體積高達數百Kbytes,實際上,在最終産品中使用者并不需要這些功能,它們隻是為了友善開發。 

U-Boot全稱是Universal Bootloader,也是一款開源項目,作為Bootloader的一種,具備多種引導核心啟動的方式。常用的go和bootm指令可以直接引導核心映像啟動。U-Boot與核心的關系主要是核心啟動過程中參數的傳遞。

bootloader的作用

那我們也知道其實OS(如linux)的Kernel其實也是一段裸機程式,也是直接掌管硬體的,不過這個程式極其複雜,許許多多的計算機專家和黑客為其耗費心血,如果三四百K的U-boot已經比較複雜,那麼一個典型功能的linux Kernel編譯後竟然能高達萬Kbytes,光從代碼量來看,linux的複雜度已經是U-boot的百倍。而其實遠不止。

雖然kernel很complex,但終究不過是一段裸機代碼,Bootloader進行所謂的“kernel引導”,其過程不過是從bootloader裡的一句跳轉代碼,跳轉到kernel代碼處(執行kernel中的第一個函數),所謂傳遞參數也不過是bootloader和kernel約定一個記憶體地點存放。在這個過程中,bootloader和kernel雖然都處于同一個記憶體裡,但是它們除了“引導”與“傳遞有限的參數”這樣的關系,并無其它關系,完全是兩個獨立的程式。之是以在kernel之前用一個bootloader來引導(為什麼開機不能直接執行kernel,所有事情都交給kernel做?),其思想類似于一個闆級支援包:kernel假定執行的時候已經具備了一個基本的硬體運作條件,這個環境的初始化(最底層的一些硬體初始化、硬體資訊設定)需要bootloader來完成,也許這樣kernel的設計才能保持一定的一緻性。

說到底,bootloader是一段裸機程式,是直接與硬體打交道的。① 它在系統上電後開始執行(PC系統中在bootloader之前有個BIOS固件,嵌入式系統中一般沒有),其最終目的是“初始化硬體裝置,準備好軟體環境,最後調用作業系統核心”。② 為了友善進行底層開發(比如調試核心等),bootloader增加了很多功能,主要有UART、網絡、USB、讀寫Flash(Nor or Nand)、解壓縮、LCD支援等等。

-------------------------------------------------------------------

通用概念

在一個嵌入式Linux系統中,從軟體的角度通常可以分為4個層次: 

(1)引導加載程式。

包括固化在固件(firmware)中的 boot 代碼(可選)和Bootloader兩大部分。 

有些CPU在運作Bootloader之前先運作一段固化的程式(固件,firmware),比如x86結構的CPU就是先運作BIOS中的固件,然後才運作硬碟第一個分區(MBR)中的Bootloader。 

在大多嵌入式系統中并沒有固件,Bootloader是上電後執行的第一個程式。 

(2)Linux核心。 

特定于嵌入式闆子的定制核心以及核心的啟動參數。核心的啟動參數可以是核心預設的,或是由Bootloader傳遞給它的。 

(3)檔案系統。 

包括根檔案系統和建立于Flash記憶體裝置之上的檔案系統。裡面包含了Linux系統能夠運作所必需的應用程式、庫等,比如可以給使用者提供操作Linux的控制界面的shell程式,動态連接配接的程式運作時需要的glibc或uClibc庫,等等。 

(4)使用者應用程式。 

特定于使用者的應用程式,它們也存儲在檔案系統中。有時在使用者應用程式和核心層之間可能還會包括一個嵌入式圖形使用者界面。常用的嵌入式 GUI 有:Qtopia 和 MiniGUI 等。 

----------------------------------------------------------------------

Bootloader的啟動方式 

CPU上電後,會從某個位址開始執行。比如MIPS結構的CPU會從0xBFC00000取第一條指令,而ARM結構的CPU則從位址0x0000000開始。嵌入式單闆中,需要把存儲器件ROM或Flash等映射到這個位址,Bootloader就存放在這個位址開始處,這樣一上電就可以執行。 

在開發時,通常需要使用各種指令操作Bootloader,一般通過序列槽來連接配接PC和開發闆,可以在序列槽上輸入各種指令、觀察運作結果等。這也隻是對開發人員才有意義,使用者使用産品時是不用接序列槽來控制Bootloader的。從這個觀點來看,Bootloader可以分為兩種操作模式(Operation Mode): 

(1)啟動加載(Boot loading)模式。 

上電後,Bootloader從闆子上的某個固态儲存設備上将作業系統加載到RAM中運作,整個過程并沒有使用者的介入。産品釋出時,Bootloader工作在這種模式下。 

(2)下載下傳(Downloading)模式。 

在這種模式下,開發人員可以使用各種指令,通過序列槽連接配接或網絡連接配接等通信手段從主機(Host)下載下傳檔案(比如核心映像、檔案系統映像),将它們直接放在記憶體運作或是燒入Flash類固态儲存設備中。 

闆子與主機間傳輸檔案時,可以使用序列槽的xmodem/ymodem/zmodem協定,它們使用簡單,隻是速度比較慢;還可以使用網絡通過tftp、nfs協定來傳輸,這時,主機上要開啟tftp、nfs服務;還有其他方法,比如USB等。 

像Blob或U-Boot等這樣功能強大的Bootloader通常同時支援這兩種工作模式,而且允許使用者在這兩種工作模式之間進行切換。比如,U-Boot在啟動時處于正常的啟動加載模式,但是它會延時若幹秒(這可以設定)等待終端使用者按下任意鍵而将U-Boot切換到下載下傳模式。如果在指定時間内沒有使用者按鍵,則U-Boot繼續啟動Linux核心。 

 Bootloader的兩個階段 

Bootloader的啟動過程啟動過程可以分為單階段(Single Stage)、多階段(Multi-Stage)兩種。通常多階段的Bootloader能提供更為複雜的功能,以及更好的可移植性。從固态儲存設備上啟動的Bootloader大多都是 2 階段的啟動過程。這從前面的硬體實驗可以很好地了解這點:第一階段使用彙編來實作,它完成一些依賴于 CPU 體系結構的初始化,并調用第二階段的代碼。第二階段則通常使用C語言來實作,這樣可以實作更複雜的功能,而且代碼會有更好的可讀性和可移植性。 

一般而言,這兩個階段完成的功能可以如下分類,但這不是絕對的: 

(1)Bootloader第一階段的功能。 

硬體裝置初始化。 

為加載Bootloader的第二階段代碼準備RAM空間。 

拷貝Bootloader的第二階段代碼到 RAM 空間中。 

設定好棧。 

跳轉到第二階段代碼的C入口點。 

在第一階段進行的硬體初始化一般包括:關閉WATCHDOG、關中斷、設定CPU的速度和時鐘頻率、RAM初始化等。這些并不都是必需的,比如S3C2410/S3C2440的開發闆所使用的U-Boot中,就将CPU的速度和時鐘頻率的設定放在第二階段。 

甚至,将第二階段的代碼複制到RAM空間中也不是必需的,對于NOR Flash等儲存設備,完全可以在上面直接執行代碼,隻不過這相比在RAM中執行效率大為降低。 

(2)Bootloader第二階段的功能。 

初始化本階段要使用到的硬體裝置。 

檢測系統記憶體映射(memory map)。 

将核心映像和根檔案系統映像從Flash上讀到RAM空間中。 

為核心設定啟動參數。 

調用核心。 

為了友善開發,至少要初始化一個序列槽以便程式員與Bootloader進行互動。

-------------------------------------------------------------------------

U-Boot工程簡介 

U-Boot,全稱為Universal Boot Loader,即通用Bootloader,是遵循GPL條款的開放源代碼項目。其前身是由德國DENX軟體工程中心的Wolfgang Denk基于8xxROM的源碼建立的PPCBOOT工程。後來整理代碼結構使得非常容易增加其他類型的開發闆、其他架構的CPU(原來隻支援PowerPC);增加更多的功能,比如啟動Linux、下載下傳S-Record格式的檔案、通過網絡啟動、通過PCMCIA/CompactFLash/ATA disk/SCSI等方式啟動。增加ARM架構CPU及其他更多CPU的支援後,改名為U-Boot。 

它的名字“通用”有兩層含義:可以引導多種作業系統、支援多種架構的CPU。它支援如下作業系統:Linux、NetBSD、 VxWorks、QNX、RTEMS、ARTOS、LynxOS等,支援如下架構的CPU:PowerPC、MIPS、x86、ARM、NIOS、XScale等。 

U-Boot有如下特性: 

開放源碼; 

支援多種嵌入式作業系統核心,如Linux、NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS; 

支援多個處理器系列,如PowerPC、ARM、x86、MIPS、XScale; 

較高的可靠性和穩定性; 

高度靈活的功能設定,适合U-Boot調試、作業系統不同引導要求、産品釋出等; 

豐富的裝置驅動源碼,如序列槽、以太網、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、鍵盤等; 

較為豐富的開發調試文檔與強大的網絡技術支援; 

支援NFS挂載、RAMDISK(壓縮或非壓縮)形式的根檔案系統 

支援NFS挂載、從FLASH中引導壓縮或非壓縮系統核心; 

可靈活設定、傳遞多個關鍵參數給作業系統,适合系統在不同開發階段的調試要求與産品釋出,尤對Linux支援最為強勁; 

支援目标闆環境變量多種存儲方式,如FLASH、NVRAM、EEPROM; 

CRC32校驗,可校驗FLASH中核心、RAMDISK鏡像檔案是否完好; 

上電自檢功能:SDRAM、FLASH大小自動檢測;SDRAM故障檢測;CPU型号; 

特殊功能:XIP核心引導; 

U-Boot的啟動過程源碼分析 

U-Boot屬于兩階段的Bootloader,第一階段的檔案為cpu/arm920t/start.S和board/smdk2410/lowlevel_init.S,前者是平台相關,後者是開發闆相關。 

U-Boot第一階段代碼分析 

它與前面描述的Bootloader第一階段所完成的功能可以一一對應: 

(1)硬體裝置初始化。 

依次完成如下設定:将CPU的工作模式設為管理模式(svc),關閉WATCHDOG,設定FCLK、HCLK、PCLK的比例(即設定CLKDIVN寄存器),關閉MMU、CACHE。 

(2)為加載Bootloader的第二階段代碼準備RAM空間。 

所謂準備RAM空間,就是初始化記憶體晶片,使它可用。

參考資源

U-boot百度百科:http://baike.baidu.com/view/1348254.htm

Bootloader百度百科:http://baike.baidu.com/view/1223454.htm

Bootloader(U-boot):http://hi.baidu.com/firstm25/item/5a716411073a414fe75e068d

Bootloader(U-boot)學習研究心得:http://www.cnblogs.com/andrew-wang/archive/2012/12/09/2810483.html

u-boot 移植步驟詳解:http://www.lisdn.com/html/38/n-10038.html

UBOOT和bootloader的關系:http://blog.sina.com.cn/s/blog_4c66653101000cda.html

繼續閱讀