Uboot如何实现控制台命令?我们从几个方面进行分析
使用
常用的命令有help、bootm等等。有的命令有参数,有的命令没参数,有的参数可以有参数也可以没参数。
例如help命令:
help //列出当前uboot所有支持的命令
help 命令 //查看指定命令的帮助
我们输入的命令help被接收后,uboot会寻找名为help的命令,并执行对应的函数,那么命令是如何被定义的?又是如何执行的?我们需要通过源码进行分析。
源码分析
我们以help命令为例进行分析。
1、命令的定义
先从文件结构上看,所有的命令源码都在uboot的common文件夹下,文件命名形式为cmd_*.c,*代表命令名字。
从代码上看,每个命令由一个cmd_tbl_t类型结构体描述。
struct cmd_tbl_s {
char *name; /* 命令名 */
int maxargs; /* 命令最多可带参数 */
int repeatable; /* 命令是否可重复执行 */
/* 实现命令函数 */
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char *usage; /* Usage message (short) */
#ifdef CFG_LONGHELP
char *help; /* Help message (long) */
#endif
#ifdef CONFIG_AUTO_COMPLETE
/* do auto completion on the arguments */
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
help命令定义如下,这是宏定义的形式,我们还原一下经过预处理之后的形式
U_BOOT_CMD(
help, CFG_MAXARGS, 1, do_help,
"help - print online help\n",
"[command ...]\n"
" - show help information (for 'command')\n"
"'help' prints online help for the monitor commands.\n\n"
"Without arguments, it prints a short usage message for all commands.\n\n"
"To get detailed help information for specific commands you can type\n"
"'help' with one or more command names as arguments.\n"
);
首先找到U_BOOT_CMD();的宏定义,这里有几个知识点,#和##作用、第一行的宏定义
1、#和##:#的作用是转换为字符串。 ##的作用是连接前后的内容
2、__attribute__ ((unused,section (".u_boot_cmd")))就是把定义的内容标记为.u_boot_cmd段。在程序连接的时候有作用。
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
经过预处理之后help命令的定义就变成了如下的形式
cmd_tbl_t __u_boot_cmd_help __attribute__ ((unused,section (".u_boot_cmd"))) = {
help,
CFG_MAXARGS,
1,
do_help,
"help - print online help\n",
"[command ...]\n"
" - show help information (for 'command')\n"
"'help' prints online help for the monitor commands.\n\n"
"Without arguments, it prints a short usage message for all commands.\n\n"
"To get detailed help information for specific commands you can type\n"
"'help' with one or more command names as arguments.\n"
}
这样看来命令定义的方式就很明显了,其他命令也是使用相同的方式定义的,接下来分析他是如何被初始化和被使用的。
2、命令的初始化和使用
在命令被定义的时候有一个段的定义就是这个__attribute__ ((unused,section (".u_boot_cmd")))。在uboot的链接脚本中有这段的定义,就是把所有使用这种方式定义的命令都连接在了一起,也就是完成了命令的初始化
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
使用则只需要检索命令名字就可以了。
了解了原理添加自定义的命令自然就不是难事了。
来源:CSDN
作者:zd845101500
链接:https://blog.csdn.net/zd845101500/article/details/104017849