• Uboot命令U_BOOT_CMD


    转载:http://blog.csdn.net/shengzhadon/article/details/52766263

     U_BOOT_CMD是一个宏定义,具体功能是定义一个struct cmd_tbl_s的结构体变量,U_BOOT_CMD宏传递的参数是该结构体变量的成员变量。通过U_BOOT_CMD定义的变量会通过脚本链接到uboot指定的一个section中,然后可以通过find_cmd遍历这个section找到这个cmd,可以通过run_command(cmd, flag)函数执行具体命令。

     uboot的命令都存放在uboot/common/目录下,可以在该目录下的Makefile中添加编译命令的选项。如,网络的编译选项如下:

    obj-$(CONFIG_CMD_NET) += cmd_net.o  

    网络的具体命令是再uboot/common/cmd_net.c中定义的,如nfs命令

    #if defined(CONFIG_CMD_NFS)  
    static int do_nfs(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])  
    {  
        return netboot_common(NFS, cmdtp, argc, argv);  
    }  
      
    U_BOOT_CMD(  
        nfs,    3,  0,  do_nfs,  
        "boot image via network using NFS protocol",  
        "[loadAddress] [[hostIPaddr:]bootfilename]"  
    );  
    #endif  

    可以看出nfs命令是通过U_BOOT_CMD宏定义“注册“的,并关联上do_nfs(...)函数,执行具体功能。这里的U_BOOT_CMD是在uboot/include/command.h文件中定义的,如下:

    #define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help)        
        U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)  

    U_BOOT_CMD_COMPLETE定义紧挨着,如下:

    #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp)   
        ll_entry_declare(cmd_tbl_t, _name, cmd) =             
            U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,    
                            _usage, _help, _comp);  

    这里可以看出是一个赋值语句(其实“=”前面是定义一个变量,后面赋值)。“=”后面的宏定义紧挨着,如下:

    #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd,        
                    _usage, _help, _comp)             
            { #_name, _maxargs, _rep, _cmd, _usage,           
                _CMD_HELP(_help) _CMD_COMPLETE(_comp) }  

    注:这里的“#”,作用是将_name传递的值字符串化。_CMD_HELP和_CMD_COMPLETE就是取本身(具体宏定义在本文件command.h中)。

    可以看出,这个宏定义的作用就是将U_BOOT_CMD传递的参数放在大括号内。

    “=”前面的ll_entry_declare也是一个宏定义,具体在uboot/include/linker_lists.h中,如下

    #define ll_entry_declare(_type, _name, _list)                
        _type _u_boot_list_2_##_list##_2_##_name __aligned(4)        
                __attribute__((unused,                
                section(".u_boot_list_2_"#_list"_2_"#_name)))

    注:这里的"##"表示连接作用。即##_list##表示用_list变量的值替换当前位置。

    即通过_type传递变量类型,_name和_list传递组成变量名称的字符串,然后将该变量放在section中,section的名称也由_name和_list命令传递。这里的__aligned(4)是指定定义的变量4字节对其,__attribute是选择未使用的section,可以在理解原理时忽略掉。

    这里的_type=cmd_tbl_t,后者的定义如下:

    typedef struct cmd_tbl_s    cmd_tbl_t;  

    即cmd_tbl_t就是cmd_tbl_s,定义如下:

    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 * const []);  
        char        *usage;     /* Usage message    (short) */  
    #ifdef  CONFIG_SYS_LONGHELP  
        char        *help;      /* Help  message    (long)  */  
    #endif  
    #ifdef CONFIG_AUTO_COMPLETE  
        /* do auto completion on the arguments */  
        int     (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]);  
    #endif  
    };  

    如前所述,U_BOOT_CMD的作用就是定义一个结构体变量(struct cmd_tbl_s),并将其存放再uboot的没有被占用的section中。展开就是:

    struct cmd_tbl_s _u_boot_list_2_cmd_2_##_name = {  
            #_name, _maxargs, _rep, _cmd, _usage, _help, NULL  
        };  

    注:该变量属性是4字节对齐(__aligned(4) ),存放在未被使用的section中,并将该section命名为【".u_boot_list_2_"#name】(__attribute__((unused, section(".u_boot_list_2_"#name))))。

    举例:

    命令nfs

    U_BOOT_CMD(  
        nfs,    3,  0,  do_nfs,  
        "boot image via network using NFS protocol",  
        "[loadAddress] [[hostIPaddr:]bootfilename]"  
    );  

    即为:

    struct cmd_tbl_s _u_boot_list_2_cmd_2_nfs = {  
            "nfs", 3, 0, do_nfs,  
            "boot image via network using NFS protocol",  
            "[loadAddress] [[hostIPaddr:]bootfilename]", NULL  
        };  

    将_u_boot_list_2_cmd_2_nfs变量4字节对齐存放在未被使用的uboot的section中,该section被命名为.u_boot_list_2_nfs。

  • 相关阅读:
    [原]跟我学silverlight系列教程[1]—wpf/silverlight体系架构和运行机制
    [转载]My97DatePicker在Frame中无法打开站点
    sql select的时候按特定的顺序排序
    javascript获取滚动条位置
    sql2005 数据库没有完全关闭,无法重新生成日志
    .Net framework
    输出datagrid的内容到excel
    IIS中网站出错
    [原]跟我学silverlight系列教程
    SharePoint2010 的ADFS2.0设置
  • 原文地址:https://www.cnblogs.com/Caden-liu8888/p/7692046.html
Copyright © 2020-2023  润新知