uboot 命令具体是如何实现的,我看了一部分,现在卡住了;求高人指点; 我的QQ:436035433
我的全部理解如下:1.从start.S开始,最后跳转到start_armboot执行。start_armboot函数先完成一些设备的初始化工作,最后是一个死循环:循环调用...
我的全部理解如下:
1.从start.S开始,最后跳转到start_armboot执行。start_armboot函数先完成一些设备的初始化工作,最后是一个死循环:循环调用main_loop ();
2.main_loop ()函数中,调用readline ()读取命令行到console_buffer,再把console_buffer复制到lastcommand中去,还要设置flag,最后调用run_command (lastcommand, flag)函数。
3.run_command (lastcommand, flag)函数中,首先定义cmd_tbl_t *cmdtp,再解析命令行。再调用find_cmd(argv[0])函数,其中argv[0]应该是命令本身,参数已经被剥离,这个函数返回的是一个cmd_tbl_t结构体,就是说每个命令都有一个cmd_tbl_t结构体相对应。cmd_tbl_t结构体的大致定义如下:
struct cmd_tbl_s {
char *name; /* Command Name */
…
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
…
};
typedef struct cmd_tbl_s cmd_tbl_t;
name是命令本身,cmd是处理函数。
run_command函数最后调用(cmdtp->cmd) (cmdtp, flag, argc, argv)完成命令。最后u-boot逐层返回到main_loop中去,重复以上步骤。
以上应该是uboot命令实现的一个大致过程。
但是关于,find_cmd函数的实现,我有疑问
###############################################################
关于find_cmd()函数的实现。
定义如下:
cmd_tbl_t *find_cmd (const char *cmd)
{
int len = &__u_boot_cmd_end - &__u_boot_cmd_start;
return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
}
其中,find_cmd_tbl的原型是
cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
看源代码可知,这个函数是在一个以table为起始地址,长度为len的cmd_tbl_t结构体数组中搜索name为cmd的cmd_tbl_t结构体,搜索到后返回这个结构体的地址,搜索不到表示没有这个命令。
所以,根据如下2句
int len = &__u_boot_cmd_end - &__u_boot_cmd_start;
return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
可以看出,应该有一个起始地址为&__u_boot_cmd_start,终止地址为&__u_boot_cmd_end的全局的cmd_tbl_t数组;这个数组中涵盖了u_boot支持的全部命令。
问题就在:这个数组我在u_boot源代码中没有找到。__u_boot_cmd_start和__u_boot_cmd_end是在哪里定义的? 展开
1.从start.S开始,最后跳转到start_armboot执行。start_armboot函数先完成一些设备的初始化工作,最后是一个死循环:循环调用main_loop ();
2.main_loop ()函数中,调用readline ()读取命令行到console_buffer,再把console_buffer复制到lastcommand中去,还要设置flag,最后调用run_command (lastcommand, flag)函数。
3.run_command (lastcommand, flag)函数中,首先定义cmd_tbl_t *cmdtp,再解析命令行。再调用find_cmd(argv[0])函数,其中argv[0]应该是命令本身,参数已经被剥离,这个函数返回的是一个cmd_tbl_t结构体,就是说每个命令都有一个cmd_tbl_t结构体相对应。cmd_tbl_t结构体的大致定义如下:
struct cmd_tbl_s {
char *name; /* Command Name */
…
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
…
};
typedef struct cmd_tbl_s cmd_tbl_t;
name是命令本身,cmd是处理函数。
run_command函数最后调用(cmdtp->cmd) (cmdtp, flag, argc, argv)完成命令。最后u-boot逐层返回到main_loop中去,重复以上步骤。
以上应该是uboot命令实现的一个大致过程。
但是关于,find_cmd函数的实现,我有疑问
###############################################################
关于find_cmd()函数的实现。
定义如下:
cmd_tbl_t *find_cmd (const char *cmd)
{
int len = &__u_boot_cmd_end - &__u_boot_cmd_start;
return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
}
其中,find_cmd_tbl的原型是
cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len);
看源代码可知,这个函数是在一个以table为起始地址,长度为len的cmd_tbl_t结构体数组中搜索name为cmd的cmd_tbl_t结构体,搜索到后返回这个结构体的地址,搜索不到表示没有这个命令。
所以,根据如下2句
int len = &__u_boot_cmd_end - &__u_boot_cmd_start;
return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);
可以看出,应该有一个起始地址为&__u_boot_cmd_start,终止地址为&__u_boot_cmd_end的全局的cmd_tbl_t数组;这个数组中涵盖了u_boot支持的全部命令。
问题就在:这个数组我在u_boot源代码中没有找到。__u_boot_cmd_start和__u_boot_cmd_end是在哪里定义的? 展开
1个回答
展开全部
那u-boot的那些个关于命令的结构体到底从何而来呢?在include/command.h里定义了这样的宏:
#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}
第
二个宏展开便定义了悔卜一个代表u-boot命令的结构体。也就是说定义了一个变量,并赋与其初值。关键在于Struc_Section,它被展开后成了
__attribute__
((unused,section(".u_boot_cmd")))。也就是说,每个变量(占内存!)都放在.u_boot_cmd段里。它们还被加上
了unused的属性,应该是为了平息编译器的警告。确实,没有任何代码引用过它们!!如果这些变量被放在一个显示声明的数组里,那么,每增加一个命令都
得去更改数组的定义。然后,通过这种方法,各人想要增加新的命令时,只需用上面的这个宏即可。这些表示命令的结构体被统一放在.u_boot_cmd段
里,链接脚本里又有:
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
即,
把所有待链接文件里u_boot_cmd段合并在一起生成一个大的.u_boot_cmd段,并且用__u_boot_cmd_start与
__u_boot_cmd_end两个符号标识这块内存的首尾边界。这样,不用大家去修改某一文件的代码(为了改变数组的定义),而是像数据库一样,各个神祥
提供自己的信息。借由编译器与链接器生成这个“数据库”,操作数据时对“数据库”进行查询即可。正是一个月前看《计算机程序构造与解释》时看到的
“Data Direct”(好像是这么说)。在Grub及内核里也用了这样机制。碧瞎穗
参考:http://blog.163.com/lijiji_1515/blog/static/12687744620114522449739/
#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}
第
二个宏展开便定义了悔卜一个代表u-boot命令的结构体。也就是说定义了一个变量,并赋与其初值。关键在于Struc_Section,它被展开后成了
__attribute__
((unused,section(".u_boot_cmd")))。也就是说,每个变量(占内存!)都放在.u_boot_cmd段里。它们还被加上
了unused的属性,应该是为了平息编译器的警告。确实,没有任何代码引用过它们!!如果这些变量被放在一个显示声明的数组里,那么,每增加一个命令都
得去更改数组的定义。然后,通过这种方法,各人想要增加新的命令时,只需用上面的这个宏即可。这些表示命令的结构体被统一放在.u_boot_cmd段
里,链接脚本里又有:
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
即,
把所有待链接文件里u_boot_cmd段合并在一起生成一个大的.u_boot_cmd段,并且用__u_boot_cmd_start与
__u_boot_cmd_end两个符号标识这块内存的首尾边界。这样,不用大家去修改某一文件的代码(为了改变数组的定义),而是像数据库一样,各个神祥
提供自己的信息。借由编译器与链接器生成这个“数据库”,操作数据时对“数据库”进行查询即可。正是一个月前看《计算机程序构造与解释》时看到的
“Data Direct”(好像是这么说)。在Grub及内核里也用了这样机制。碧瞎穗
参考:http://blog.163.com/lijiji_1515/blog/static/12687744620114522449739/
微测检测5.10
2023-05-10 广告
2023-05-10 广告
您好!建议咨 深圳市微测检测有限公司,已建立起十余个专业实验室,企业通过微测检测就可以获得一站式的测试与认 证解决方案;(EMC、RF、MFi、BQB、QI、USB、安全、锂电池、快充、汽车电子EMC、汽车手机互 联、语音通话质量),认证遇...
点击进入详情页
本回答由微测检测5.10提供
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询