本文为CP根据网上内容以及U-Boot 2014.4版本进行整理而成。
原文地址为 http://blog.chinaunix.net/uid-8867796-id-358806.html———————————————————————————————————————————————————
1:uboot的命令解析执行代码在main_loop()函数中实现,其向上的调用层次是:main_loop()//common\Main.cßboard_init_r()//arch\arm\lib\board.cßctr0.S//arch\arm\libßstart.S//arch\arm\cpu\arm7.
2. 现在我们已经进入了这个圈套那么只能往里钻了. common/main.c文件中的main_loop().
Main_loop会进入process_boot_delay()来处理boot延时。在process_boot_delay()内有如下操作: // 宏定义CONFIG_BOOTCOUNT_LIMIT猜测是限制启动次数的功能 #ifdef CONFIG_BOOTCOUNT_LIMIT bootcount = bootcount_load();
//从环境变量里找bootdelay //获取bootcmd 以作为默认启动参数开始启动 run_command_list(s, -1, 0); |
上面代码主要是对自启动部分的描述, 其中命令执行部分是在run_command中进行的, 这个等在后文分析. 如果我们没有bootcmd或者在延时中被打断, 那么代码会继续向下执行
//下面for循环是uboot处理终端命令的主循环, 这时等待我们从键盘中输入一行命令, 真正的人机交互从这里开始 |
3.read_line()读取到命令行后会调用common/main.c文件中的run_command(). 现在是分析run_command()的时候了, 不管是从环境变量还是终端获得命令, 都是由run_command()来处理的.
run_command()函数实际执行的是 builtin_run_command(cmd, flag)函数 //下面if语句判断命令是否太长, 还是避免有些变态的家伙输入了超过CFG_CBSIZE个字符的命令 |
//str就是指向cmdbuf的指针, 其实这些东西都是针对的刚才那行命令 /* |
4.上述命令获取完成之后,会进入命令执行。其函数为cmd_process(flag,argc, argv, &repeatable, NULL)。首要会执行find_cmd.find_cmd()在.u_boot_cmd段中寻找该命令的cmd_tbl_t结构, 找到后返回该结构. 该命令的结构是通过定义在include/command.h中的宏定义U_BOOT_CMD登记进.u_boot_cmd段中的.
//先研究一下这个神奇的U_BOOT_CMD, 定义如下, 其中cmd_tbl_t是命令的结构体类型, 这里不罗列了,成员包括命令名字, 参数的最大个数, 使用说明等等. U_BOOT_CMD定义为 #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, _comp) \ { #_name, _maxargs, _rep, _cmd, _usage, \ _CMD_HELP(_help) _CMD_COMPLETE(_comp) } #define U_BOOT_CMD_MKENT(_name, _maxargs, _rep, _cmd, _usage, _help) \ U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, NULL) #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \ ll_entry_declare(cmd_tbl_t, _name, cmd) = \ U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, _comp); #define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \ U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL) cmd_tbl_t *find_cmd (const char *cmd)函数会找到命令区的入口以及命令总数,并最终调用 cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len) 找到指定命令的入口 |
5. 刚才我们在长征的半路翻越了一座雪山, 现在继续回到while循环中
if (argc > cmdtp->maxargs) {
printf ("Usage:\n%s\n", cmdtp->usage);
rc = -1;
continue;
}
//这是啥, 我不管它了, 掠过这条小溪
#if defined(CONFIG_CMD_BOOTD)
/* avoid"bootd" recursion */
if (cmdtp->cmd == do_bootd) {
if (flag & CMD_FLAG_BOOTD) {
puts ("'bootd' recursion detected\n");
rc = -1;
continue;
} else {
flag |= CMD_FLAG_BOOTD;
}
}
#endif
//长征马上结束, 胜利就在眼前! 调用结构体中注册的cmd函数, 何时注册的呢? 上面不远处介绍的U_BOOT_CMD!
/* OK - call functionto do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
rc = -1;
}
repeatable &= cmdtp->repeatable;
/* ctrl+c 会终止, Did the user stop this? */
if (had_ctrlc ())
return -1; /*if stopped then not repeatable */
}