uboot启动之后可以响应键盘输入,执行自带命令,完成各种功能,文本主要围绕uboot自有命令实现细节。
接着上节的main_loop函数,删除不必要细节,精简如下:
void main_loop (void)
{
static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
int len;
int rc = 1;
int flag;
char *s;
int bootdelay;
s = getenv ("bootdelay");
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
s = getenv ("bootcmd");
if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
run_command (s, 0);
}
/* Main Loop for Monitor Command Processing */
for (;;) {
len = readline (CONFIG_SYS_PROMPT);
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;
}
}
}
主要关注getenv以及run_command函数,在调用main_loop之前,即board_init_r函数体中调用env_relocate()来初始化与环境变量相关的信息:
void env_relocate (void)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
extern void env_reloc(void);
env_reloc();
#endif
if (gd->env_valid == 0) {
#if defined(CONFIG_ENV_IS_NOWHERE) /* Environment not changable */
set_default_env(NULL);
#else
show_boot_progress (-60);
set_default_env("!bad CRC");
#endif
} else {
env_relocate_spec ();
}
}
我们按默认的环境变量来分析set_default_env:
函数himort_r主要是进行词法分析,注释也有说明:
Import linearized data into hash table.
This is the inverse function to hexport(): it takes a linear list
of “name=value” pairs and creates hash table entries from it.
env_htab是个全局变量,存储进行词法分析之后的相关信息:
现在回到getevn函数:
该函数的作用是返回在环境变量中的数据,举个例子,在const uchar default_environment[]有如下环境参数:
“bootdelay=3 ”,
那么getenv (“bootdelay”)返回的就是=之后的字符串——“3”,称之为数据部分。
同理bootcmd环境参数的数据部分如下:
"if mmc rescan ${mmcdev}; then " \
"if run loadbootscript; then " \
"run bootscript; " \
"else " \
"if run loaduimage; then " \
"run mmcboot; " \
"else run nandboot; " \
"fi; " \
"fi; " \
"else run nandboot; fi" "\0"
以上字符串也就是run_command的第一个参数cmd:
*int run_command (const char cmd, int flag)
run_command在字符串中提取一系列参数,最后查找相应的命令:
这里要去查看u-boot.lds文件:
处于段.u_boot_cmd的数据,那么查找相关信息:
举个例子,假设执行 **“run nandboot”**命令:
需要执行 字符 run对应的命令:
将宏展开如下:
那么之前find_cmd传入参数"run",返回 __u_boot_cmd_run结构,接着就会执行do_run函数:
这里会继续之前的步骤,解析nandboot符号来找到相应的命令函数:
基本上uboot所有的自有命令都是类似过程,通过分析命令函数也可以加深对自有命令功能的理解,可以模仿创建自有命令。