实现uboot 命令自动补全 及 修正设置环境变量时自启动内核

习惯了了linux下的命令自动补全,换做uboot下的单个字符的输入长串命令,实在是不太习惯。常常在uboot下习惯性的按TAB键。为了习惯,下面来实现uboot的命令的自动补全。

这个功能的实现非常容易,只是在/include/configs/开发板头文件.h(我的是micro2440.h)添加一个配置宏:

#define CONFIG_CMDLINE_EDITING//#ifdef CONFIG_CMDLINE_EDITING
//#undef CONFIG_AUTO_COMPLETE
//#else
#define CONFIG_AUTO_COMPLETE //开启命令自动补全函数的编译

编译,运行,功能实现

另外还碰到了一个奇怪的问题,把我卡了很久。每次在我执行这个命令后

setenv bootcmd "nand read 31000000 0x60000 500000;bootm 31000000"

会出现uboot立即自启动内核,也就是立即执行了bootm 31000000 这个命令。

原因找了很久,最后定为在/include/configs/开发板头文件.h(我的是micro2440.h)这个文件。这个文件某个宏定义有问题或者是未定义导致这个问题的出现。是哪一个宏呢?

看uboot 源码 不难找到问题所在 文件/cmmon/main.c

 

#ifdef CFG_HUSH_PARSER
	parse_file_outer();
	/* This point is never reached */
	for (;;);
#else
	for (;;) {
#ifdef CONFIG_BOOT_RETRY_TIME
		if (rc >= 0) {
			/* Saw enough of a valid command to
			 * restart the timeout.
			 */
			reset_cmd_timeout();
		}
#endif
		len = readline (CFG_PROMPT);

		flag = 0;	/* assume no special flags for now */
		if (len > 0)
			strcpy (lastcommand, console_buffer);
		else if (len == 0)
			flag |= CMD_FLAG_REPEAT;
#ifdef CONFIG_BOOT_RETRY_TIME
		else if (len == -2) {
			/* -2 means timed out, retry autoboot
			 */
			puts ("\nTimed out waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY
			/* Reinit board to run initialization code again */
			do_reset (NULL, 0, 0, NULL);
# else
			return;		/* retry autoboot */
# endif
		}
#endif

		if (len == -1)
			puts ("<INTERRUPT>\n");
		else
			rc = run_command (lastcommand, flag);

		if (rc <= 0) {
			/* invalid command or not repeatable, forget it */
			lastcommand[0] = 0;
		}
	}
#endif /*

如果不定义宏 CFG_HUSH_PARSER  就将执行红色部分代码,分析这部分代码在CFG_PROMPT>=0时执行strcpy (lastcommand, console_buffer);函数,即等待串口缓冲区得数据 ,如果有数据,将把数据复制到lastcommand这个串中,然后执行rc = run_command (lastcommand, flag);而恰恰就是run_command (lastcommand, flag);这个函数有问题,函数内把带有 ; 号的命令作为下一个命令执行了,所以出现了bootm 自启动内核的问题.

而定义 CFG_HUSH_PARSER  宏将执行parse_file_outer();函数,函数内最后调用,cmmon/hush.c 文件的int parse_stream_outer(struct in_str *inp, int flag)函数

do {
		ctx.type = flag;
		initialize_context(&ctx);
		update_ifs_map();
		if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";{1}|", 0);
		inp->promptmode=1;
		rcode = parse_stream(&temp, &ctx, inp, '\n');
#ifdef __U_BOOT__
		if (rcode == 1) flag_repeat = 0;
#endif
		if (rcode != 1 && ctx.old_flag != 0) {
			syntax();
#ifdef __U_BOOT__
			flag_repeat = 0;
#endif
		}
		if (rcode != 1 && ctx.old_flag == 0) {
			done_word(&temp, &ctx);
			done_pipe(&ctx,PIPE_SEQ);
#ifndef __U_BOOT__
			run_list(ctx.list_head);
#else
			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;
#endif
		} else {
			if (ctx.old_flag != 0) {
				free(ctx.stack);
				b_reset(&temp);
			}
#ifdef __U_BOOT__
			if (inp->__promptme == 0) printf("<INTERRUPT>\n");
			inp->__promptme = 1;
#endif
			temp.nonnull = 0;
			temp.quote = 0;
			inp->p = NULL;
			free_pipe_list(ctx.list_head,0);
		}
		b_free(&temp);
	} while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP));   

会发现条件rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)是一直满足的,就进入了另一个命令提示输入循环,这个循环避免上面那个现象。

代码没看的太仔细,分析的可能还存在问题,希望遇到同样问题的朋友如果发现分析错误能够多多指正。

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值