uboot命令体系

简介: 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 );

相关实践学习
分布式链路追踪Skywalking
Skywalking是一个基于分布式跟踪的应用程序性能监控系统,用于从服务和云原生等基础设施中收集、分析、聚合以及可视化数据,提供了一种简便的方式来清晰地观测分布式系统,具有分布式追踪、性能指标分析、应用和服务依赖分析等功能。 分布式追踪系统发展很快,种类繁多,给我们带来很大的方便。但在数据采集过程中,有时需要侵入用户代码,并且不同系统的 API 并不兼容,这就导致了如果希望切换追踪系统,往往会带来较大改动。OpenTracing为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。Skywalking基于OpenTracing规范开发,具有性能好,支持多语言探针,无侵入性等优势,可以帮助我们准确快速的定位到线上故障和性能瓶颈。 在本套课程中,我们将全面的讲解Skywalking相关的知识。从APM系统、分布式调用链等基础概念的学习加深对Skywalking的理解,从0开始搭建一套完整的Skywalking环境,学会对各类应用进行监控,学习Skywalking常用插件。Skywalking原理章节中,将会对Skywalking使用的agent探针技术进行深度剖析,除此之外还会对OpenTracing规范作整体上的介绍。通过对本套课程的学习,不止能学会如何使用Skywalking,还将对其底层原理和分布式架构有更深的理解。本课程由黑马程序员提供。
目录
相关文章
|
3月前
|
存储 运维 Linux
Linux内核学习(三):Bootloader的特种兵-Uboot(一)
Linux内核学习(三):Bootloader的特种兵-Uboot(一)
40 0
|
20天前
|
存储 Ubuntu Linux
嵌入式Linux系统中根文件系统构建方式
嵌入式Linux系统中根文件系统构建方式
74 0
|
8月前
|
存储 数据库
飞腾uboot命令简单介绍
飞腾uboot命令简单介绍
455 0
飞腾uboot命令简单介绍
|
11月前
|
Linux 开发者
Linux设备驱动开发3-Kconfig构建系统
Linux设备驱动开发3-Kconfig构建系统
|
存储
龙芯2K1000内核及文件系统烧写流程(恢复Boot内核引导配置及分区)
龙芯2K1000内核及文件系统烧写流程(恢复Boot内核引导配置及分区)
388 0
龙芯2K1000内核及文件系统烧写流程(恢复Boot内核引导配置及分区)
|
Shell Linux Perl
|
Linux Shell 测试技术
在tinycolinux上组建子目录引导和混合32位64位的rootfs系统
本文关键字:mount subdirectory as linux root,boot linux from root subdirectory,从子目录引导linux root,separated system and usr extend under linux root
247 0
在tinycolinux上组建子目录引导和混合32位64位的rootfs系统
|
Linux Shell Go
一个设想,在统一bios/uefi firmware,及内存中的firmware中为pebuilder.sh建立不死booter
本文关键字:firmware in RAM' replacements for UEFI firmware,虚拟efi,编译类colinux的linuxboot
218 0
一个设想,在统一bios/uefi firmware,及内存中的firmware中为pebuilder.sh建立不死booter