bootm命令分析

2021-05-26 13:25:54 字數 3233 閱讀 5868

bootm命令函式do_bootm位於cmd_bootm.c,其流程為:

確定是否要校驗uimage和ramdisk裡的資料,預設校驗,若想不校驗:設定了環境變數verify=n。

s = getenv ("verify");

verify = (s && (*s == 'n')) ? 0 : 1;

判斷命令是否制定了 作業系統 的載入位址。如果沒有,使用預設位址cfg_load_addr,一般cfg_load_addr可以在include/configs資料夾自己單板的配置檔案裡配置。

if (argc < 2) else

根據image 載入位址是在 flash還是記憶體,獲取image的 頭資訊。

#ifdef config_has_dataflash

if (addr_dataflash(addr)) else

#endif

memmove (&header, (char *)addr, sizeof(image_header_t));

校驗頭里的magic num和crc是否正確,頭部的crc計算內容是 :頭部64b,且頭部crc處按內容0來計算。

if (ntohl(hdr->ih_magic) != ih_magic) });

.............................................

if (crc32 (0, (uchar *)data, len) != checksum)

根據image type進行不同的處理,如果是linux kernel後面再處理:

switch (hdr->ih_type)

判斷壓縮型別,做不同拷貝處理。

未壓縮:

如果映象中load位址與第乙個引數一致的話,意思是核心已經在loadaddr準備好了,無需處理。

如果映象中load位址與第乙個引數不一致的話,就要從傳遞的位址拷貝到 image指定的loadaddr(hdr->ih_load)了。

如果是壓縮型別gzip或者bzip2:

就呼叫相應解壓縮函式,將映象解壓到image指定的loadaddr(hdr->ih_load)了。預設預留解壓後的大小為8m。當然這個空間大小可以使用這個巨集定義cfg_bootm_len來修改

switch (hdr->ih_comp) else

#else /* !(config_hw_watchdog || config_watchdog) */

memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);

#endif /* config_hw_watchdog || config_watchdog */

}break;

case ih_comp_gzip:

printf ("   uncompressing %s ... ", name);

if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,

(uchar *)data, &len) != 0)

break;

.............................................

}判斷如果是核心,暫時不用處理

switch (hdr->ih_type) {

.............................................

case ih_type_kernel:

case ih_type_multi:

/* handled below */

break;

根據映象的不同型別,呼叫不同的作業系統啟動函式。

switch (hdr->ih_os) {

default:   /* handled by (original) linux case */

case ih_os_linux:

#ifdef config_silent_console

fixup_silent_linux();

#endif

do_bootm_linux  (cmdtp, flag, argc, argv,

addr, len_ptr, verify);

break;

如果linux作業系統就呼叫do_bootm_linux ,其流程為:

如果定義了config_cmdline_tag,就從環境變數取出bootargs,準備傳引數給核心。#ifdef config_cmdline_tag

char *commandline = getenv ("bootargs");

#endif

從映象檔案的頭里提取entry point,即核心的入口位址。

thekernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);

確認命令是否傳遞了initrd位址,如果有進行相應的處理

校驗ramdisk的magic num和頭的crc

列印頭並校驗資料crc

/** check if there is an initrd image

*/if (argc >= 3) {

根據配置,準備向核心傳遞相應的引數。

setup_end_tag (bd);

#endif

關閉cache和中斷,啟動核心。

bd->bi_boot_params:傳遞給核心引數位址。tag型別

bd->bi_arch_number:cpu型別

在各自單板的board_init函式中初始化。

cleanup_before_linux ();

thekernel (0, bd->bi_arch_number, bd->bi_boot_params);

四十二 移植bootm命令

2 加上了原版u boot裡dm9000傳送函式裡傳送前後都要清除傳送標誌 3 取消了老師說的要對包進行判斷,實際上不判斷效果還要好一點,那一部分,要求只要在空讀前後有20微妙的時間間隔就好了,經我實際測試,我的開發板確實只用空讀一次就滿足該條件。4 取消了中斷處理函式裡之前為了驗證進的是什麼中斷的...

通過移植bootm命令啟動已經編譯好

首先在移植bootm命令之前,我們要了解bootloader的主要作用 除了初始化cpu和外設外,bootloader還有乙個最大的作用就是啟動linux核心。但是在啟動linux核心之前,有幾個部分是必須先初始化的 1.初始化記憶體 2.初始化串列埠 其實也不是必須的,但可以方便看輸出,檢查錯誤 ...

SQLite VACUUM命令分析

vacuum命令是sqlite的乙個擴充套件功能,模仿postgresql中的相同命令而來。若呼叫vacuum帶乙個表名或索引名,則將整理該錶或索引。在sqlite 1.0中,vacuum命令呼叫 gdbm reorganize 整理後端資料庫檔案。sqlite 2.0.0中去掉了gdbm後端,va...