u-boot 內核引導與添加指令


1.Uboot:Start.s -> start_armboot ()<./lib_arm/board.c>  ->  main_loop ()<./common/main.c>
       main_loop()會調用abortboot (bootdelay)判斷在delay time內有沒有鍵按下,並給出prompt“Hit any key to stop autoboot”,若沒有鍵按下則run_command (s, 0)(s為默認的bootcmd)。這里默認的bootcmd需要根據內核的位置設置,若bootcmd未賦值,Uboot就會一直等待。如果敲入bootm,也會啟動kernel,並且傳入參數。如果使用tftp從pc中下載kernel並啟動也是可以的。

2.添加u-boot命令。也就是在進入main_loop()函數后,在等待的時間里可以識別的命令。

需要修改5個地方:

  1. /include/config_cmd_all.h    添加CONFIG_CMD_NANDBOOT宏
  2. /include/config_cmd_default.h  同上
  3. /include/configs/SEP0611.h  添加宏   (以上頭文件的修改,都是為了條件編譯做准備的)
  4. /common/cmd_nandboot.c   自己定義的命令   具體實現命令的函數   (命令的實現與命令的注冊都在這兒)
  5. /common/Makefile   把自己寫的實現命令文件添加到Makefile中,(參加編譯需要配置一下) 

最主要的還是自己寫的命令實現文件。

那么為什么要修改這幾個文件呢?下面先分析一下正常的執行過程:

對應的函數執行過程是:

其中main_loop() run_command() 都在comman/main.c中,而find_cmd(),find_cmd_tbl()是在common/command.c中的。

1)實現命令的具體功能,在comman文件夾中建立對應的.c文件。

2)如果要添加指令,首先為了能讓系統找到該指令,所以要在命令表中注冊一下。

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

  ##”與“#”都是預編譯操作符,“##”有字符串連接的功能,“#”表示后面緊接着的是一個字符串。

#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))

其中,unused表示該函數或變量可能不使用,這個屬性可以避免編譯器產生警告信息。

凡通過U_BOOT_CMD定義的cmd_tbl_t變量會全部被放在.u_boot_cmd段當中。這也是在你寫的.c文件的末尾必須要寫的,為了完成注冊這個動作。

比如說:U_BOOT_CMD(nandboot,0,0,do_nandboot,"boot from nand","--help")  通過宏展開就是:

cmd_tbl_t  __u_boot_cmd_nandboot  __attribute__((unused, section(".u_boot_cmd"))) = {"nandboot", 0, 0, do_nandboot, "boot from nand","--help"}

 

struct cmd_tbl_s {

       char              *name;          /* 命令名*/

       int          maxargs;       /* 最大參數個數*/

       int          repeatable;    /* 是否自動重復*/

       int          (*cmd)(struct cmd_tbl_s *, int, int, char *[]);  /*  響應函數*/

       char              *usage;         /* 簡短的幫助信息*/

#ifdef    CONFIG_SYS_LONGHELP

       char              *help;           /*  較詳細的幫助信息*/

#endif

#ifdef CONFIG_AUTO_COMPLETE

       /* 自動補全參數*/

       int          (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);

#endif

};

 

所謂注冊就是把一個特定命令的信息填在這個結構體中,然后把這個結構體放到一個表中,用於查找和跳轉。

 

 

#include <common.h>
#include <command.h>

#if defined(CONFIG_CMD_NANDBOOT)
int do_bootfromnand (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{


    printf ("## you are using command nandboot\n");
        run_command("nand read 0x40008000 0x400000 0x300000",0);
        run_command("bootm 0x40008000",0);
    return 0;
}
#endif
/* -------------------------------------------------------------------- */

U_BOOT_CMD(
    nandboot, CONFIG_SYS_MAXARGS, 1,    do_bootfromnand,
    "boot from nand",
    "boot from nand"
);


 


bootm命令執行過程解析:

 

當你輸入bootm命令的時候,最終執行的就是do_bootm()函數。

執行過程大體是這樣的:先到ram內存中kernel所在位置(uboot從nandflash中拷貝過來的),找到uImage的header,header中保存了很多關於鏡像的信息,用一個結構體來保存的,這個header一共占64個字節,還保存了一些bootargs參數。那么怎么找到這個地址呢,那就是從bootm后面跟的參數得知的,或者使用默認地址,但這些地址必須與uboot拷貝kernel到ram中的地址一樣,否則是找不到的。找到header之后,就把header中的信息保存起來。后面就是關於要不要在loadkernel的問題,那么需要比較兩個地址,如果mkimage時候定的load地址與bootm后面跟隨的地址不一樣,那么就需要再load一次。但是load之后load地址與entrypoint地址肯定是一樣的。如果前兩個地址一樣,那么就不需要再次load,但是這時候的entrypoint就與load地址相差0x40,其實相差的就是一個header的大小,第一次是省去了header,所以相等。

load之后就可以進入do_bootm_linux()函數了。在這個函數中呢,會把bootargs參數做成TAG鏈表形式。然后void    (*theKernel)(int zero, int arch,uint params);  其中thekernel賦值為ep,就是entrypoint即入口地址。這是mkimage制作鏡像時定義的。

問題說說:

1.一直在想在bootm中,加入nand read ,完成kernel由nandflash到ram的拷貝,只需要bootm一條指令就可以完成autoboot的工作,其實這樣不好,想想autoboot就知道了。所謂的autoboot,是執行的bootcmd,bootcmd=nand read 0x40008000 0x400000 0x300000 ;bootm 0x40008000;兩條指令完成的。還是不要改boom的實現吧。

2.tftp 0x40008000 uImage;然后就啟動內核了,把文件系統從nandflash拷貝到ram空間不是必須得,只需要把參數bootargs傳給內核,內核在引導文件系統的時候會自動加載。

3.這次學習添加了2條指令,感覺還不錯。關於0x40008000這個地址的理解,花了不少時間的。首先,這是個ram地址,第二kernel從nandflash拷貝到ram就是到這兒,第三bootm 后面的地址參數或者默認的地址參數,都必須與此地址相同,否則找不到header 第四 mkimage指定的load地址與之是否一樣決定了kernel的解壓地址與entrypoint。比如mkimage指定的load地址是0x41800000,與0x40008000不一樣,那么kernel將解壓到0x41800000,此時已經不含header了,所以entrypoint就必須是0x41800000。

arch

 

 

, uint params); 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM