Bootstrap

<Linux>u-boot 命令分析并编写一个命令

一、run_command函数

前面我们说到,u-boot的核心就是run_command这个函数,那么我们就来分析一下这个函数具体要做那些事情。


1321行,对命令进行解析。举个例子:

比如说,md.w 0这个命令,它就能解析成为:Argv[0]=”md” Argv[1]=”0

那么这个代表什么意思呢?接着往下看:

1327行,这个函数提取1321行解析后的参数,那就先跟踪cmdtp这个变量是如何定义的:cmd_tbl_t *cmdtp;继续跟踪这个结构体:


从这个结构体的定义中,我们可以看到,它分别包含命令的名字,最大的参数,是否可重复等。那么我们上面所举的例子中,md就代表这个命令的名字,0是其中一个参数。回到run_command这个函数的1327行。这行代码的通过一个find_command这个函数对命令的名字进行比较。那我们进去看一下find_command这个函数具体要做什么:


在for循环里面,从u-boot_command_start到u-boot_command_end之间寻找,也就是比较输入的命令名和原来参数中的命令名是否一致,若是一致,就返回这结构体,若是不一致,就指向下一个。

那么这个时候问题来了,u-boot_command_star和u-boot_command_end到底是什么?请参考前一篇我转载博客《Linux链接脚本分析》,在链接脚本中有定义:

_u-boot_command_start=.;

.u_boot_cmd:{*(..u_boot_cmd)}

_u-boot_command_end=.;

那么我们继续来搜索一下.u_boot_cmd,其位于command.h(include,定义如下:

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

也就是说,定义好的命令放在u_boot_cmd里面,每次输入命令时都会从这个段里面寻找是否有名字相同的命令,若是找到,就返回这个结构体,也就是命令的具体消息和要处理的内容。若是没有找到就打印相关的信息。

二、bootm命令。

通过前面几篇博客的分析,我们知道,u-boot要启动Linux内核是通过bootm这个命令实现的。那么bootm到底是什么?我们可以来搜索一下


接着再来搜下U_BOOT_CMD这个宏:


对比上述两段代码:

首先98行中的name是命令的名字,也就是bootm ,第二个参数是struct_section 对应的就是我们上面分析的结构体。这就相当于,给这个结构体的成员赋值:

name=bootm;   maxarg=CFG_MAXARG;  rep=1; cmd=do_bootm,usage和help分别对应下面的字符串。

我们再来看一下上面说到的Struct_Section  的定义:

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

从这个定义中我们可以看到,u_boot_cmd这个命令会被强制转换成这个结构体,由此,把所有的命令都保存在.u_boot_cmd:{*(..u_boot_cmd)}这个段里面。每次只要比较输入命令的名字和这个段中保存的命令名字即可匹配(上面run_command中的for函数)。

三、添加一个命令

通过上面的分析,我们知道命令的格式以及如何实现,接下来就可以仿照这样的格式自己编写一个命令。

1、首先写这个命令要处理的函数:

do_test (cmdtp, flag, argc, argv)

{

printf("this is a test for adding a u-boot command\n");

}

2、接着对U_BOOT_CMD进行赋值:

U_BOOT_CMD(
  test, CFG_MAXARGS, 1,do_test ,
  “this is my test command usage.....\n"

"this is the long help msg of my test.....\n"

);

这就完成了一个简单u-boot命令的编写,我们只要把这个c文件加到u-boot工程下的common目录下编译即可。

其他的命令可以仿照这个格式来写。


;