uboot(五)—— main_loop

举报
dz小伟 发表于 2022/11/12 18:53:43 2022/11/12
【摘要】 ​ 目录一、main_loop函数二、去掉多余if判断函数三、autoboot_command3.1、abortboot3.2、run_command_list四、cli_loop一、main_loop函数位置:u-boot-2022.01/common/main.c    40行void main_loop(void){ const char *s; bootstage_mark_name...

 

目录

一、main_loop函数

二、去掉多余if判断函数

三、autoboot_command

3.1、abortboot

3.2、run_command_list

四、cli_loop



一、main_loop函数

位置:u-boot-2022.01/common/main.c    40行

void main_loop(void)
{
	const char *s;

	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");

	if (IS_ENABLED(CONFIG_VERSION_VARIABLE))
		env_set("ver", version_string);  /* set version variable */

	cli_init();

	if (IS_ENABLED(CONFIG_USE_PREBOOT))
		run_preboot_environment_command();

	if (IS_ENABLED(CONFIG_UPDATE_TFTP))
		update_tftp(0UL, NULL, NULL);

	if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))
		efi_launch_capsules();

	s = bootdelay_process();
	if (cli_process_fdt(&s))
		cli_secure_boot_cmd(s);

	autoboot_command(s);

	cli_loop();
	panic("No CLI available");

二、去掉多余if判断函数

void main_loop(void)
{
	const char *s;

	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); //打印出启动进度

	cli_init();    //命令初始化有关,初始化 hush shell 相关的变量

	run_preboot_environment_command();    //获取环境变量 perboot 的内容


	s = bootdelay_process();    //此函数会读取环境变量 bootdelay 和 bootcmd 的内容
	
	autoboot_command(s);     //检查倒计时是否结束

	cli_loop();    //命令行处理函数
	panic("No CLI available");

}
  • bootstage_mark_name:打印出启动进度
  • cli_init():命令初始化有关,初始化 hush shell 相关的变量
  • run_preboot_environment_command:获取环境变量 perboot 的内容
  • s = bootdelay_process:此函数会读取环境变量 bootdelay 和 bootcmd 的内容
    将 bootdelay 的值赋值给全局变量 stored_bootdelay,返回值为环境变量 bootcmd 的值。
  • autoboot_command:检查倒计时是否结束
  • cli_loop:命令行处理函数

三、autoboot_command

  • 位置:u-boot-2022.01/common/autoboot.c   475行
  • 大致执行流程:判断3个条件,if成立进入执行run_command_list()启动内核,否则相当于什么都不执行,函数返回,接着执行cli_loop函数
  • if成立的关键,abortboot()函数,判断键盘是否按下,按下if就不成立,否则成立
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 返回值为 0。键盘按下导致为一
		bool lock;
		int prev;

		lock = autoboot_keyed() &&
			!IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC);
		if (lock)
			prev = disable_ctrlc(1); /* disable Ctrl-C checking */

		run_command_list(s, -1, 0);

		if (lock)
			disable_ctrlc(prev);	/* restore Ctrl-C checking */
	}

	if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY) &&
	    menukey == AUTOBOOT_MENUKEY) {
		s = env_get("menucmd");
		if (s)
			run_command_list(s, -1, 0);
	}
}

3.1、abortboot

  • 最终执行abortboot_single_key函数
  • abortboot_single_key:判断键盘是否按下,按下返回1,否则0
    倒计时并输出
static int abortboot(int bootdelay)
{
	int abort = 0;

	if (bootdelay >= 0) {
		if (autoboot_keyed())
			abort = abortboot_key_sequence(bootdelay);
		else
			abort = abortboot_single_key(bootdelay);
	}

	if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && abort)
		gd->flags &= ~GD_FLG_SILENT;

	return abort;
}

static int abortboot_single_key(int bootdelay)
{
	int abort = 0;
	unsigned long ts;

	printf("Hit any key to stop autoboot: %2d ", bootdelay);

	/*
	 * Check if key already pressed 判断键盘是否有按下
	 */
	if (tstc()) {	/* we got a key press	*/
		getchar();	/* consume input	*/
		puts("\b\b\b 0");
		abort = 1;	/* don't auto boot	*/
	}

	while ((bootdelay > 0) && (!abort)) {
		--bootdelay;
		/* delay 1000 ms */
		ts = get_timer(0);
		do {
			if (tstc()) {	/* we got a key press	*/
				int key;

                //倒计时赋值0,返回赋值1
				abort  = 1;	/* don't auto boot	*/
				bootdelay = 0;	/* no more delay	*/
				key = getchar();/* consume input	*/
				if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY))
					menukey = key;
				break;
			}
			udelay(10000);
		} while (!abort && get_timer(ts) < 1000);

		printf("\b\b\b%2d ", bootdelay);//  \b退格
	}

	putc('\n');

	return abort;
}

3.2、run_command_list

此函数会执行参数 s 指定的一系列命令,也就是环境变量 bootcmd 的命令
启动内核

四、cli_loop

命令行处理函数

  • 位置:common/cli.c
  • cli_loop:中执行parse_file_outer函数进行命令的解析与执行
  • parse_file_outer:
    parse_stream 进行命令解析
    run_list 执行解析出来的命令
  • run_list:里面经过一系列调用run_list_real --> run_pipe_real --> cmd_process 来处理命令
void cli_loop(void)
{
	bootstage_mark(BOOTSTAGE_ID_ENTER_CLI_LOOP);
	parse_file_outer();
	/* This point is never reached */
	for (;;);
}

//位置:common/cli_hush.c
int parse_file_outer(void)
{
	int rcode;
	struct in_str input;
	setup_file_in_str(&input);    //初始化变量 input 的成员变量
	rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON); //hush shell 的命令解释器
	return rcode;
}

static int parse_stream_outer(struct in_str *inp, int flag)
{
	struct p_context ctx;
	o_string temp=NULL_O_STRING;
	int rcode;
	int code = 1;

	do {
		ctx.type = flag;
		initialize_context(&ctx);
		update_ifs_map();
		if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0);
		inp->promptmode=1;
		rcode = parse_stream(&temp, &ctx, inp,
				     flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n'); //命令解析
		if (rcode == 1) flag_repeat = 0;
		if (rcode != 1 && ctx.old_flag != 0) {
			syntax();
			flag_repeat = 0;
		}
		if (rcode != 1 && ctx.old_flag == 0) {
			done_word(&temp, &ctx);
			done_pipe(&ctx,PIPE_SEQ);
			code = run_list(ctx.list_head);    //执行命令
			if (code == -2) {	/* exit */
				b_free(&temp);
				code = 0;
				/* XXX hackish way to not allow exit from main loop */
				if (inp->peek == file_peek) {
					printf("exit not allowed from main input shell.\n");
					continue;
				}
				break;
			}
			if (code == -1)
			    flag_repeat = 0;
		} else {
			if (ctx.old_flag != 0) {
				free(ctx.stack);
				b_reset(&temp);
			}
			if (inp->__promptme == 0) printf("<INTERRUPT>\n");
			inp->__promptme = 1;
			temp.nonnull = 0;
			temp.quote = 0;
			inp->p = NULL;
			free_pipe_list(ctx.list_head,0);
		}
		b_free(&temp);
	/* loop on syntax errors, return on EOF */
	} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP) &&
		(inp->peek != static_peek || b_peek(inp)));
	return (code != 0) ? 1 : 0;
}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。