uboot命令的实现以及解析

来源:互联网 发布:开源网络监控工具 编辑:程序博客网 时间:2024/05/17 06:42

解析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命令的名字*/intmaxargs;/* maximum number of arguments命令的最大参数的个数*/intrepeatable;/* autorepeat allowed?命令是否可以重复,比如执行过一个命令后,再按下Enter重复之前的命令*//* Implementation function命令的实现函数*/int(*cmd)(struct cmd_tbl_s *, int, int, char *[]);char*usage;/* Usage message(short)命令的使用方法*/#ifdefCFG_LONGHELPchar*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重新编译即可.