1、main_loop()函数源码
从uboot中摘抄的部分main_loop函数,为了便于理解,函数只保留了主线部分代码,一些用宏定义控制的代码被删除掉了。
void main_loop (void)
{
static char lastcommand[CFG_CBSIZE] = {
0, };
int len;
int rc = 1;
int flag;
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) //是否有bootdelay
char *s;
int bootdelay;
#endif
#ifdef CONFIG_BOOTCOUNT_LIMIT //启动次数的限制
unsigned long bootcount = 0;
unsigned long bootlimit = 0;
char *bcs;
char bcs_set[16];
#endif /* CONFIG_BOOTCOUNT_LIMIT */
#ifdef CONFIG_BOOTCOUNT_LIMIT
bootcount = bootcount_load();//读取已经启动的次数
bootcount++;
bootcount_store (bootcount);//将启动次数加1再写回去保存起来
sprintf (bcs_set, "%lu", bootcount);
setenv ("bootcount", bcs_set); //设置已经启动的次数到环境变量bootcount
bcs = getenv ("bootlimit");//从环境变量获取启动次数的上限,此时返回的是字符串还需要转换成整数
bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
#endif /* CONFIG_BOOTCOUNT_LIMIT */
#ifdef CONFIG_VERSION_VARIABLE //设置ver环境变量,里面保存的是uboot的版本
{
extern char version_string[];
setenv ("ver", version_string); /* set version variable */
}
#endif /* CONFIG_VERSION_VARIABLE */
#ifdef CONFIG_AUTO_COMPLETE //命令的自动补全功能
install_auto_complete();
#endif
#ifdef CONFIG_FASTBOOT//支持fastboot刷机
if (fastboot_preboot())
run_command("fastboot", 0);
#endif
/* 下面就是实现uboot启动延时机制bootdelay的代码 */
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
s = getenv ("bootdelay"); /* 从环境变量获取启动延时的秒数 */
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
/* 检查启动次数是否超过上限*/
#ifdef CONFIG_BOOTCOUNT_LIMIT
if (bootlimit && (bootcount > bootlimit)) {
printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
(unsigned)bootlimit);
s = getenv ("altbootcmd");
}
else
#endif /* CONFIG_BOOTCOUNT_LIMIT */
s = getenv ("bootcmd"); /* 从环境变量获取启动内核的命令 */
debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
/*abortboot函数是检测在bootdelay时间内是否有人按键:如果有人按键则返回1;
超过bootdelay的时间没有人按键则返回0,if条件满足则启动内核*/
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
#ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* 禁止 ctrl+c 功能 */
#endif
run_command (s, 0); //启动内核
#ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* 恢复 ctrl+c 功能 */
#endif
}
#endif /* CONFIG_BOOTDELAY */
/*
* 下面是一个死循环,不停的从控制台读取命令解析,直到执行bootm命令去启动内核
*/
for (;;) {
len = readline (CFG_PROMPT); //从控制台读取一行指令,存放在console_buffer
flag = 0; /* assume no special flags for now */
if (len > 0)
strcpy (lastcommand, console_buffer);
else if (len == 0)
flag |= CMD_FLAG_REPEAT;
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;
}
}
}
2、abortboot函数
该函数的传参是bootdelay,函数内部会不停的去检测当前是否有按键被按下,如果有则返回1,超时则返回0。
3、readline函数
该函数是从控制台读取一行数据,也就是从串口读取,但是有控制台实现了行缓冲。
4、run_command函数
以输入"setenv bootdelay 5"为例。
传参是readline读取到的指令;内部parse_line函数先进行字符处理,解析成argc=3, argv[0]=setenv ,argv[1]=bootdelay, argv[0]=5;cmdtp = find_cmd(argv[0])去查找当前是否有该命令,如果找到会返回该命令的结构体;执行命令:(cmdtp->cmd) (cmdtp, flag, argc, argv)