您的位置:首页 > 其它

uboot命令的实现以及解析

2013-03-18 15:36 405 查看
解析run_command

1.argc = parse_line (finaltoken, argv) //解析命令的参数有几个

2.cmdtp = find_cmd(argv[0] //获取命令的结构体

3.(cmdtp->cmd) (cmdtp, flag, argc, argv) //执行命令的实现函数

在分析之前先说一个命令的结构体

1.结构体cmd_tbl_t *cmdtp;

定义如下:typedef struct cmd_tbl_s cmd_tbl_t;

struct cmd_tbl_s {
char		*name;		/* Command Name			命令的名字*/
int		maxargs;	/* maximum number of arguments	命令的最大参数的个数*/
int		repeatable;	/* autorepeat allowed?		命令是否可以重复,比如执行过一个命令后,再按下Enter重复之前的命令*/
/* Implementation function	命令的实现函数*/
int		(*cmd)(struct cmd_tbl_s *, int, int, char *[]);
char		*usage;		/* Usage message	(short)	命令的使用方法*/
#ifdef	CFG_LONGHELP
char		*help;		/* Help  message	(long)	命令的详细使用方法*/
#endif
};
重要的函数;

cmdtp = find_cmd(argv[0])//这个函数通过argv[0]也即命令的名字来找到cmd_tbl_s的结构体。

如果没有找到输入命令的结构体,则会打印错误输出信息:

Unknown command '%s' - try 'help'

下面看下函数find_cmd是如何处理的:

for (cmdtp = &__u_boot_cmd_start;
cmdtp != &__u_boot_cmd_end;
cmdtp++) {
if (strncmp (cmd, cmdtp->name, len) == 0) {
if (len == strlen (cmdtp->name))
return cmdtp;	/* full match */

cmdtp_temp = cmdtp;	/* abbreviated command ? */
n_found++;
}
}
它是在__u_boot_cmd_start与__u_boot_cmd_end段之间一一的和cmd name进行比对,如果匹配上,则返回该命令的cmdtp结构体。

其中__u_boot_cmd_start与__u_boot_cmd_end的定义是在链接脚本u-boot.lds中定义:

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;

这两个段之间放的就是uboot的命令,.u_boot_cmd段

定义如下:

#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))

这句话的意思是Struct_Section的宏定以为一个属性,这个属性转换为 .u_boot_cmd段

下面就看看Struct_Section被哪些cmd使用到了。

经过source insight搜索,发现Struct_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}
可以想象U_BOOT_CMD就是uboot命令的宏.继续使用si搜索U_BOOT_CMD,发现这个宏在很多的文件中使用,选择一个cmd_bootm.c发现:

U_BOOT_CMD(
bootm,	CFG_MAXARGS,	1,	do_bootm,
"bootm   - boot application image from memory\n",
"[addr [arg ...]]\n    - boot application image stored in memory\n"
"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
"\t'arg' can be the address of an initrd image\n"
#ifdef CONFIG_OF_FLAT_TREE
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif
);
将其展开:

cmd_tbl_t __u_boot_cmd_bootm  __attribute__ ((unused,section (".u_boot_cmd")))=
{bootm, CFG_MAXARGS, 1, do_bootm,
"bootm   - boot application image from memory\n",
"[addr [arg ...]]\n    - boot application image stored in memory\n"
"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
"\t'arg' can be the address of an initrd image\n"
#ifdef CONFIG_OF_FLAT_TREE
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif}
可以看到定义了一个类型为cmd_tbl_t的__u_boot_cmd_bootm,属性强制设为.u_boot_cmd段,这也就解释了为什么uboot命令存放在__u_boot_cmd_start 与__u_boot_cmd_end 之间的原因了。

下面自己添加一个命令的实例cmd_hello.c:

#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <zlib.h>
#include <bzlib.h>
#include <environment.h>
#include <asm/byteorder.h>

int do_hello(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
printf("Hello World\n");
return 0;
}

U_BOOT_CMD(
hello,  CFG_MAXARGS,    1,  do_hello,
"hello   - hello for test\n",
"Hello long test........\n"
);
修改Makefile,在COBJS = 后面加上cmd_hello.o重新编译即可.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: