uboot啟動核心

2021-09-24 09:25:18 字數 3346 閱讀 3762

uboot 映象為 uboot.bin,linux 映象為 zimage

嵌入式裝置中的分割槽表是自己定義的,uboot 和核心中的分割槽表應一致

核心執行前必須載入到 ddr 中指定的位址處

uboot 需要提供核心必要的引數

uboot 啟動核心有兩種方式,一種是等待倒計時結束後直接啟動核心,一種是在 uboot 命令列中使用 boot 命令啟動核心

其**分別如下

其中 parse_string_outer 的作用是解析 boot 引數並執行

/*------------------倒計時----------------------*/

s = getenv ("bootcmd");

if (bootdelay >= 0 && s && !abortboot (bootdelay))

/*------------------命令列----------------------*/

int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *ar**)

u_boot_cmd(

boot, 1, 1, do_bootd,

"boot - boot default, i.e., run 'bootcmd'\n",

null

);/*-----------------相關巨集定義----------------------*/

#ifdef config_bootargs

"bootargs=" config_bootargs "\0"

#endif

#ifdef config_bootcommand

"bootcmd=" config_bootcommand "\0"

#endif

#define config_bootargs "console=ttysac2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3"

#define config_bootcommand "movi read kernel 30008000; movi read rootfs 30b00000 300000; bootm 30008000 30b00000"

uboot 啟動核心的步驟

本文使用的開發板 x210 將映象存放在 sd 卡中,要載入到 ddr 中需要使用到 movi 指令

movi 提供了對 inand/sd 卡的操作,movi read 用來讀取 inand/sd 卡中的內容到ddr中;movi write 用來將ddr中的內容寫入到 inand/sd 卡中

上面的**中 bootcmd 中的命令就是用來載入 kernel rootfs 到 ddr

通過movi read kernel 30008000可以知道,核心載入到了 0x30008000 的位置

linux 直接編譯得到 elf 檔案,叫 vmlinux 或 vmlinuz。這種檔案會比較大,為了燒錄方便,會使用 objcopy 工具製作成映象檔案,叫 image(從78m精簡成了7.5m)

早期使用的軟盤比較小,image 對與軟盤來說還是太大了,放不下。linux 對 image 做進一步的壓縮,並在壓縮檔案前端附加了一部分解壓縮**,形成 zimage

uboot 可以使用 mkimage 工具,在 zimage 前面加上64位元組的uimage的頭資訊,形成 uimage

核心的載入啟動是通過 do_bootm 完成的

前面介紹過,映象檔案分為兩個部分,頭部以及真正的核心

所以 do_bootm 會先對映象進行頭部資訊的校驗,然後再進行核心的啟動

頭部資訊的結構體如下

typedef struct image_header  image_header_t;
在 do_bootm 中就是通過 ih_os 判斷映象的型別,然後使用相應的方法啟動核心

這裡的映象是 linux 映象,所以使用的是 do_bootm_linux, do_bootm_linux 的引數大部分是通過 do_bootm 傳遞的

啟動的引數bootm 30008000,告訴 uboot 去 30008000 這個位址去找映象檔案

映象的程式入口叫做 entrypoint ,在 do_bootm_linux 中使用 ep 儲存,映象的程式入口在頭資訊的 ih_ep 中,可以通過讀取頭資訊得到

得到 ep 後,通過thekernel = (void (*)(int, int, uint))ep;將 ep 格式化後傳遞給 thekernel ,這樣 thekernel 函式就指向了記憶體中載入的os映象的真正入口位址

前面也提到了,每個開發板在 uboot 中都有唯一的機器碼,這個編碼用來驗證開發板與 uboot 是否匹配,這個機器碼還會傳到核心中再次驗證。這個機器碼獲取的第一順序備選是環境變數machid,第二順序備選是gd->bd->bi_arch_num(x210_sd.h 中的 #define mach_type 2456)

接下來就是傳參的過程。先看看 linux 的 documentation/arm/booting 中對 cpu 暫存器設定的描述

- cpu register settings

r0 = 0,

r1 = machine type number discovered in (3) above.

r2 = physical address of tagged list in system ram, or

physical address of device tree block (dtb) in system ram

通過讀取 r0 r1 r2 這三個暫存器的值來設定 cpu ,r0 固定為0,r1 為前面提到的機器碼,r2 為存放啟動引數 tag 結構體的首位址

所以在 do_bootm_linux 通過thekernel (0, machid, bd->bi_boot_params);完成傳參的過程

傳參是通過 struct tag 這個結構體完成的,獲取引數就是獲取乙個個 tag 的過程。這些 tag 也有著規定的格式,do_bootm_linux 中通過 setup_start_tag 和 setup_end_tag 函式設定 tag 的開始和結束,這個函式的作用就是設定當前 tag 的型別為 atag_core 和 atag_none ,用作 tag 起始終止位置的判別

需要注意的是,傳參是乙個很重要的過程,核心啟動不成功與傳參錯誤有很大關係

第一步:將核心搬移到ddr中

第二步:校驗核心格式、crc等

第三步:準備傳參

第四步:跳轉執行核心

u-boot 啟動核心解析

uboot啟動核心

假設bootcmd nand read.jffs2 0x30007fc0 kernel bootm 0x30007fc0 1 nand read.jffs2 0x30007fc0 kernel nand read.jffs2 0x30007fc0 kernel 從nand讀出核心 從 讀?從kern...

uboot啟動核心

經過了前面的的一系列準備,終於要啟動核心了。在uboot分析二中,提到過下面的這個函式 void main loop void 在啟動核心的時候在uboot裡面用到什麼命令呢?bootcmd 命令 nand.read.jffs 0x30007f00 kernel 從nand的kernel 分割槽讀核...

uboot分析 uboot啟動核心

u boot啟動核心概述 u boot啟動完成後,最終進入到main loop 迴圈中。若在bootdelay倒計時為0之前,u boot控制台有輸入,則進入命令解析 執行的迴圈 若控制台無輸入,u boot將啟動核心。u boot啟動核心可歸結為以下四個步驟 1 將核心搬移至ddr中 2 校驗核心...