一. run_main_loop 到 cmd_process处理过程
之前文章了解了 uboot的命令格式组成。本文简单分析下 cmd_process函数对 uboot命令的处理过程。
本文继上一篇文章的学习,地址如下:
uboot启动流程-run_main_loop 到 cmd_process处理说明二-CSDN博客
二. cmd_process函数处理命令过程
1. 函数调用关系
这里主要分析一下 uboot 的命令行处理过程。
通过分析可知, cli_loop 函数通过一系列调用,最终调用 cmd_process函数处理命令。调用关系如下:
2. cmd_process函数处理命令过程
cmd_process 函数定义在文件
common/command.c
中,函数内容如下:
enum command_ret_t cmd_process(int flag, int argc, char * const argv[],
int *repeatable, ulong *ticks)
{
enum command_ret_t rc = CMD_RET_SUCCESS;
cmd_tbl_t *cmdtp;
/* Look up command in command table */
cmdtp = find_cmd(argv[0]);
if (cmdtp == NULL) {
printf("Unknown command '%s' - try 'help'\n", argv[0]);
return 1;
}
/* found - check max args */
if (argc > cmdtp->maxargs)
rc = CMD_RET_USAGE;
#if defined(CONFIG_CMD_BOOTD)
/* avoid "bootd" recursion */
else if (cmdtp->cmd == do_bootd) {
if (flag & CMD_FLAG_BOOTD) {
puts("'bootd' recursion detected\n");
rc = CMD_RET_FAILURE;
} else {
flag |= CMD_FLAG_BOOTD;
}
}
#endif
/* If OK so far, then do the command */
if (!rc) {
if (ticks)
*ticks = get_timer(0);
rc = cmd_call(cmdtp, flag, argc, argv);
if (ticks)
*ticks = get_timer(*ticks);
*repeatable &= cmdtp->repeatable;
}
if (rc == CMD_RET_USAGE)
rc = cmd_usage(cmdtp);
return rc;
}
cmd_process 函数 调用函数 find_cmd函数
在命令表中找到指定的命令,
find_cmd
函数内容如下:
cmd_tbl_t *find_cmd(const char *cmd)
{
cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd);
const int len = ll_entry_count(cmd_tbl_t, cmd);
return find_cmd_tbl(cmd, start, len);
}
参数 cmd
就是所查找的命令名字,
uboot
中的命令表其实就是
cmd_tbl_t
结构体数组,通
过
ll_entry_star
t 函数得到数组的第一个元素,也就是命令表起始地址。
通过 ll_entry_count 函数得到数组长度,也就是命令表的长度。
最终通过 find_cmd_tbl 函数在命令表中找到所需的命 令,每个命令都有一个
name
成员,所以将参数
cmd
与命令表中每个成员的
name
字段都对比
一下,如果相等的话就说明找到了这个命令,找到以后就返回这个命令。
cmd_process
函数中,找到命令以后肯定就要执行这个命令了,
调用 cmd_call函数来执行具体的命令,cmd_call
函数内容如下:
static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int result;
result = (cmdtp->cmd)(cmdtp, flag, argc, argv);
if (result)
debug("Command failed, result=%d\n", result);
return result;
}
在前面的分析中我们知道,
cmd_tbl_t
的
cmd 成员就是具体的命令处理函数,所以,cmd_call
函数中,第5行
调用
cmdtp
的
cmd
成员来处理具体的命令,返回值为命令的执行结果。
cmd_process
中会检测
cmd_tbl
的返回值,如果返回值为
CMD_RET_USAGE
,就会调用
cmd_usage
函数输出命令的用法,其实就是输出
cmd_tbl_t
的
usage
成员变量。