流程分析
********************************************************
1.最開始系統上電後
ENTRY(_start)程式進入點是 _start board/mingddie/u-boot.lds
2._start: cpu/mips/start.S
3. la t9, board_init_f 將函數board_init_f地址賦予t9
j t9 跳轉到t9寄存器中儲存的地址指向的指令
即跳轉到RAM 中執行 C 代碼
這裡會列印一些資訊。
3.1 board_init_f() lib_mips/board.c
初始化外部記憶體
relocate_code() 回到cpu/mips/start.S中繼續執行
4.la t9,board_init_r cpu/mips/start.S
j t9 將函數board_init_r地址賦予t9
跳轉到t9寄存器中儲存的地址指向的指令
即跳轉到RAM 中執行 C 代碼
這裡會列印一些資訊
4.1 board_init_r() 函數 lib_mips/board.c
4.2 main_loop() common/main.c
s=getenv ("bootcmd") 取得環境變數中的啟動命令列,如bootcmd=bootm 0xbf020000
run_command (s, 0); //執行這個命令列 ,即bootm
4.3 do_bootm() common/cmd_bootm.c
// printf ("## Booting image at %08lx .../n", addr); //比如
5. bootm 啟動核心
5.1 do_bootm_linux() lib_mips/mips_linux.c
函數解析
***************************************************
1.board_init_f()
1.1
void board_init_f(ulong bootflag)
{
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) {
hang ();
}
}
//調用init_sequence 函數隊列,對板子進行一些初始化,詳細見後面
初始化external memory,初始化堆棧用cache作堆棧,為
relocate_code (addr_sp, id, addr); //回到cpu/mips/start.S 中
/* NOTREACHED - relocate_code() does not return */
}
1.2
typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = {
clx_board_init, //初始化GPIO,CPU速度,PLL,SDRAM 等
timer_init, //時鐘初始化
env_init, //環境變臉初始化
incaip_set_cpuclk, //根據環境變數設定CPU 時鐘
init_baudrate, //初始化串口傳輸速率
serial_init, /* serial communications setup */
console_init_f, //串口初始化,後面才能顯示
display_banner, //在螢幕上輸出一些顯示資訊
checkboard,
init_func_ram,
NULL,
};
2.board_init_r()
(1)調用一系列的初始化函數。
(2)初始化Flash裝置。
(3)初始化系統記憶體配置函數。
(4)如果目標系統擁有NAND裝置,則初始化NAND裝置。
(5)如果目標系統有顯示裝置,則初始化該類裝置。
(6)初始化相關網路裝置,填寫IP、MAC地址等。
(7)進去命令迴圈(即整個boot的工作迴圈),接受使用者從串口輸入的命令,然後進行相應的工作
void board_init_r (gd_t *id, ulong dest_addr)
{
/* configure available FLASH banks */ //配置可用的flash單元
size = flash_init(); //初始化flash
display_flash_config (size); //顯示flash 的大小
/* initialize malloc() area */
mem_malloc_init();
malloc_bin_reloc();
puts ("NAND:");
nand_init(); /* go init the NAND */ //NAND初始化
/* relocate environment function pointers etc. */
env_relocate(); //初始化環境變數
/* board MAC address */
s = getenv ("ethaddr"); //乙太網路MAC地址
for (i = 0; i < 6; ++i) {
bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
if (s)
s = (*e) ? e + 1 : e;
}
/* IP Address */
bd->bi_ip_addr = getenv_IPaddr("ipaddr");
pci_init(); //pci初始化配置
/** leave this here (after malloc(), environment and PCI are working) **/
/* Initialize devices */
devices_init ();
jumptable_init ();
/* Initialize the console (after the relocation and devices init) */
console_init_r (); //串口初始化
/* miscellaneous platform dependent initialisations */
misc_init_r ();
puts ("Net: ");
eth_initialize(gd->bd);
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop (); //迴圈執行,試圖自動啟動,接受使用者從串口輸入的命令,
然後進行相應的工作,設定延時時間,確定目標板是進入下載模式還是啟動載入模式
}
/* NOTREACHED - no way out of command loop except booting */
}
3.main_loop()
void main_loop (void)
{
s = getenv ("bootdelay"); //從環境變數中取得bootdelay 核心等待延時
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
debug ("### main_loop entered: bootdelay=%d/n/n", bootdelay);
s = getenv ("bootcmd"); //從環境變數中取得bootcmd 啟動命令列
如bootcmd=tftp;bootm 或者 bootcmd=bootm 0xbf020000
char *s1 = getenv ("bootargs"); //從環境變數中取得bootargs 啟動參數
debug ("### main_loop: bootcmd=/"%s/"/n", s ? s : "<UNDEFINED>");
run_command (s, 0); //執行啟動命令
//手動輸入命令
for (;;) {
len = readline (CFG_PROMPT); //讀取鍵入的命令到CFG_PROMPT 中
rc = run_command (lastcommand, flag); //執行這個命令
}
#endif /*CFG_HUSH_PARSER*/
}
4.do_bootm()
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
這個函數看著挺長的,其實無非就是將核心解壓縮,然後調用do_bootm_linux引導核心
5.do_bootm_linux() lib_mips/mips_linux.c
列印資訊Starting kernel ...
void do_bootm_linux (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong * len_ptr, int verify)
{
char *commandline = getenv ("bootargs");
theKernel =
(void (*)(int, char **, char **, int *)) ntohl (hdr->ih_ep);
//hdr為指向image header的指標,hdr->ih_ep就是我們用mkimage建立image時-e選項的參數:核心的入口地址
linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline);
/* we assume that the kernel is in place */
printf ("/nStarting kernel .../n/n");
theKernel (linux_argc, linux_argv, linux_env, 0); //啟動核心
}
u-boot向核心傳遞啟動參數由一系列在include/configs/.h中的宏控制,啟動參數傳遞的地址在board_init中初始化