流程分析
***************************************************
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 (); }
- }
-
- 初始化external memory,初始化堆栈用cache作堆栈,为
- relocate_code (addr_sp, id, addr);
-
- }
1.2
- typedef int (init_fnc_t) (void);
- init_fnc_t *init_sequence[] =
- { clx_board_init,
- timer_init,
- env_init,
- incaip_set_cpuclk,
- init_baudrate,
- serial_init,
- 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)
- {
-
- size = flash_init();
- display_flash_config (size);
-
- mem_malloc_init();
- malloc_bin_reloc();
- puts ("NAND:");
- nand_init();
-
- env_relocate();
-
- s = getenv ("ethaddr");
- for (i = 0; i < 6; ++i) {
- bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
- if (s)
- s = (*e) ? e + 1 : e;
- }
-
- bd->bi_ip_addr = getenv_IPaddr("ipaddr");
- pci_init();
-
-
- devices_init ();
- jumptable_init ();
-
- console_init_r ();
-
- misc_init_r ();
- puts ("Net: ");
- eth_initialize(gd->bd);
-
- for (;;) {
- main_loop ();
- }
-
- }
-
- 3.main_loop()
- void main_loop (void)
- {
- s = getenv ("bootdelay");
- bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
- debug ("### main_loop entered: bootdelay=%d/n/n", bootdelay);
- s = getenv ("bootcmd");
- 如bootcmd=tftp;bootm 或者 bootcmd=bootm 0xbf020000
- char *s1 = getenv ("bootargs");
- debug ("### main_loop: bootcmd=/"%s/"/n", s ? s : "<UNDEFINED>");
- run_command (s, 0);
-
- for (;;) {
- len = readline (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);
-
- linux_params_init (UNCACHED_SDRAM (gd->bd->bi_boot_params), commandline);
-
- printf ("/nStarting kernel .../n/n");
- theKernel (linux_argc, linux_argv, linux_env, 0);
- }
u-boot向内核传递启动参数由一系列在include/configs/.h中的宏控制,启动参数传递的地址在board_init中初始化