u-boot-2019 u-boot 命令分析

代码分析

u-boot源码我们知道,在u-boot中的每一个命令都是通过U_BOOT_CMDU_BOOT_CMD_COMPLETE来定义的。下面来分析分析他们的具体实现逻辑。

U_BOOT_CMD 是一个宏定义,代码在 include/command.h中。

#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)		\
	U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)

#ifdef CONFIG_CMDLINE

	#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \
		ll_entry_declare(cmd_tbl_t, _name, cmd) =			\		//此处需要注意的时这里赋值的是cmd 而非上层参数 _cmd
			U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,	\
							_usage, _help, _comp);
	
	#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) }

#else

	#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help,	\
				    _comp)				\
		_CMD_REMOVE(sub_ ## _name, _cmd)
		
	#define _CMD_REMOVE(_name, _cmd)					\
		int __remove_ ## _name(void)					\
		{								\
			if (0)							\
				_cmd(NULL, 0, 0, NULL);				\
			return 0;						\
		}

#endif /* CONFIG_CMDLINE */

ll_entry_declare 代码在include/linker_lists.h 中。

/**
 * ll_entry_declare() - Declare linker-generated array entry
 * @_type:	Data type of the entry
 * @_name:	Name of the entry
 * @_list:	name of the list. Should contain only characters allowed
 *		in a C variable name!
 *
 * This macro declares a variable that is placed into a linker-generated
 * array. This is a basic building block for more advanced use of linker-
 * generated arrays. The user is expected to build their own macro wrapper
 * around this one.
 *
 * A variable declared using this macro must be compile-time initialized.
 *
 * Special precaution must be made when using this macro:
 *
 * 1) The _type must not contain the "static" keyword, otherwise the
 *    entry is generated and can be iterated but is listed in the map
 *    file and cannot be retrieved by name.
 *
 * 2) In case a section is declared that contains some array elements AND
 *    a subsection of this section is declared and contains some elements,
 *    it is imperative that the elements are of the same type.
 *
 * 3) In case an outer section is declared that contains some array elements
 *    AND an inner subsection of this section is declared and contains some
 *    elements, then when traversing the outer section, even the elements of
 *    the inner sections are present in the array.
 *
 * Example:
 *
 * ::
 *
 *   ll_entry_declare(struct my_sub_cmd, my_sub_cmd, cmd_sub) = {
 *           .x = 3,
 *           .y = 4,
 *   };
 */
#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)))

通过上面的代码可知U_BOOT_CMD就是定义了一个类型为cmd_tbl_t的结构体数据并赋值。并且U_BOOT_CMDU_BOOT_CMD_COMPLETE的精减版,实现上U_BOOT_CMD 是调用U_BOOT_CMD_COMPLETE。区别在于U_BOOT_CMDcmd_tbl_t的结构体中的complete成员赋了空值。U_BOOT_CMD_COMPLETE则是对cmd_tbl_t的结构体的所有成员都有赋值。

cmd_tbl_tinclude/command.h中定义

typedef struct cmd_tbl_s	cmd_tbl_t;

struct cmd_tbl_s {
	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_s *cmd, int flags, int argc,
				   char * const argv[], int *repeatable);
					/* Implementation function	*/
	int		(*cmd)(struct cmd_tbl_s *, int, int, char * const []);
	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
};

U_BOOT_CMD 中的各个参数,其实对应的就是cmd_tbl_s 结构体里面成员变量。

U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) 
_name		:命令名称
_maxargs	:接受最大的参数个数
_rep		:重复
_cmd		:命令实现函数
_usage		:使用说明(短说明)
_help		:使用说明

具体命令分析

envprintenv 为例, 这两个命令为别通过U_BOOT_CMDU_BOOT_CMD_COMPLETE来定义。其代码在cmd/nvedit.c中,

U_BOOT_CMD(
	env, CONFIG_SYS_MAXARGS, 1, do_env,
	"environment handling commands", env_help_text
);

通过宏展开后可知U_BOOT_CMD就是定义了一个名为 _u_boot_list_cmd_2_env类型为cmd_tbl_t的结构体数据并赋值。

 cmd_tbl_t _u_boot_list_cmd_env __aligned(4)        \
            __attribute__((unused,section(".u_boot_list_2_cmd_2_env))) = \
			{ env, 16,                    \
             1 ? cmd_always_repeatable : cmd_never_repeatable,    \
             do_env, "environment handling commands", env_help_text  }
U_BOOT_CMD_COMPLETE(
	printenv, CONFIG_SYS_MAXARGS, 1,	do_env_print,
	"print environment variables",
	"[-a]\n    - print [all] values of all environment variables\n"
#if defined(CONFIG_CMD_NVEDIT_EFI)
	"printenv -e [name ...]\n"
	"    - print UEFI variable 'name' or all the variables\n"
#endif
	"printenv name ...\n"
	"    - print value of environment variable 'name'",
	var_complete
);

通过宏展开后可知U_BOOT_CMD_COMPLETE就是定义了一个名为 _u_boot_list_2_cmd_2_printenv类型为cmd_tbl_t的结构体数据并赋值。

 cmd_tbl_t _u_boot_list_2_cmd_2_printenv __aligned(4)        \
            __attribute__((unused, section(".u_boot_list_2_cmd_2_printenv))) = \
			{ printenv, 16,                    \
             1 ? cmd_always_repeatable : cmd_never_repeatable,    \
             do_env_print, 
			"print environment variables", 
			"[-a]\n    - print [all] values of all environment variables\n"
			#if defined(CONFIG_CMD_NVEDIT_EFI)
				"printenv -e [name ...]\n"
				"    - print UEFI variable 'name' or all the variables\n"
			#endif
				"printenv name ...\n"
				"    - print value of environment variable 'name'",
				var_complete}

通过nmreadelf 查看相应的符号表

$ nm u-boot | grep _u_boot_list_2_cmd_2_env
9fca6818 D _u_boot_list_2_cmd_2_env

$ readelf -s u-boot | grep _u_boot_list_2_cmd_2_env
  4671: 9fca6818    28 OBJECT  GLOBAL DEFAULT    8 _u_boot_list_2_cmd_2_env

命令调用流程

run_command common/cli.c
	 cli_simple_run_command	common/cli_simple.c
		cli_simple_parse_line 				分析参数
		cmd_process		common/command.c	
			find_cmd 						根据name查找命令,在section .u_boot_list_2_cmd_1和.u_boot_list_2_cmd_3 之间查找
			cmd_call						执行命令

在u-boot中添加命令

  1. common 建立cmd_xx.c 文件,参考其他文件如 cmd_bootm.c 来添加头文件
  2. U_BOOT_CMDU_BOOT_CMD_COMPLETE 来定义命令
  3. 实现命令的操作do_xx 函数
  4. common/cmd_xx.c 加入common/Makefile中 COBJS += cmd_xx.o
  5. 重新配置编译u-boot
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值