uboot之run_command函数U_BOOT_CMD及命令表

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’"
);
///

  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值