uboot 屬於bootloader的一種,是用來引導啟動內核的,它的最終目的就是,從flash中讀出內核,放到內存中,啟動內核
所以,由上面描述的,就知道,UBOOT需要具有讀寫flash的能力。
uboot是怎樣引導啟動內核的?
uboot剛開始被放到flash中,板子上電后,會自動把其中的一部分代碼拷到內存中執行,這部分代碼負責把剩余的uboot代碼拷到內存中,然后uboot代碼再把kernel部分代碼也拷到內存中,並且啟動,內核啟動后,掛着根文件系統,執行應用程序。
uboot啟動的大過程是怎么樣的?
uboot啟動主要分為兩個階段,主要在start.s文件中,第一階段主要做的是硬件的初始化,包括,設置處理器模式為SVC模式,關閉看門狗,屏蔽中斷,初始化sdram,設置棧,設置時鍾,從flash拷貝代碼到內存,清除bss段等,bss段是用來存儲靜態變量,全局變量的,然后程序跳轉到start_arm_boot函數,宣告第一階段的結束。
第二階段比較復雜,做的工作主要是1.從flash中讀出內核。2.啟動內核。start_arm_boot的主要流程為,設置機器id,初始化flash,然后進入main_loop,等待uboot命令,uboot要啟動內核,主要經過兩個函數,第一個是s=getenv("bootcmd"),第二個是run_command(s...),所以要啟動內核,需要根據bootcmd環境變量的內容啟動,bootcmd環境變量一般指示了從某個flash地址讀取內核到啟動的內存地址,然后啟動,bootm。
uboot啟動的內核為uImage,這種格式的內核是由兩部分組成:真正的內核和內核頭部組成,頭部中包括內核中的一些信息,比如內核的加載地址,入口地址。
uboot在接受到啟動命令后,要做的主要是,1,讀取內核頭部,2,移動內核到合適的加載地址,3,啟動內核,執行do_bootm_linux
do_bootm_linux主要做的為,1,設置啟動參數,在特定的地址,保存啟動參數,函數分別為setup_start_tag,setup_memory_tag,setup_commandline_tag,setup_end_tag,根據名字我們就知道具體的段內存儲的信息,memory中為板子的內存大小信息,commandline為命令行信息,
2,跳到入口地址,啟動內核
啟動的函數為the_kernel(0,bd->bi_arch_number,bd->bi_boot_param)
bd->bi_arch_number為板子的機器碼,bd->bi_boot_param為啟動參數的地址
總結:uboot到底是干嘛的,對應下面uboot必須要解決哪些問題!
1)uboot主要作用是用來啟動操作系統內核。體現在uboot最后一句代碼就是啟動內核。
2)uboot還要負責部署整個計算機系統。體現在uboot最后的傳參。
3)uboot中還有操作Flash等板子上硬件的驅動。例如串口要打印,ping網絡成功,擦除、燒寫flash是否成功等。
4)uboot還得提供一個命令行界面供人來操作。很簡單,至少你能看到。
計算機系統的組成部件非常多,不同的計算機系統組成部件也不同。但是所有的計算機系統運行時需要的主要核心部件都是3個東西:CPU + 外部存儲器(Flash/硬盤) + 內部存儲器(DDR SDRAM/SDRAM/SRAM)。而一般的PC機啟動過程為:PC上電后先執行BIOS程序(實際上PC的BIOS就是NorFlash),BIOS程序負責初始化DDR內存,負責初始化硬盤,然后從硬盤上將OS鏡像讀取到DDR中,然后跳轉到DDR中去執行OS直到啟動(OS啟動后BIOS就無用了)。
嵌入式系統和PC機的啟動過程幾乎沒有兩樣,只是BIOS成了uboot,硬盤成了Flash。
3 uboot必須解決哪些問題?
3.1自身可開機直接啟動
1)一般的SoC都支持多種啟動方式,譬如SD卡啟動、NorFlash啟動、NandFlash啟動等•••••uboot要能夠開機啟動,必須根據具體的SoC的啟動設計來設計uboot
2)uboot必須進行和硬件相對應的代碼級別的更改和移植,才能夠保證可以從相應的啟動介質啟動。uboot中第一階段的start.S文件中具體處理了這一塊。
3.2能夠引導操作系統內核啟動並給內核傳參
1)uboot的終極目標就是啟動內核。
2)linux內核在設計的時候,設計為可以被傳參。也就是說我們可以在uboot中事先給linux內核准備一些啟動參數放在內存中特定位置然后傳給內核,內核啟動后會到這個特定位置去取uboot傳給他的參數,然后在內核中解析這些參數,這些參數將被用來指導linux內核的啟動過程。
3.3能提供系統部署功能
1)uboot必須能夠被人借助而完成整個系統(包括uboot、kernel、rootfs等的鏡像)在Flash上的燒錄下載工作。
2)裸機教程中刷機(ARM裸機第三部分)就是利用uboot中的fastboot功能將各種鏡像燒錄到iNand中,然后從iNand啟動。
3.4 能進行soc級和板級硬件管理
1)uboot中實現了一部分硬件的控制能力(uboot中初始化了一部分硬件),因為uboot為了完成一些任務必須讓這些硬件工作。譬如uboot要實現刷機必須能驅動iNand,譬如uboot要在刷機時LCD上顯示進度條就必須能驅動LCD,譬如uboot能夠通過串口提供操作界面就必須驅動串口。譬如uboot要實現網絡功能就必須驅動網卡芯片。
2)SoC級(譬如串口)就是SoC內部外設,板級就是SoC外面開發板上面的硬件(譬如網卡、iNand)
3.5 uboot的"生命周期"
1)uboot的生命周期就是指:uboot什么時候開始運行,什么時候結束運行。
2)uboot本質上是一個裸機程序(不是操作系統),一旦uboot開始SoC就會單純運行uboot(意思就是uboot運行的時候別的程序是不可能同時運行的),一旦uboot結束運行則無法再回到uboot(所以uboot啟動了內核后uboot自己本身就死了,要想再次看到uboot界面只能重啟系統。重啟並不是復活了剛才的uboot,重啟只是uboot的另一生)
3)uboot的入口和出口。uboot的入口就是開機自動啟動,uboot的唯一出口就是啟動內核。uboot還可以執行很多別的任務(譬如燒錄系統),但是其他任務執行完后都可以回到uboot的命令行繼續執行uboot命令,而啟動內核命令一旦執行就回不來了。
總結:uboot的一切都是為了啟動內核。
5 uboot的工作方式
5.1 從裸機程序鏡像uboot.bin說起
1)uboot的本質就是一個裸機程序,和我們裸機全集中寫的那些裸機程序xx.bin並沒有本質區別。如果非說要有區別,那就是:我們寫的大部分小於16KB,而uboot大於16KB(一般uboot在180k-400k之間)
2)uboot本身是一個開源項目,由若干個.c文件和.h文件組成,配置編譯之后會生成一個uboot.bin,這就是uboot這個裸機程序的鏡像文件。然后這個鏡像文件被合理的燒錄到啟動介質中拿給SoC去啟動。也就是說uboot在沒有運行時表現為uboot.bin,一般躺在啟動介質中。
3)uboot運行時會被加載到內存中然后一條指令一條指令的拿給CPU去運行。
5.2 uboot的命令式shell界面
1)普通的裸機程序運行起來就直接執行了,執行時效果和代碼有關。
2)有些程序需要和人進行交互,於是乎程序中就實現了一個shell(shell就是提供人機交互的一個界面,回想ARM裸機全集第十六部分),uboot就實現了一個shell。
注意:shell並不是操作系統,和操作系統一點關系都沒有。linux中打開一個終端后就得到了一個shell,可以輸入命令回車執行。uboot中的shell工作方式和linux中的終端shell非常像(其實幾乎是一樣的,只是命令集不一樣。譬如linux中可以ls,uboot中ls就不識別)。
4.3掌握uboot使用的2個關鍵點:命令和環境變量
1)uboot啟動后大部分時間和工作都是在shell下完成的(譬如uboot要部署系統要在shell下輸命令、要設置環境變量也得在命令行地下,要啟動內核也要在命令行底下敲命令)。
2)命令就是uboot的shell中可以識別的各種命令。uboot中有幾十個命令,其中有一些常用另一些不常用(我們還可以自己給uboot添加命令),后面會用幾節課時間來依次學習uboot中常用命令。
3)uboot的環境變量和操作系統的環境變量工作原理和方式幾乎完全相同。uboot在設計時借助了操作系統的設計理念(命令行工作方式借鑒了linux終端命令行,環境變量借鑒了操作系統的環境變量,uboot的驅動管理幾乎完全照抄了linux的驅動框架)。
4)環境變量可以被認為是系統的全局變量,環境變量名都是系統內置的(認識就認識,不認識就不認識,這部分是系統自帶的默認的環境變量,譬如PATH;但是也有一部分環境變量是自己添加的,自己添加的系統就不認識但是我們自己認識)。系統或者我們自己的程序在運行時可以通過讀取環境變量來指導程序的運行。這樣設計的好處就是靈活,譬如我們要讓一個程序更改運行方法,不用去重新修改程序代碼再重新編譯運行,而只要修改相應的環境變量就可以了。
5)環境變量就是運行時的配置屬性。