uboot命令体系

目录

一、命令体系基础知识

1.1、命令结构体

1.2、命令的管理方式

二、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 );
    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dz小伟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值