前言
写文章的目的是想通过记录自己的学习过程,以便以后使用到相关的知识点可以回顾和参考。
一、命令的定义
先看一下uboot中命令是如何定义的,打开common文件夹
会发现里面有很多以cmd_xxx.c来命名的c文件, 随便打开一个c文件,里面都会有一个do_xxx的函数 和 U_BOOT_CMD宏定义, 其实uboot使用宏U_BOOT_CMD来定义命令,宏 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)
把它展开得:
cmd_tbl_t _u_boot_list_2_cmd_2_##_name __aligned(4) \
__attribute__((unused,section(".u_boot_list_2_cmd_2_"#_name)))\
{ #_name, _maxargs, _rep, _cmd, _usage, \
_CMD_HELP(_help) _CMD_COMPLETE(NULL) }
如果以exit命令为例:
U_BOOT_CMD(
exit, 2, 1, do_exit,
"exit script",
""
);
展开得:
cmd_tbl_t _u_boot_list_2_cmd_2_exit __aligned(4) \
__attribute__((unused,section(.u_boot_list_2_cmd_2_exit))) \
{ "exit", 2, 1, do_exit, "exit script", "", NULL }
-> 第1行:定义了一个cmd_tbl_t类型的变量,变量名为**_u_boot_list_2_cmd_2_exit**,此变量4字节对齐
-> 第2行:__attribute__关键字设置变量 _u_boot_list_2_cmd_2_exit 存储在 ". _u_boot_list_2_cmd_2_exit"的段中。u-boot.lds链接脚本中有一个名为“._u_boot_list ”的段,所有以_u_boot_list开头的段都存放到“._u_boot_list ”段中
->第3行:cmd_tbl_t是个结构体,所以是初始化cmd_tbl_t结构体的各个成员变量。
u-boot.lds中的“._u_boot_list ”段如下图所示:
. = ALIGN(4);
. = .;
. = ALIGN(4);
.u_boot_list : {
KEEP(*(SORT(.u_boot_list*)));
}
cmd_tbl_t结构体:
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 * 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
};
typedef struct cmd_tbl_s cmd_tbl_t;
结合上面实例代码可以得出**_u_boot_list_2_cmd_2_exit**的各个成员变量的值如下所示:
_u_boot_list_2_cmd_2_exit .name = “exit”
_u_boot_list_2_cmd_2_exit .maxargs = 2
_u_boot_list_2_cmd_2_exit .repeatable = 1
_u_boot_list_2_cmd_2_exit .cmd = do_exit
_u_boot_list_2_cmd_2_exit .usage = “exit script”
_u_boot_list_2_cmd_2_exit .help = " "
_u_boot_list_2_cmd_2_exit .complete = NULL
当在uboot的命令行中输入“exit”这个命令时,最终执行的是do_exit函数。总结一下,uboot 中使用 U_BOOT_CMD 来定义一个命令,最终的目的就是为了定义一个cmd_tbl_t 类型的变量,并初始化这个变量的各个成员。uboot 中的每个命令都存储在.u_boot_list段中,每个命令都有一个名为 do_xxx(xxx 为具体的命令名)的函数,这个 do_xxx 函数就是具体的命令处理函数。
二、自定义命令
在上面的分析中,我们知道了命令的由来,那么就可以自定义uboot的命令了。
步骤:
1、在common文件夹中建立cmd_命令.c文件
2、在cmd_命令.c文件中用U_BOOT_CMD来定义命令
3、在cmd_命令.c文件中实现命令的操作函数:do_命令
4、在common文件夹的Makefile中添加obj-y += cmd_命令.o
5、重新配置编译u-boot