【Linux】嵌入式Linux系統(tǒng)的移植(下篇:BootLoader,以U-Boot為例)

姓名:鄧皓軒? 學(xué)號(hào):19020100151? 學(xué)院:丁香2號(hào)書院

轉(zhuǎn)自:https://yngzmiao.blog.csdn.net/article/details/90243257

【嵌牛導(dǎo)讀】嵌入式Linux系統(tǒng)移植

【嵌牛鼻子】介紹嵌入式Linux系統(tǒng)移植的要點(diǎn)

【嵌牛提問】怎樣進(jìn)行嵌入式Linux系統(tǒng)移植

BootLoader

BootLoader的概念

BootLoader就是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。通過這段小程序,可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境,這就是所謂的引導(dǎo)加載程序(Boot Loader)。

在Flash存儲(chǔ)中存放文件的分布圖如下所示:


歸根結(jié)底,BootLoader的任務(wù)是引導(dǎo)操作系統(tǒng),所謂引導(dǎo)操作系統(tǒng),就是啟動(dòng)內(nèi)核,把內(nèi)核加載到內(nèi)存RAM中去運(yùn)行。

本文中,BootLoader的起始地址為0x20000000,內(nèi)核(uImage)的起始地址為0x20008000,根文件系統(tǒng)(initrd.img.gz)的起始地址為0x21000000。

BootLoader的分類

通常,BootLoader是嚴(yán)重地依賴于硬件而實(shí)現(xiàn)的,特別是在嵌入式中。因此,在嵌入式里建立一個(gè)通用的BootLoader幾乎是不可能的。因此,BootLoader的種類繁多,

可以看出,不同的bootloader具有不同的使用范圍。

其中最令人矚目的就是有一個(gè)叫U-Boot的BootLoader,是一個(gè)比較通用的引導(dǎo)程序,而且同時(shí)支持X86、ARM和PowerPC等多種處理器架構(gòu)。

U-Boot

U-Boot,全稱 Universal Boot Loader,是遵循GPL條款的開放源碼項(xiàng)目,是由德國DENX小組開發(fā)的用于多種嵌入式CPU的BootLoader程序,對于Linux的開發(fā),德國的u-boot做出了巨大的貢獻(xiàn),而且是開源的。

U-Boot具有以下特點(diǎn):

開放源碼;

支持多種嵌入式操作系統(tǒng)內(nèi)核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;

支持多個(gè)處理器系列,如PowerPC、ARM、x86、MIPS、XScale;

較高的可靠性和穩(wěn)定性;

高度靈活的功能設(shè)置,適合U-Boot調(diào)試、操作系統(tǒng)不同引導(dǎo)要求、產(chǎn)品發(fā)布等;

豐富的設(shè)備驅(qū)動(dòng)源碼,如串口、以太網(wǎng)、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、鍵盤等;

較為豐富的開發(fā)調(diào)試文檔與強(qiáng)大的網(wǎng)絡(luò)技術(shù)支持;

其實(shí),把u-boot可以理解為是一個(gè)小型的操作系統(tǒng)。

U-Boot的常用命令

U-Boot的文件通過SD卡或者USB線可直接燒寫到Flash中,然后就可以進(jìn)行U-Boot的命令的執(zhí)行了。

U-Boot的基本命令

print:打印U-Boot中的環(huán)境變量(打印格式:變量名=變量值)

setenv:設(shè)置U-Boot中的環(huán)境變量,重啟后無效(設(shè)置格式:setenv 變量名 變量值;當(dāng)變量值為空的時(shí)候,表示刪除該環(huán)境變量)

saveenv:保存U-Boot中的環(huán)境變量,重啟后有效

md:內(nèi)存顯示,顯示特定內(nèi)存地址的內(nèi)容(設(shè)置格式:md 內(nèi)存地址,如20008000)

U-Boot網(wǎng)絡(luò)層相關(guān)命令

一般而言,將文件(例如:內(nèi)核)從主板傳輸?shù)侥繕?biāo)板采用TFTP協(xié)議,這就涉及到U-Boot的網(wǎng)絡(luò)層設(shè)置。而U-Boot的網(wǎng)絡(luò)層的設(shè)置與環(huán)境變量ipaddr有關(guān):

setenv ipaddr 192.168.10.3

saveenv

需要注意的是,該ip地址需要和虛擬機(jī)的網(wǎng)卡地址在同一網(wǎng)段,即需要Ping通(U-Boot為了精簡,Ping協(xié)議并不完全,必須由目標(biāo)板去Ping主機(jī)虛擬機(jī))。這樣才能完成目標(biāo)板與主板虛擬機(jī)的網(wǎng)絡(luò)層的通暢。

Ping通之后,就可以通過TFTP進(jìn)行文件傳輸了。由于U-Boot內(nèi)有TFTP的客戶端,因此服務(wù)器端有兩種可能:

主板:下載TFTPD軟件,設(shè)置目錄并選擇網(wǎng)卡

主板虛擬機(jī):下載服務(wù)器端軟件,命令如下:

sudo apt-get install tftpd-hpa //32位

sudo apt-get install tftpd openbsc-xinetd //64位

然后TFTP的目錄配置文件在/etc/inetd.conf中,比如:

sudo vi /etc/inetd.conf

...

tftp dgram udp wait noboby /usr/sbin/tcpd /usr/sbin/in.tftpd [目錄]

...

sudo /etc/init.d/tftpd-hpa/restart //重啟服務(wù)

目標(biāo)板進(jìn)行TFTP需要知曉服務(wù)器端的ip地址、端口號(hào)、傳輸?shù)降膬?nèi)存地址和需要傳輸?shù)膬?nèi)容。服務(wù)器端的ip地址在環(huán)境變量serverip,端口號(hào)是TFTP規(guī)定好的(69號(hào)端口),剩下的兩個(gè)參數(shù)就是tftp命令需要指定的:

tftp 20008000 hello.c

這段命令的意思為,從環(huán)境變量serverip的服務(wù)器端將hello.c文件通過TFTP協(xié)議傳輸?shù)侥繕?biāo)板內(nèi)存地址為20008000的內(nèi)存中。

U-Boot Flash相關(guān)命令

當(dāng)調(diào)試完程序后,最終需要將其寫入NandFlash中,否則程序仍在內(nèi)存中,一旦重啟就會(huì)消失。這就需要用到nand命令了。其一般格式為:

nand erase [NandFlash內(nèi)部地址] [擦除大小]

nand [write/read] [內(nèi)存地址] [NandFlash內(nèi)部地址] [搬移大小]

通常,在使用write之前都需要先進(jìn)行erase命令。例如:

nand erase 500000 1024 //擦除Flash5M地址1字節(jié)的內(nèi)容

nand write 20008000 500000 1024 //將內(nèi)存20008000以后1字節(jié)的內(nèi)容寫入Flash5M地址

nand read 20008000 500000 1024 //將Flash5M地址以后1字節(jié)的內(nèi)容讀取到內(nèi)存20008000

這樣就能保證,目標(biāo)板重啟之后數(shù)據(jù)也不會(huì)丟失了。

U-Boot啟動(dòng)內(nèi)核命令

bootm命令用于啟動(dòng)一個(gè)操作系統(tǒng)映像。它會(huì)從內(nèi)核映像文件(uImage)的頭部取得一些信息,這些信息包括:映像文件的基于的cpu架構(gòu)、其操作系統(tǒng)類型、映像的類型、壓縮方式、映像文件在內(nèi)存中的加載地址、映像文件運(yùn)行的入口地址、映像文件名等。

緊接著bootm命令將映像加載到指定的地址,如果需要的話,還會(huì)解壓映像并傳遞必要有參數(shù)給內(nèi)核,最后跳到入口地址進(jìn)入內(nèi)核。

U-Boot啟動(dòng)內(nèi)核,需要滿足一定的條件:

啟動(dòng)參數(shù) bootargs

根文件系統(tǒng)

啟動(dòng)參數(shù)bootargs,一般包括以下三項(xiàng):

root=:啟動(dòng)的根文件系統(tǒng)的位置相關(guān)信息

init=:內(nèi)核啟動(dòng)后的第一個(gè)可執(zhí)行文件,即init進(jìn)程

console=:內(nèi)核啟動(dòng)后,作為控制臺(tái)的設(shè)備

根文件系統(tǒng)一般有兩種方式:Ramdisk、NFS。

Ramdisk:顧名思義內(nèi)存磁盤,即將根文件系統(tǒng)放在內(nèi)存中。本質(zhì)上,RamDisk并非一個(gè)實(shí)際的文件系統(tǒng),而是一種將實(shí)際的文件系統(tǒng)裝入內(nèi)存的機(jī)制,并且可以作為根文件系統(tǒng)。實(shí)際上它使用的文件系統(tǒng)是ext2。

此時(shí)的配置需要指定root的位置在RAM,同時(shí)還需要指定RAM中的具體位置和大小,啟動(dòng)參數(shù)為:

setenv bootargs root=/dev/ram initrd=0x21000000,8M init=/linuxrc console=ttySAC0,115200

saveenv

確定完啟動(dòng)參數(shù)之后,就可以傳輸文件,并進(jìn)行內(nèi)核啟動(dòng)了,使用bootm命令:

tftp 20008000 uImage

tftp 21000000 initrd.img.gz

bootm 20008000

NFS:顧名思義網(wǎng)絡(luò)文件系統(tǒng)。即允許網(wǎng)絡(luò)中的計(jì)算機(jī)之間通過TCP/IP網(wǎng)絡(luò)共享資源。在NFS的應(yīng)用中,本地NFS的客戶端應(yīng)用可以透明地讀寫位于遠(yuǎn)端NFS服務(wù)器上的文件,就像訪問本地文件一樣。這種方式,對于調(diào)試就非常方便。

簡單一點(diǎn)說,就是將根文件系統(tǒng)放在主板的虛擬機(jī)上,目標(biāo)板通過NFS來進(jìn)行訪問。那么,顯而易見,主板的虛擬機(jī)需要安裝NFS的服務(wù)器端。

sudo apt-cache search nfs- //記不得名稱了可以用此命令搜索

sudo apt-get install nfs-kernel-server

安裝完成后,需要進(jìn)行NFS的配置,配置文件在/etc/exports中:

sudo vi /etc/exports

...

[目錄] *(rw,sync,no_subtree_check)

...

sudo /etc/init.d/nfs-kernel-server restart //重啟服務(wù)

需要注意的是,根文件系統(tǒng)的后綴為.gz,是一個(gè)壓縮包。當(dāng)通過TFTP傳輸給目標(biāo)板之后,目標(biāo)板會(huì)自動(dòng)對其進(jìn)行解壓操作,形成相應(yīng)的文件夾。然而,如果采用NFS的方式,服務(wù)器端需要自身解壓完,留給目標(biāo)板進(jìn)行訪問:

gunzip initrd.img.gz //解壓為initrd.img,相當(dāng)于一個(gè)ios文件

mount -t ext2 init.img [掛載目錄] //掛載initrd.img

服務(wù)器端配置完成后,目標(biāo)板的配置需要指定root的位置在NFS,同時(shí)還需要指定NFS中的具體ip、端口和目錄絕對地址,端口號(hào)是NFS規(guī)定好的。

除此之外,U-Boot一旦啟動(dòng)內(nèi)核之后,它就喪失了對目標(biāo)板的主動(dòng)權(quán),此時(shí)它的環(huán)境變量ipaddr也喪失作用了。這個(gè)時(shí)候,目標(biāo)板就是屬于無ip的狀態(tài),自然NFS就無法連接上了。因此,還需要設(shè)置ip參數(shù)。啟動(dòng)參數(shù)為:

setenv bootargs root=/dev/nfs nfsroot=192.168.10.110:/home/rocky/work/rootfs ip=192.168.10.120 init=/linuxrc console=ttySAC0,115200

saveenv

確定完啟動(dòng)參數(shù)之后,就可以傳輸文件,并進(jìn)行內(nèi)核啟動(dòng)了,使用bootm命令:

tftp 20008000 uImage

bootm 20008000

采用NFS方式的好處就是,可以在主板虛擬機(jī)上寫一個(gè)程序,并運(yùn)用交叉編譯器進(jìn)行編譯,編譯完成后,自動(dòng)就會(huì)同步到目標(biāo)板上。這個(gè)時(shí)候,就可以直接在目標(biāo)板上運(yùn)行編譯完的程序。即主板虛擬機(jī)編譯,目標(biāo)板運(yùn)行!

U-Boot自動(dòng)啟動(dòng)內(nèi)核命令

可以看出,上面的兩種啟動(dòng)內(nèi)核的方式都不能做到一上電就自動(dòng)啟動(dòng)內(nèi)核的作用。其實(shí)這都和U-Boot的環(huán)境變量有關(guān):bootdelay、bootcmd。前者為啟動(dòng)后倒計(jì)時(shí),后者為倒計(jì)時(shí)后自動(dòng)執(zhí)行的命令。

就可以將內(nèi)核、根文件系統(tǒng)都nand到Flash中,倒計(jì)時(shí)后從Flash中讀取并啟動(dòng)內(nèi)核:

setenv bootdelay 2

setenv bootcmd nand read 20008000 100000 200000;nand read 21000000 5600000 400000;bootm 20008000

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容