uboot命令体系

举报
dz小伟 发表于 2022/11/02 19:38:37 2022/11/02
【摘要】 一、命令体系基础知识每一个uboot的命令对应一个函数do_命令名字,例如do_bootm命令是可以传参的,参数以argc&argv传给函数例如:int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);uboot的命令体系在工作时,一个命令对应一个cmd_tbl结构体的一个实例,然后uboot支持...

一、命令体系基础知识


每一个uboot的命令对应一个函数do_命令名字,例如do_bootm
命令是可以传参的,参数以argc&argv传给函数
例如:int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
uboot的命令体系在工作时,一个命令对应一个cmd_tbl结构体的一个实例,然后uboot支持多少个命令,就需要多少个结构体实例。uboot的命令体系把这些结构体实例管理起来,当用户输入了一个命令时,uboot会去这些结构体实例中查找(查找方法和存储管理的方法有关)。如果找到则执行命令,如果未找到则提示命令未知。
1.1、命令结构体
命令结构体cmd_tbl
struct cmd_tbl {
    char        *name;        /* Command Name            */
    int        maxargs;    /* maximum number of arguments    */
                    /*
                     * Same as ->cmd() except the command
                     * tells us if it can be repeated.
                     * Replaces the old ->repeatable field
                     * which was not able to make
                     * repeatable property different for
                     * the main command and sub-commands.
                     */
    int        (*cmd_rep)(struct cmd_tbl *cmd, int flags, int argc,
                   char *const argv[], int *repeatable);
                    /* Implementation function    */
    int        (*cmd)(struct cmd_tbl *cmd, int flags, int argc,
                   char *const argv[]);
    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 *const argv[],
                    char last_char, int maxv, char *cmdv[]);
#endif
};

name:命令名称,字符串格式
maxargs:命令最多可以接收多少个参数
cmd_rep:指示这个命令是否可重复执行
cmd:函数指针,命令对应的函数的函数指针
usage:命令的短帮助信息
help:命令的长帮助信息
complete:函数指针,指向这个命令的自动补全的函数
1.2、命令的管理方式
管理方式:数组,链表等
uboot管理方式是:通过自定义段,实现

给命令结构体实例附加特定段属性(用户自定义段),链接时将带有该段属性的内容链接在一起排列(挨着的,不会夹杂其他东西,也不会丢掉一个带有这种段属性的,但是顺序是乱序的)。
uboot重定位时将该段整体加载到DDR中。加载到DDR中的uboot镜像中带有特定段属性的这一段其实就是命令结构体的集合,有点像一个命令结构体数组。
段起始地址和结束地址(链接地址、定义在u-boot.lds中)决定了这些命令集的开始和结束地址。
 . = ALIGN(8);
 . = .;
 . = ALIGN(8);
 .u_boot_list : {
  KEEP(*(SORT(.u_boot_list*)));
 }
U_BOOT_CMD宏:位置common/command.h
 
U_BOOT_CMD(
    bootm,    CONFIG_SYS_MAXARGS,    1,    do_bootm,
    "boot application image from memory", bootm_help_text
);
 
//U_BOOT_CMD 是 U_BOOT_CMD_COMPLETE 的特例 ,多了一个NULL参数
#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)        \
    U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)
 
//用到了ll_entry_declare和U_BOOT_CMD_MKENT_COMPLETE
// U_BOOT_CMD替换后
//struct cmd_tbl _u_boot_list_2_cmd_2_name __aligned(4) __attribute__((unused)) __section(".u_boot_list_2_"cmd"_2_"name) = { #name, maxargs, rep, cmd, usage, help NULL }
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
    ll_entry_declare(struct cmd_tbl, _name, cmd) =            \
        U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,    \
                        _usage, _help, _comp);
 
//ll_entry_declare,位置在include/linker_lists.h 中,定义如下
//定义了一个 cmd_tbl 变量,
//“##_name”就是用_name 的值来替换,“ # ” 表示将 _name 传递过来的值字符串化
#define ll_entry_declare(_type, _name, _list)                \
    _type _u_boot_list_2_##_list##_2_##_name __aligned(4)        \
            __attribute__((unused))                \
            __section(".u_boot_list_2_"#_list"_2_"#_name)
 
#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,        \
                _usage, _help, _comp)            \
        { #_name, _maxargs,                    \
         _rep ? cmd_always_repeatable : cmd_never_repeatable,    \
         _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) }
 

替换后:
struct cmd_tbl _u_boot_list_2_cmd_2_name __aligned(4) __attribute__((unused)) __section(".u_boot_list_2_"cmd"_2_"name) = { #name, maxargs, rep, cmd, usage, help NULL }


二、uboot命令体系执行


cli_loop函数,就是一个获取命令、解析命令、执行命令的过程参考博文
位置:common/cli.c
cmd_process函数,就是查找执行处理命令的函数
位置:common/command.c
enum command_ret_t cmd_process(int flag, int argc, char *const argv[],
                   int *repeatable, ulong *ticks)
{
    enum command_ret_t rc = CMD_RET_SUCCESS;
    struct cmd_tbl *cmdtp;
 
#if defined(CONFIG_SYS_XTRACE)
    char *xtrace;
 
    xtrace = env_get("xtrace");
    if (xtrace) {
        puts("+");
        for (int i = 0; i < argc; i++) {
            puts(" ");
            puts(argv[i]);
        }
        puts("\n");
    }
#endif
 
    /* Look up command in command table */
    cmdtp = find_cmd(argv[0]);
    if (cmdtp == NULL) {
        printf("Unknown command '%s' - try 'help'\n", argv[0]);
        return 1;
    }
 
    /* found - check max args */
    if (argc > cmdtp->maxargs)
        rc = CMD_RET_USAGE;
 
#if defined(CONFIG_CMD_BOOTD)
    /* avoid "bootd" recursion */
    else if (cmdtp->cmd == do_bootd) {
        if (flag & CMD_FLAG_BOOTD) {
            puts("'bootd' recursion detected\n");
            rc = CMD_RET_FAILURE;
        } else {
            flag |= CMD_FLAG_BOOTD;
        }
    }
#endif
 
    /* If OK so far, then do the command */
    if (!rc) {
        int newrep;
 
        if (ticks)
            *ticks = get_timer(0);
        rc = cmd_call(cmdtp, flag, argc, argv, &newrep);
        if (ticks)
            *ticks = get_timer(*ticks);
        *repeatable &= newrep;
    }
    if (rc == CMD_RET_USAGE)
        rc = cmd_usage(cmdtp);
    return rc;
}

find_cmd查找命令,位置common/command.c
struct cmd_tbl *find_cmd(const char *cmd)
{
    struct cmd_tbl *start = ll_entry_start(struct cmd_tbl, cmd); //命令集的头
    const int len = ll_entry_count(struct cmd_tbl, cmd); //命令集长度
    return find_cmd_tbl(cmd, start, len); //查找命令
}
cmd_call:执行命令
static int cmd_call(struct cmd_tbl *cmdtp, int flag, int argc,
            char *const argv[], int *repeatable)
{
    int result;
 
    result = cmdtp->cmd_rep(cmdtp, flag, argc, argv, repeatable);
    if (result)
        debug("Command failed, result=%d\n", result);
    return result;
}

三、添加命令


在u-boot-2022.01/cmd下,新建文件xw.c
可以cp里面的echo.c文件
在common/cmd/Makefile中添加上xw.o,目的是让Make在编译时编译链接进去
xw.c
    #include <common.h>
  8 #include <command.h>
  9 
 10 static int do_xw(struct cmd_tbl *cmdtp, int flag, int argc,
 11                    char *const argv[])
 12 {
 13         if (argc > 1) {
 14                 printf("argc>1\n");
 15         }else{
 16                 printf("xw do_xw zhixing\n");
 17         }
 18 
 19         return 0;
 20 }
 21 
 22 U_BOOT_CMD(
 23         xw, 1, 1, do_xw,
 24         "Custom Commands xw",
 25         "Custom Commands xw!!!"
 26 );

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。