uboot下用do_run()函数来执行U_BOOT_CMD定义的命令

          今天研究了一下uboot中怎么用do_run()函数来执行定义好的一些命令,发现其实也挺简单的,关键是得把do_run函数的几个参数吃透,这几个参数都是由uboot commmod 的cmd_tbl_s结构体决定的,U_BOOT_CMD的宏定义也取决于它,如下:

#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}


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    CONFIG_SYS_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
}

        对比两者后很容易就明白了怎样去定义一个uboot下的命令

        接下来看看do_run函数的定义(在../boot/common/main.c下):

#if defined(CONFIG_CMD_RUN)
int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
    int i;

    if (argc < 2) {                                 //参数个数小于2则提示重新输入
        cmd_usage(cmdtp);
        return 1;
    }

    for (i=1; i<argc; ++i) {
        char *arg;

        if ((arg = getenv (argv[i])) == NULL) {
            printf ("## Error: \"%s\" not defined\n", argv[i]);
            return 1;
        }
#ifndef CONFIG_SYS_HUSH_PARSER
        
    
        if (run_command (arg, flag) == -1){     //调用run_command函数,先查找命令,然后执行命令
            return 1;
        }
#else
        if (parse_string_outer(arg,
            FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0){
            return 1;
        }
#endif
    }
    return 0;
}

      其中第一个参数cmd_tbl_t * cmdtp为Command Table,即命令表参数,该结构体的定义在common.h下,一般设为NULL。


      第二个参数int flag为Command Flag,用来标志命令来自哪里,跟它相关的有两个宏:

#define CMD_FLAG_REPEAT        0x0001    /* repeat last command        */
#define CMD_FLAG_BOOTD        0x0002    /* command is from bootd    */

       它被传给run_command (const char *cmd, int flag),一般设为0,表示bootd,设为1则表示repeat(递归式)。

        第三个int argc表示输入参数的个数,小于2则提示重新输入。第三个char *argv[]是输入命令字符的指针,用来传递定义好的指针数组。下面通过一个简单的例子来说明怎么使用do_run()函数,yaffs2ram的作用是实现从yaffs文件系统中拷贝logo.bmp到指定的RAM地址上:

int yaffs2ram(void)

{

  char *argv[5];   //定义5个指针数组,用来存放各个字符命令的指针

  char buf[100];

  char *name_buf = "/logo/logo.bmp";

  int ret;

   if(!yaffs_file_exist(name_buf))//检查文件系统中是否存在logo.bmp
    {
        dprintf_line("%s NOT Exist!",name_buf);
        return -1;
    }


//把yrdm  /logo/logo.bmp  0x8000_0000命令传给buf(loadaddr为环境变量)

    sprintf(buf,"yrdm %s ${loadaddr}",name_buf);

    setenv("upgradetemp", buf);//设置临时环境变量upgradetemp的值
    argv[0] = "run";
    argv[1] = "upgradetemp";
    argv[2] = NULL;
    ret = do_run(NULL, 0, 2, argv);
   //运行yrdm  /logo/logo.bmp  0x8000_0000命令,把logo.bmp拷贝到0x8000_000地址上

    if ( ret == 1)

       {

         printf("do_run error!")

        return -1;

         }

    setenv("upgradetemp", NULL); //清空临时环境变量的值

return 0;

}


注:由于do_yrdm函数规定输入命令的个数必须为3(如下所示),所以我们加了一个argv[2] = NULL命令,该命令什么都不做。

U_BOOT_CMD(
    yrdm,   3,  0,  do_yrdm,
    "read file to memory from yaffs",
    "filename offset"
);


你可能感兴趣的:(uboot下用do_run()函数来执行U_BOOT_CMD定义的命令)