/*
** 在u-boot-1.1.6中添加自定义命令的步骤:
** 1.增加一个u-boot命令文件,可以在common目录下复制一个文件名是cmd_***的文件,重命名为cmd_mynew.c;
** 2.把文件放置目录dir: common/cmd_mynew.c;
** 3.文件内大体包括这些内容:
3.1包含需要的头文件:common.h, command.h, mynew.h, .......;
3.2添加u-boot命令宏:
U_BOOT_CMD(
mynew, CFG_MAXARGS, 1, do_mynew,
"mynew - test my add new u-boot command.\n",
"print some message to show.\n"
" ...... \n"
);
3.3实现u-boot命令函数do_***(),比如这里的do_mynew().
*/
/*
** u-boot-1.1.6 的命令实现过程 理解。
** run_command函数位于dir:common/main.c
** 由于这个函数移植的时候基本不需要修改,并且本身注释也很清楚,所以没有花
** 太多的时间去注释和理解。
*/
/****************************************************************************
* returns:
* 1 - command executed, repeatable
* 0 - command executed but not repeatable, interrupted commands are
* always considered not repeatable
* -1 - not executed (unrecognized, bootd recursion or too many args)
* (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is
* considered unrecognized)
*
* WARNING:
*
* We must create a temporary copy of the command since the command we get
* may be the result from getenv(), which returns a pointer directly to
* the environment data, which may change magicly when the command we run
* creates or modifies environment variables (like "bootp" does).
*/
int run_command (const char *cmd, int flag)
{
cmd_tbl_t *cmdtp;
char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */
char *token; /* start of token in cmdbuf */
char *sep; /* end of token (separator) in cmdbuf */
char finaltoken[CFG_CBSIZE];
char *str = cmdbuf;
char *argv[CFG_MAXARGS + 1]; /* NULL terminated */
int argc, inquotes;
int repeatable = 1;
int rc = 0;
/*
** ctrlc_was_pressed = 0; 清除先前的控制命令
*/
clear_ctrlc(); /* forget any previous Control C */
/*
** 如果命令cmd是空的或者Null,那么返回-1.
*/
if (!cmd || !*cmd)
{
return -1; /* empty command */
}
/*
** 如果cmd命令太长,则输出提示:command too long!
** 且返回-1.
*/
if (strlen(cmd) >= CFG_CBSIZE)
{
puts ("## Command too long!\n");
return -1;
}
/*
** 把u-boot命令(cmd)内容复制到cmdbuf。
*/
strcpy (cmdbuf, cmd);
/*
** Process separators and check for invalid repeatable commands.
*/
while (*str)
{
/*
* Find separator, or string end
* Allow simple escape of ';' by writing "\;"
* 要明白这段解析命令参数的方法,要知道命令在内存中存放的格式
* 暂时还没有精力去了解,留给以后。
*/
for (inquotes = 0, sep = str; *sep; sep++)
{
if ((*sep=='\'') && (*(sep-1) != '\\'))
inquotes=!inquotes;
if (!inquotes &&
(*sep == ';') && /* separator */
( sep != str) && /* past string start */
(*(sep-1) != '\\')) /* and NOT escaped */
break;
}
/*
* Limit the token to data between separators
*/
token = str;
if (*sep) {
str = sep + 1; /* start of command for next pass */
*sep = '\0';
}
else
str = sep; /* no more commands for next pass */
/* find macros in this token and replace them */
process_macros (token, finaltoken);
/* Extract arguments */
if ((argc = parse_line (finaltoken, argv)) == 0)
{
rc = -1; /* no command at all */
continue;
}
/* Look up command in command table */
if ((cmdtp = find_cmd(argv[0])) == NULL)
{
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1; /* give up after bad command */
continue;
}
/* found - check max args */
if (argc > cmdtp->maxargs)
{
printf ("Usage:\n%s\n", cmdtp->usage);
rc = -1;
continue;
}
/*
** OK - call function to do the command.
** 调用命令执行函数。
*/
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
rc = -1;
}
repeatable &= cmdtp->repeatable;
/* Did the user stop this? */
if (had_ctrlc ())
return 0; /* if stopped then not repeatable */
}
return rc ? rc : repeatable;
}
/*
** u-boot中的cmd_tbl_t命令结构体:
** dir: include/command.h
*/
struct cmd_tbl_s {
char *name; /* Command Name,命令名称 */
int maxargs; /* maximum number of arguments,参数数量 */
int repeatable; /* autorepeat allowed? 命令是否可重复,按空格继续执行上一次输入的命令 */
/*
** Implementation function,这就是命令执行函数,是一个函数指针,四个参数。
*/
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage; /* Usage message (short),命令提示---短内容 */
char *help; /* Help message (long),命令提示---长内容 */
/*
** do auto completion on the arguments.
** 自动执行命令???
*/
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
};
typedef struct cmd_tbl_s cmd_tbl_t;