uboot-1.1.6
#set machid 0456 这是用来设置mach id的
/*
- Configurable monitor commands definitions have been moved
- to include/cmd_confdefs.h
/
include/command.h
如果要把一个变量放入.u_boot_cmd段,需要通过宏U_BOOOT_CMD实现。宏的定义如下:
#define Struct_Section attribute ((unused,section (“.u_boot_cmd”)))
#ifdef CFG_LONGHELP
#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}
#else / no long help info /
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help)
cmd_tbl_t _u_boot_cmd##name Struct_Section = {#name, maxargs, rep, cmd, usage}
#endif / CFG_LONGHELP */
“##”与“#”都是预编译操作符,“##”有字符串连接的功能,“#”表示后面紧接着的是一个字符串。
#define Struct_Section attribute ((unused,section (“.u_boot_cmd”)))
其中,unused表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息。
凡通过U_BOOT_CMD定义的cmd_tbl_t变量会全部被放在.u_boot_cmd段当中。这也是在你写的.c文件的末尾必须要写的,为了完成注册这个动作。
在文件u-boot.lds中有如下定义:
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
该段的含义为定义一个新段.u_boot_cmd。__u_boot_cmd_start为该段的第一个符号;__u_boot_cmd_end为该段的最后一个符号。
/*
- Monitor Command Table
/
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) // 简短的帮助信息/
#ifdef CFG_LONGHELP
char help; / Help message (long) / / 较详细的帮助信息/
#endif
#ifdef CONFIG_AUTO_COMPLETE
/* do auto completion on the arguments // 自动补全参数*/
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
/
common/command.c
Uboot中所有命令都是存放在这个特殊段中的。当用户输入一个命令时(需要与定义时的name变量同名),会在函数find_cmd中从__u_boot_cmd_start开始循环匹配,匹配到后就执行对应变量中的cmd项;如果直到__u_boot_cmd_end也没有发现,则匹配失败。
/***************************************************************************
- find command table entry for a command
*/
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 */
}
/
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)
{
//例如 run_command(“nand read 0x40008000 0x400000 0x300000”,0);
// run_command(“bootm 0x40008000”,0);
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;
#ifdef DEBUG_PARSER
printf (“[RUN_COMMAND] cmd[%p]=”", cmd);
puts (cmd ? cmd : “NULL”); / use puts - string may be loooong /
puts (“”\n");
#endif
clear_ctrlc(); / forget any previous Control C */
if (!cmd || !cmd) {
return -1; / empty command /
}
if (strlen(cmd) >= CFG_CBSIZE) {
puts (“## Command too long!\n”);
return -1;
}
strcpy (cmdbuf, cmd);
/ Process separators and check for invalid - repeatable commands
*/
#ifdef DEBUG_PARSER
printf (“[PROCESS_SEPARATORS] %s\n”, cmd);
#endif
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 /
#ifdef DEBUG_PARSER
printf (“token: “%s”\n”, token);
#endif
/ 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 /
//在表中查找名字为setenv的结构体,
//找到名字相同的cmd_tbl_t结构体,就可以调用cmdtp->cmd 执行动作
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;
}
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
/ avoid “bootd” recursion /
if (cmdtp->cmd == do_bootd) {
#ifdef DEBUG_PARSER
printf (“[%s]\n”, finaltoken);
#endif
if (flag & CMD_FLAG_BOOTD) {
puts (“‘bootd’ recursion detected\n”);
rc = -1;
continue;
} else {
flag |= CMD_FLAG_BOOTD;
}
}
#endif / CFG_CMD_BOOTD /
/ 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;
}
//
common/cmd_nvedit.c
U_BOOT_CMD(
saveenv, 1, 0, do_saveenv,
“saveenv - save environment variables to persistent storage\n”,
NULL
);
///
common/cmd_nvedit.c
U_BOOT_CMD(
setenv, CFG_MAXARGS, 0, do_setenv,
“setenv - set environment variables\n”,
“name value …\n”
" - set environment variable ‘name’ to ‘value …’\n"
“setenv name\n”
" - delete environment variable ‘name’\n"
);
///
一般run_command(“usb start”, 0);那么是调用cmd_usb.c里的do_usb
run_command(“fatload usb 0 0x82000000 ESHOW”, 0) ,common/cmd_fat.c ,do_fat_fsload函数
U_BOOT_CMD(
usb, 5, 1, do_usb,
“USB sub-system”,
“reset - reset (rescan) USB controller\n”
“usb stop [f] - stop USB [f]=force stop\n”
“usb tree - show USB device tree\n”
“usb info [dev] - show available USB devices\n”
“usb storage - show details of USB storage devices\n”
“usb dev [dev] - show or set current USB storage device\n”
“usb part [dev] - print partition table of one or all USB storage”
" devices\n"
“usb read addr blk# cnt - read cnt' blocks starting at block
blk#'\n”
" to memory address addr'" "usb write addr blk# cnt - write
cnt’ blocks starting at block blk#'\n" " from memory address
addr’"
);
///