Overview
bootcmd是environment中重要的一个环境变量,u-boot的最后阶段会执行bootcmd定义的命令。
bootcmd通常就会包括load和boot命令(如bootz),即把kernel image & Flatten Device Tree加载到内存,然后执行内核内核。如此,完成u-boot到kernel的启动转换。
调用顺序
前面已经提到过,在u-boot的初始化阶段,会读取environment的值。而bootcmd的执行则在u-boot启动的最后一部分,即main_loop()。
main_loop() -> bootdelay_process() + autoboot_command() -> env "bootcmd"
main_loop()
main_loop()会等待获取用户的输入命令,或(超时后)获取环境变量中的bootcmd,之后调用autoboot_command()执行bootcmd命令序列。
// 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");
#ifdef CONFIG_VERSION_VARIABLE
setenv("ver", version_string); /* set version variable */
#endif /* CONFIG_VERSION_VARIABLE */
cli_init();
run_preboot_environment_command();
#if defined(CONFIG_UPDATE_TFTP)
update_tftp(0UL, NULL, NULL);
#endif /* CONFIG_UPDATE_TFTP */
s = bootdelay_process();
if (cli_process_fdt(&s))
cli_secure_boot_cmd(s);
autoboot_command(s);
cli_loop();
panic("No CLI available");
}
bootdelay_process()
这里的正常流程会获取环境变量中bootcmd的值,并返回这个值。
// common/autoboot.c
const char *bootdelay_process(void)
{
char *s;
int bootdelay;
// ...
s = getenv("bootcmd");
// ...
return s;
}
autoboot_command()
执行命令列表,如load, bootz等,即将内核等映像文件加载到内容,然后跳转到内核的第一条指令处执行,从而启动内核代码。
// common/autoboot.c
void autoboot_command(const char *s)
{
debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
// ...
run_command_list(s, -1, 0);
// ...
}