run_main_loop工作流程介绍
前面几篇文章介绍了uboot的代码执行流程,下面主要介绍下run_main_loop函数,它是board_init_r最后调用的一个函数,执行倒计时执行设置的bootcmd,如果倒计时被打断会进入uboot的console。
run_main_loop只调用了2个函数,最后死循环调用main_loop
static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
sandbox_main_loop_init();
#endif
/* main_loop() can return to retry autoboot, if so just run it again */
for (;;)
main_loop();
return 0;
}
main_loop就是关键,进行boot stage的设置,初始化hash shell,获取环境变量,获取delay数值和bootcmd,进行倒计时
void main_loop(void)
{
const char *s;
/* 设置boot stage */
bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
if (IS_ENABLED(CONFIG_VERSION_VARIABLE))
env_set("ver", version_string); /* set version variable */
/* hash shell的初始化 */
cli_init();
if (IS_ENABLED(CONFIG_USE_PREBOOT))
run_preboot_environment_command(); //获取环境变量preboot的内容,preboot是一些预启动命令。
if (IS_ENABLED(CONFIG_UPDATE_TFTP))
update_tftp(0UL, NULL, NULL); //Auto-update from TFTP
/* 获取uboot启动倒计时时间保存在stored_bootdelay,获取bootcmd参数 */
s = bootdelay_process();
if (cli_process_fdt(&s)) //从fdt里面获取是否要支持secure boot
cli_secure_boot_cmd(s);
/* 倒计时处理,倒计时完成后auto boot,倒计时被打断进入下面的cli_loop中 */
autoboot_command(s);
/* 如果uboot倒计时被打断,就进入这里,处理uboot console输入的命令,死循环,不再返回了 */
cli_loop();
panic("No CLI available");
}
下面简要介绍几个关键的函数
1. autoboot_command, abortboot中执行倒计时按键检测,有按键返回,没有按键执行bootcmd里面的命令。
void autoboot_command(const char *s)
{
debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
if (s && (stored_bootdelay == -2 ||
(stored_bootdelay != -1 && !abortboot(stored_bootdelay)))) {//abortboot是倒计时检测按键函数,有按键返回1,否则返回0
bool lock;
int prev;
lock = IS_ENABLED(CONFIG_AUTOBOOT_KEYED) &&
!IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC);
if (lock)
prev = disable_ctrlc(1); /* disable Ctrl-C checking */
run_command_list(s, -1, 0);//执行s里面存储的命令,一般是boot命令,也不一定
if (lock)
disable_ctrlc(prev); /* restore Ctrl-C checking */
}
//riscv中没有配置CONFIG_USE_AUTOBOOT_MENUKEY,所以不会走着里,如果上面的逻辑没有执行,将直接返回
if (IS_ENABLED(CONFIG_USE_AUTOBOOT_MENUKEY) &&
menukey == AUTOBOOT_MENUKEY) {
s = env_get("menucmd");
if (s)
run_command_list(s, -1, 0);
}
}
2. cli_loop, 循环检测console的输入,并解析执行命令
void cli_loop(void)
{
bootstage_mark(BOOTSTAGE_ID_ENTER_CLI_LOOP);
#ifdef CONFIG_HUSH_PARSER // riscv 定义了,会走着里,不在返回
// 进入到parse_stream_outer里面的do while里面,循环进行:接受命令,解析命令,执行命令
// parse_file_outer -> parse_stream_outer ->
// do{1.获取命令:parse_stream->b_getch; 2.查找执行命令run_list->cmd_call->cmd_process->cmd_call}while
parse_file_outer();
/* This point is never reached */
for (;;);
#elif defined(CONFIG_CMDLINE)
cli_simple_loop();
#else
printf("## U-Boot command line is disabled. Please enable CONFIG_CMDLINE\n");
#endif /*CONFIG_HUSH_PARSER*/
}
run_main_loop是uboot核心的运行循环,它调用main_loop进行bootstage设置、初始化hashshell、获取环境变量和bootcmd,执行倒计时以及处理预启动命令。当倒计时结束或被中断时,系统会进入console,允许用户输入命令。autoboot_command负责检查倒计时和按键,执行bootcmd,而cli_loop则持续监听console输入,解析并执行命令。
1634

被折叠的 条评论
为什么被折叠?



