u-boot启动分析02(board_init_f,board_init_r)
接着上一篇文章继续分析。
u-boot15/common/main.c
/* We come here after U-Boot is initialised and ready to process commands */
void main_loop(void)
{
const char *s;
bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
#ifndef CONFIG_SYS_GENERIC_BOARD
debug("Warning: Your board does not use generic board. Please read\n");
debug("doc/README.generic-board and take action. Boards not\n");
debug("upgraded by the late 2014 may break or be removed.\n");
#endif
modem_init();//根据定义CONFIG_MODEM_SUPPORT,初始化modem,项目无此配置
#ifdef CONFIG_VERSION_VARIABLE
setenv("ver", version_string); /* set version variable */
#endif /* CONFIG_VERSION_VARIABLE */
cli_init();//CONFIG_SYS_HUSH_PARSER,CONFIG_HUSH_INIT_VAR,项目无此配置
run_preboot_environment_command();//执行preboot命令,role 1章节分析
#if defined(CONFIG_UPDATE_TFTP) //未定义
update_tftp(0UL);
#endif /* CONFIG_UPDATE_TFTP */
s = bootdelay_process();//命令行延时处理 2章节分析
if (cli_process_fdt(&s))
cli_secure_boot_cmd(s);
autoboot_command(s); //执行启动命令 3章节分析
cli_loop();// u-boot命令行处理
}
u-boot15/common/main.c
static void run_preboot_environment_command(void)
{
#ifdef CONFIG_PREBOOT
char *p;
p = getenv("preboot");//role
if (p != NULL) {
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif
run_command_list(p, -1, 0); // 执行命令行,入参p指向的内容是“role” 1.1小节分析
# ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
# endif
}
#endif /* CONFIG_PREBOOT */
}
u-boot15/common/cmd_role.c
int do_role(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
#ifdef CONFIG_ZEBU
boot_mode_t boot_role = BOOTLOADER_MODE_LOAD;
#else
boot_mode_t boot_role = get_boot_role();//从chipram中读取boot_role
#endif
switch(boot_role) {
case BOOTLOADER_MODE_DOWNLOAD:
setenv("bootdelay", "0");
setenv("bootcmd", "download");
debugf("Get chipram env mode %x,go download\n", boot_role);
break;
case BOOTLOADER_MODE_LOAD: //走这个分支,bootcmd环境变量赋值cboot
setenv("bootcmd", "cboot");
debugf("Get chipram env mode %x,go cboot\n", boot_role);
break;
default :
printf("unkown uboot role ,nothing to do in preboot\n");
}
return 0;
}
u-boot15/common/autoboot.c
const char *bootdelay_process(void)
{
... ... //省略不满足判断条件的代码
char *s;
int bootdelay;
s = getenv("bootdelay");
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;//bootdelay取值,如果s不为空,取s的值,否则取CONFIG_BOOTDELAY
debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);//打印bootdelay的值
bootretry_init_cmd_timeout();//初始化 command line timeout的时间
s = getenv("bootcmd"); //读取bootcmd环境变量的值赋值给s
process_fdt_options(gd->fdt_blob); //如果配置了CONFIG_OF_CONTROL,则做fdt相关处理
stored_bootdelay = bootdelay; //赋值给stored_bootdelay,used by autoboot_command()
return s;
}
u-boot15/common/autoboot.c
void autoboot_command(const char *s)
{
debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "" );
if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
int prev = disable_ctrlc(1); /* disable Control C checking */
#endif
run_command_list(s, -1, 0); //执行命令 cboot,3.1小节分析
#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
disable_ctrlc(prev); /* restore Control C checking */
#endif
}
... ...
}
u-boot15/common/cmd_cboot.c
这个函数比较长,只分析重点部分。
int do_cboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
... ...
/* s_boot_func_array是一个函数指针数组,入参为void,返回值类型为boot_mode_enum_type
* typedef boot_mode_enum_type (*CBOOT_FUNC) (void);
* boot_mode_enum_type 是枚举类型,枚举了CMD_NORMAL_MODE,CMD_RECOVERY_MODE等多种启动类型
* 此for循环遍历s_boot_func_array,执行相应的函数,匹配启动模式
*/
for (i = 0; i < CHECK_BOOTMODE_FUN_NUM; i++) {
if (0 == s_boot_func_array[i]) {
bootmode = CMD_POWER_DOWN_DEVICE;
break;
}
bootmode = s_boot_func_array[i]();
if (CMD_UNDEFINED_MODE == bootmode) {
continue;
} else {
debugf("get boot mode in boot func array[%d]\n",i);
break;
}
}
board_boot_mode_regist(boot_mode_array); //注册启动模式,即给boot_mode_array赋值。
if ((bootmode > CMD_POWER_DOWN_DEVICE) &&(bootmode < CMD_MAX_MODE)&& (0 != boot_mode_array[bootmode])) {
write_log();
boot_mode_array[bootmode](); //执行相应的启动模式代码
}
}
下面以正常启动模式为例,分析后续的执行流程。
// 1. 注册NORMAL启动模式
void board_boot_mode_regist(CBOOT_MODE_ENTRY *array)
{
MODE_REGIST(CMD_NORMAL_MODE, normal_mode);
... ...
}
// 2. 执行启动模式对应的函数
boot_mode_array[CMD_NORMAL_MODE]();
//3. 执行normal_mode
// 代码路径: u-boot15/common/loader/boot_mode.c
void normal_mode(void)
{
#ifndef CONFIG_ZEBU //走这个分支
vibrator_hw_init();
set_vibrator(1);
vlx_nand_boot(BOOT_PART, BACKLIGHT_ON, LCD_ON);//继续启动,初始化LCD,安全启动验证,加载内核等
#else
vlx_nand_boot_zebu(BOOT_PART, BACKLIGHT_ON, LCD_ON);
#endif
return;
}