uboot命令的实现以及解析

解析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重新编译即可.













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值