UBOOT引導Linux核心及向核心傳遞引數的方式

2021-07-10 01:30:05 字數 2329 閱讀 5380

一直以來沒有想過有什麼好的辦法通過暫存器向核心傳遞引數,直到今天讀uboot的實現方式。

在uboot中,引導核心最常用的方法是bootm命令,bootm命令可以引導「uboot格式」的核心。先花點時間了解一下什麼是「uboot格式」的核心吧:用uboot自帶的mkimage命令生成的核心稱為"uboot"格式的核心。以下面這條命令為例:

mkimage -n "kernel 2.4.18" -a arm -o linux -t kernel -c none -a 30007fc0 -e 30008000 -d 4020.bin vmlinux-2.4.18.img

其中與核心引導最密切的是-e 30008000,也就是核心的入口位址。其它引數可以參考幫助資訊。其它uboot格式的核心與原來相比,只是進行(可選)了壓縮,並在前面加了乙個0x40大小的頭。這個頭里放了核心的位置(0x30007fc0)和入口位址(0x30008000)和其它資訊。

bootm命令執行時,先對頭部資訊等進行校驗,然後把頭資訊放到乙個結構裡面。最後根據核心型別呼叫相應的啟動函式。對於linux而言就是do_bootm_linux,在啟動函式裡面,有這麼乙個操作:

thekernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);,這是最關鍵的乙個操作,將核心的入口位址0x30008000賦給了thekernel,在啟動函式的最後,使用

thekernel (0, bd->bi_arch_number, bd->bi_boot_params);啟動核心。

根據傳參規範,三個變數分別用r0,r1,r2傳給核心,這樣就巧妙地利用了函式指標進行了引數傳遞,實在是精妙!

上面講完了核心的引導及傳參,需要引起注意的就是在使用mkimage命令生成核心時,-e後面的位址要比-a後面的位址偏移0x40,原因很簡單,就不在細說了。

上面提到,bootloader巧妙地利用函式指標及傳參規範將r0:0x0,r1:機器號,r2:引數位址傳遞給核心.由於r0,r1比較簡單,不需要再作說明.需要花點時間了解的是r2暫存器.

r2暫存器傳遞的是乙個指標,這個指標指向乙個tag區域.uboot和linux核心之間正是通過這個擴充套件了的tag區域來進行複雜引數的傳遞,如command line,檔案系統資訊等等,使用者也可以擴充套件這個tag來進行更多引數的傳遞.tag區域存放的位址,也就是r2的值,是在/board/yourboard/youboard.c裡的board_init函式中初始化的,如在ub4020中初始化為:gd->bd->bi_boot_params = 0x30000100;,這是乙個絕對位址.

tag區的結構比較簡單,可以視為乙個乙個tag的排列(陣列?),每乙個tag傳遞一種特定型別的引數.各種系統tag的定義可以參考./include/asm-arm/setup.h.

下面是乙個tag區的例子:

0x30000100  00000005 54410001 00000000 00000000 

0x30000110  00000000 0000000f 54410009 746f6f72 

0x30000120  65642f3d 61722f76 7220306d 6f632077 

0x30000130  6c6f736e 74743d65 2c305379 30303639 

0x30000140  696e6920 6c2f3d74 78756e69 ea006372 

0x30000150  00000004 54420005 30300040 00200000 

0x30000160  00000000 00000000 

我們可以看到一共有三個tag:

第乙個tag的長度是5個字,型別是atag_core(54410001),有三個元素,均為全零.tag區必須以這個tag開頭.

第二個tag的長度是f個字,型別是atag_cmdline(54410009),這是乙個字串,是向核心傳遞的kernel command line

第三個tag的長度是4個字,型別是atag_initrd2(54410005),有兩個元素,第乙個是start:30300040(30300000+40),第二個是size:200000(2m)

如果說還有第四個tag,那就是末尾的兩個全零,這是tag結束的標誌.

這些tag是在./lib_arm/arm_linux.c中的do_bootm_linux函式中建立起來的.具體建立哪些tag,由相應的控制巨集決定.具體可以參考相應**.例子中第乙個tag是起始tag,如果環境變數中有bootargs,則建立第二個tag,如果bootm有兩個引數(引導檔案系統),則會讀取檔案系統頭部的必要資訊,建立第三個tag.

核心啟動後,將根據r2暫存器的值找到這些tag,並根據tag型別,呼叫相應的處理函式進行處理,從而獲取核心執行的必要資訊.

UBOOT引導Linux核心及向核心傳遞引數的方式

一直以來沒有想過有什麼好的辦法通過暫存器向核心傳遞引數,直到今天讀uboot的實現方式。在uboot中,引導核心最常用的方法是bootm命令,bootm命令可以引導 uboot格式 的核心。先花點時間了解一下什麼是 uboot格式 的核心吧 用uboot自帶的mkimage命令生成的核心稱為 ubo...

u boot引導核心及引數傳導

uboot實現了傳遞dtb的功能,define config of libfdt使能裝置樹 i.mx6ul實現方式 if defined config sys boot nand define config extra env settings config mfg env settings pan...

記錄u boot不能引導核心的解決過程

問題還沒有解決,記錄一下吧。一發來郵件求助,說是移植的u boot啟動不了核心,是2013.7版本的,移植到s5pv210上的。我之前移植的2013.1版本的沒有問題的。一開始覺得不是什麼事,從以下幾個方面查了 a.傳引數 機器碼 b.記憶體初始化 c.檢查拷貝到記憶體中的kernel是否完整 但是...