U-boot 启动流程分析 5

run_main_loop是uboot核心的运行循环,它调用main_loop进行bootstage设置、初始化hashshell、获取环境变量和bootcmd,执行倒计时以及处理预启动命令。当倒计时结束或被中断时,系统会进入console,允许用户输入命令。autoboot_command负责检查倒计时和按键,执行bootcmd,而cli_loop则持续监听console输入,解析并执行命令。

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*/
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值