run_command(s,0); //执行这个命令行,即bootm c) do_bootm() command/cmd_bootm.c //printf(“##Booting image at lx…\\n”,addr);
5、bootm启动内核 a) do_bootm_linux() lib_mips/mips_linux.c 函数解析
1、 board_init_f()
a) 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*/
b) 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 communicatioins setup */ Console_init_f, //串口初始化,后面才能显示 Display_banner, //在屏幕上输出一些显示信息 Checkboard, Init_func_ram, NULL, };
2、 board_init_r()
a) 调用一些列的初始化函数 b) 初始化Flash设备
c) 初始化系统内存分配函数
d) 如果目标系统拥有NAND设备,则初始化NAND设备 e) 如果目标系统有显示设备,则初始化该类设备 f) 初始化相关网络设备,填写IP、MAC地址等
g) 进去命令循环(即整个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 addresss*/ 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 deivces init)*/ Console_init_t(); //串口初始化
/miscellaneous platform dependent initialisationss/ 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 : “
//手动输入命令 For (;;) { Len = readline(CFG_PROMPT); //读取键入的命令道CFG_PROMPT中 Rc = run_command(lashcommand, 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 * cmd tp, 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的指针,hr->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中初始化