一、uboot命令实现
1、run_commond(commom/main.c)
int run_command (const char *cmd, int flag)
{
while (*str) {
/*
* Find separator, or string end
* Allow simple escape of ';' by writing "\;"
*/
1、使用分号将命令提取出来
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;
}
2、处理宏(环境变量等)
/* find macros in this token and replace them */
process_macros (token, finaltoken);
3、解析命令参数,保存在argv字符串数组
/* Extract arguments */
if ((argc = parse_line (finaltoken, argv)) == 0) {
rc = -1; /* no command at all */
continue;
}
4、查找命令
/* 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;
}
}
2、命令查找函数
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;
/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end;
cmdtp++) {
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp; /* full match */
cmdtp_temp = cmdtp; /* abbreviated command ? */
n_found++;
}
}
if (n_found == 1) { /* exactly one match */
return cmdtp_temp;
}
return NULL; /* not found or ambiguous command */
}
__u_boot_cmd_start和__u_boot_cmd_end之间的命令保存在链接脚本
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
3、命令实现原理
1、以bootm为例,说明命令实现过程
U_BOOT_CMD(
bootm, CFG_MAXARGS, 1, do_bootm,
"bootm - boot application image from memory\n",
"[addr [arg ...]]\n - boot application image stored in memory\n"
"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
"\t'arg' can be the address of an initrd image\n"
#ifdef CONFIG_OF_FLAT_TREE
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif
);
2、U_BOOT_CMD宏实现
<include/command.h>
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
3、展开
cmd_tbl_t __u_boot_cmd_bootm Struct_Section = {"bootm", CFG_MAXARGS, 1, do_bootm, usage, help}
4、将Struct_Section展开
<include/command.h>
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
cmd_tbl_t __u_boot_cmd_bootm __attribute__ ((unused,section (".u_boot_cmd"))) = {"bootm", CFG_MAXARGS, 1, do_bootm, usage, help}
5、说明
创建一个cmd_tbl_t类型的__u_boot_cmd_bootm结构体,属性为保存在".u_boot_cmd"段(链接脚本会说明)的地址,成员为 {"bootm", CFG_MAXARGS, 1, do_bootm, usage, help}
4、实现一个命令(hello:打印一个hello)
(1)创建一个命令文件(common/cmd_hello.c)
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <zlib.h>
#include <bzlib.h>
#include <environment.h>
#include <asm/byteorder.h>
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i=0;
printf("hello world ! , %d\n", argc);
for(;i<argc;i++)
{
printf("hello argv[%d] -> %s\n", i, argv[i]);
}
return 0;
}
U_BOOT_CMD(
hello, CFG_MAXARGS, 1, do_hello,
"hello, -just for test\n",
"hello, long help ---------\n"
);
(2)将命令添加至uboot
1、在common目录下的Makefile中添加cmd_hello.h
OGJS = ....
cmd_hello.o