前言
uboot 如果最后走到了用户交互模式, 则会循环在 main_loop 函数( 位于common/ main. c, main. c中的出口函数) 中
main_loop 被 start_armboot 函数调用
main_loop 流程
会解析bootdelay变量, 并延时
在延时中如果被中断, 则会执行一个循环, 循环中readline并执行 run_command
如果没被中断, 会解析变量boot_cmd里面的变量, 并执行
run_command
1 / 判断了长度
2 / 依据; 截取字符串, 得到一个一个的命令
3 / 去掉宏, 得到一个解析过的命令
4 / 分析一个命令得到 命令名 和 参数
5 / 依次将 命令名 和 结构体数组 中的结构体成员的第一个参数 name 进行比较, 判断是否相等. 相等说明是合法命令
6 / 判断合法命令的 参数个数 是否合法
7 / 调用命令
在上述序列中, 步骤 5 最难理解
命令及命令集的遍历解析
typedef struct cmd_tbl_s cmd_tbl_t;
struct cmd_tbl_s {
char * name;
int maxargs;
int repeatable;
int ( * cmd) ( struct cmd_tbl_s * , int , int , char * [ ] ) ;
char * usage;
#ifdef CONFIG_SYS_LONGHELP
char * help;
#endif
#ifdef CONFIG_AUTO_COMPLETE
int ( * complete) ( int argc, char * argv[ ] , char last_char, int maxv, char * cmdv[ ] ) ;
#endif
} ;
其实步骤5 中的结构体数组并没有在程序中定义.
而是依靠段的用法将这些结构体存到了指定的段中, 然后在链接的时候将各个文件的这个段 连接到一个输出文件的 段中, 也就是将这些结构体放到了一起, 所以就像我之前说的结构体数组.
下面分为两个部分说
1 / 输入文件中的段
它是用宏函数 U_BOOT_CMD ( name, maxargs, rep, cmd, usage, help) , 宏函数的定义在include/ command. h中
#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}
bootm 解析
假设这个命令是bootm , U_BOOT_CMD ( bootm, 16 , 1 , do_bootm, “bootm-- usage”, “help”)
最后展开会成为这个样子
cmd_tbl_t __u_boot_cmd_ bootm __attribute__ ( ( unused, section ( ".u_boot_cmd" ) ) ) = { “bootm”, 16 , 1 , do_bootm, “bootm-- usage”}
表示
定义一个结构体 变量
类型为 cmd_tbl_t
初始化为{ “bootm”, 16 , 1 , do_bootm, “bootm-- usage”}
变量地址 在 段名 ".u_boot_cmd" 中, 而到底在段中的什么位置, 依赖于链接顺序
2 / 输出文件中的段
链接的时候会读取链接文件include/ u- boot/ u- boot. lds
按照链接顺序 依次 将输入文件中的 ".u_boot_cmd" 段 放入 输出文件中的 ".u_boot_cmd" 段
__u_boot_cmd_start = . ;
. u_boot_cmd : { * ( . u_boot_cmd) }
__u_boot_cmd_end = . ;
. u_boot_cmd段开始的位置符号为 __u_boot_cmd_start , 段结束地址符号为 __u_boot_cmd_end
main_loop
readline
run_command
判断了长度, 截取字符串, 将宏去掉, 得到 "bootm"
cmtp = find_cmd ( ) ;
cmdtp-> 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) ;
}
cmd_tbl_t * find_cmd_tbl ( const char * cmd, cmd_tbl_t * table, int table_len)
{
cmd_tbl_t * cmdtp;
cmd_tbl_t * cmdtp_temp = table;
const char * p;
int len;
int n_found = 0 ;
len = ( ( p = strchr ( cmd, '.' ) ) == NULL ) ? strlen ( cmd) : ( p - cmd) ;
for ( cmdtp = table;
cmdtp != table + table_len;
cmdtp++ ) {
if ( strncmp ( cmd, cmdtp-> name, len) == 0 ) {
if ( len == strlen ( cmdtp-> name) )
return cmdtp;
cmdtp_temp = cmdtp;
n_found++ ;
}
}
if ( n_found == 1 ) {
return cmdtp_temp;
}
return NULL ;
}
-- --
并执行
if ( ( cmdtp-> cmd) ( cmdtp, flag, argc, argv) != 0 ) {
rc = - 1 ;
}