find_cmd函数分析

 一、概述 

1、函数位置

  common/command.c 

2、函数功能分析   

  解析命令的关键环节是如何根据输入命令查找对应命令的信息,从而跳转到对应命令的函数处执行程序。这必然涉及到如何存放命令的详细信息这个问题。因为一种存法,对应一种查法,进而取法。也就是说,实际上是两个问题:

(1)命令的详细信息是如何存放的

(2)如何在命令存储区查找是否有与输入命令匹配的命令

    就这两个问题,我们来分别分析uboot的设计方法。

二、".u_boot_cmd"环境变量存储区

1、命令详细信息存储结构体

struct cmd_tbl_s {
  char     *name;     /* Command Name     */
  int     maxargs;    /* maximum number of arguments    */
  int     repeatable;    /* autorepeat allowed?     */
  /* 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
  #ifdef CONFIG_AUTO_COMPLETE
  /* do auto completion on the arguments */
  int     (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
  #endif
};

typedef struct cmd_tbl_s    cmd_tbl_t;

2、把命令的详细信息安排在".u_boot_cmd"存储区

(1)相关声明

#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}

##    代表字符串连接符

#      代表转换为字符串

(2)实例说明

int do_hello (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{

}

U_BOOT_CMD(
md, 3, 1, do_hello,
"md - memory display
",
"[.b, .w, .l] address [# of objects]
 - memory display
"
);
U_BOOT_CMD(
hello, 3, 1, do_hello,
"md - memory display
",
"[.b, .w, .l] address [# of objects]
 - memory display
"
);
展开后为:
cmd_tbl_t __u_boot_cmd_hello
__attribute__ ((unused,section (".u_boot_cmd"))) 
={
    "hello", 3, 1, do_hello,
    "md - memory display
",
    "[.b, .w, .l] address [# of objects]
 - memory display
"
};

    可见,实际上就是定义了一个cmd_tbl_t类型的变量"__u_boot_cmd_hello",并且强制性的将其存储在".u_boot_cmd"段,等号后边的就是该变量的初始值。

三、具体分析find_cmd函数

函数功能:查找命令是否存在,如果存在就将命令结构体地址返回
/***************************************************************************
* find command table entry for a command
*/
cmd_tbl_t *find_cmd (const char *cmd)
{
cmd_tbl_t *cmdtp;
cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */
const char *p;
int len;
int n_found = 0;

/*
* Some commands allow length modifiers (like "cp.b");
* compare command name only until first dot.
*/
len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);
//获取命令的长度,因为uboot支持命令的简写,但是以'.'为分隔符

//下边的for循环就是在命令结构体存储区中,从前到后依次查找是否有匹配的命令
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++;
}
}
if (n_found == 1) { /* exactly one match */ //如果简写命令只有一个匹配,那么说明就是要找的命令
//但是,倘若超过一个就不知道所谓的简写是哪一个命令了
return cmdtp_temp;
}

return NULL; /* not found or ambiguous command */
}

参考资料:U-Boot启动第二阶段代码分析

原文地址:https://www.cnblogs.com/amanlikethis/p/3556413.html