U-BOOT分析4

10 篇文章 0 订阅

转载自:http://blog.csdn.net/toraloo/article/details/7821000


run_command()分析:

[cpp]  view plain copy
  1. int run_command (const char *cmd, int flag)  
  2. {  
  3.     cmd_tbl_t *cmdtp;  
  4.     char cmdbuf[CFG_CBSIZE];    /* working copy of cmd      */  
  5.     char *token;            /* start of token in cmdbuf */  
  6.     char *sep;          /* end of token (separator) in cmdbuf */  
  7.     char finaltoken[CFG_CBSIZE];  
  8.     char *str = cmdbuf;  
  9.     char *argv[CFG_MAXARGS + 1];    /* NULL terminated  */  
  10.     int argc, inquotes;  
  11.     int repeatable = 1;  
  12.     int rc = 0;  
  13.   
  14.     clear_ctrlc();      /* forget any previous Control C */  
  15.       
  16.     if (!cmd || !*cmd) {  
  17.         return -1;  /* empty command */  
  18.     }  
  19.   
  20.     if (strlen(cmd) >= CFG_CBSIZE) {  
  21.         puts ("## Command too long!\n");  
  22.         return -1;  
  23.     }  
  24.   
  25.     strcpy (cmdbuf, cmd);  
  26.       
  27.     while (*str) {  
  28.   
  29.         /* 
  30.          * Find separator, or string end 
  31.          * Allow simple escape of ';' by writing "\;" 
  32.          */  
  33.         for (inquotes = 0, sep = str; *sep; sep++) {  
  34.             if ((*sep=='\'') &&  
  35.                 (*(sep-1) != '\\'))  
  36.                 inquotes=!inquotes;  
  37.   
  38.             if (!inquotes &&  
  39.                 (*sep == ';') &&    /* separator        */  
  40.                 ( sep != str) &&    /* past string start    */  
  41.                 (*(sep-1) != '\\')) /* and NOT escaped  */  
  42.                 break;  
  43.         }  
  44.   
  45.         /* 
  46.          * Limit the token to data between separators 
  47.          */  
  48.         token = str;  
  49.         if (*sep) {  
  50.             str = sep + 1;  /* start of command for next pass */  
  51.             *sep = '\0';  
  52.         }  
  53.         else  
  54.             str = sep;  /* no more commands for next pass */  
  55.   
  56.         /* find macros in this token and replace them */  
  57.         process_macros (token, finaltoken);  
  58.   
  59.         /* Extract arguments */  
  60.         if ((argc = parse_line (finaltoken, argv)) == 0) {  
  61.             rc = -1;    /* no command at all */  
  62.             continue;  
  63.         }  
  64.   
  65.         /* Look up command in command table */  
  66.         if ((cmdtp = find_cmd(argv[0])) == NULL) {  
  67.             printf ("Unknown command '%s' - try 'help'\n", argv[0]);  
  68.             rc = -1;    /* give up after bad command */  
  69.             continue;  
  70.         }  
  71.   
  72.         /* found - check max args */  
  73.         if (argc > cmdtp->maxargs) {  
  74.             printf ("Usage:\n%s\n", cmdtp->usage);  
  75.             rc = -1;  
  76.             continue;  
  77.         }  
  78.   
  79. #if (CONFIG_COMMANDS & CFG_CMD_BOOTD)  
  80.         /* avoid "bootd" recursion */  
  81.         if (cmdtp->cmd == do_bootd) {  
  82.             if (flag & CMD_FLAG_BOOTD) {  
  83.                 puts ("'bootd' recursion detected\n");  
  84.                 rc = -1;  
  85.                 continue;  
  86.             } else {  
  87.                 flag |= CMD_FLAG_BOOTD;  
  88.             }  
  89.         }         
  90. #endif  /* CFG_CMD_BOOTD */  
  91.   
  92.         /* OK - call function to do the command */  
  93.         if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {  
  94.             rc = -1;  
  95.         }  
  96.   
  97.         repeatable &= cmdtp->repeatable;  
  98.   
  99.         /* Did the user stop this? */  
  100.         if (had_ctrlc ())  
  101.             return 0;   /* if stopped then not repeatable */  
  102.     }  
  103.   
  104.     return rc ? rc : repeatable;  
  105. }  

上述代码为删减后的run_command()函数代码并不是很难,且代码中有着较为详细的注释。其中应注意如下两句代码:

[cpp]  view plain copy
  1. if ((cmdtp = find_cmd(argv[0])) == NULL)            /* 在u_boot_com数据段下查询是否有这个指令 */  

[cpp]  view plain copy
  1. if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0)     /* 调用实现该指令的函数 */  

下面进行find_cmd()函数的分析,这函数相对较为简短;

[cpp]  view plain copy
  1. cmd_tbl_t *find_cmd (const char *cmd)  
  2. {  
  3.     cmd_tbl_t *cmdtp;  
  4.     cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start;    /*Init value */  
  5.     const char *p;  
  6.     int len;  
  7.     int n_found = 0;  
  8.   
  9.     /* 
  10.      * Some commands allow length modifiers (like "cp.b"); 
  11.      * compare command name only until first dot. 
  12.      */  
  13.     len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd);  
  14.   
  15.     for (cmdtp = &__u_boot_cmd_start;  
  16.          cmdtp != &__u_boot_cmd_end;  
  17.          cmdtp++) {  
  18.         if (strncmp (cmd, cmdtp->name, len) == 0) {  
  19.             if (len == strlen (cmdtp->name))  
  20.                 return cmdtp;   /* full match */  
  21.   
  22.             cmdtp_temp = cmdtp; /* abbreviated command ? */  
  23.             n_found++;  
  24.         }  
  25.     }  
  26.     if (n_found == 1) {         /* exactly one match */  
  27.         return cmdtp_temp;  
  28.     }  
  29.   
  30.     return NULL;    /* not found or ambiguous command */  
  31. }  

重点留意如下代码:

1cmd_tbl_t结构体:

[cpp]  view plain copy
  1. struct cmd_tbl_s {  
  2.     char        *name;      /* Command Name         */  
  3.     int     maxargs;    /* maximum number of arguments  */  
  4.     int     repeatable; /* autorepeat allowed?      */  
  5.                     /* Implementation function  */  
  6.     int     (*cmd)(struct cmd_tbl_s *, intintchar *[]);  
  7.     char        *usage;     /* Usage message    (short) */  
  8. #ifdef  CFG_LONGHELP  
  9.     char        *help;      /* Help  message    (long)  */  
  10. #endif  
  11. #ifdef CONFIG_AUTO_COMPLETE  
  12.     /* do auto completion on the arguments */  
  13.     int     (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);  
  14. #endif  
  15. };  
  16.   
  17. typedef struct cmd_tbl_s    cmd_tbl_t;  

2、查询u_boot_cmd数据段的for循环寻找合适的指令

[cpp]  view plain copy
  1. for (cmdtp = &__u_boot_cmd_start;  
  2.          cmdtp != &__u_boot_cmd_end;  
  3.          cmdtp++)  

要查询此数据段那则次数据段必须建立一组命令表,通过如下步骤建立这个表:

一、添加结构体定义

[cpp]  view plain copy
  1. U_BOOT_CMD(  
  2.     menu,   3,  0,  do_menu,  
  3.     "menu - display a menu, to select the items to do something\n",  
  4.     " - display a menu, to select the items to do something"  
  5. );  

二、此命令的实现函数

[cpp]  view plain copy
  1. int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  
  2. {  
  3.     menu_shell();  
  4.     return 0;  
  5. }  

其中上面循环中使用到的__u_boot_cmd_start与__u_boot_cmd_end均定义在u_boot.lds连接脚本中;

[cpp]  view plain copy
  1. cmdtp = &__u_boot_cmd_start;     /* u_boot_cmd数据段的__u_boot_cmd_start地址的内容取出存放至cmdtp中 */  

此时进行.u_boot_cmd数据段查询的如下代码:

[cpp]  view plain copy
  1. #define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))  

并得到如下的宏定义:

[cpp]  view plain copy
  1. #define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \  
  2. cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}  

例如增加一个toraloo命令,则上述宏可展开为:

[cpp]  view plain copy
  1. cmd_tbl_t __u_boot_cmd_toraloo Struct_Section = {“toraloo”, 3, 1, do_toraloo, “string 1”, “string 2”};  

toraloo命令可仿照menu命令编写如:

[cpp]  view plain copy
  1. U_BOOT_CMD(  
  2.     toraloo 3,  1,  do_toraloo,  
  3.     "toraloo  - I am toraloo,HAHAHA.......\n",  
  4.     " TORALOO is toraloo,ToraLoo is toraloo"  
  5. );  
  6. int do_menu (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  
  7. {  
  8.     int i;  
  9.     printf(“this is a test! %d\n”,argc);  
  10.     for(i=0; i<argc; i++)  
  11.   {  
  12.     printf(“argv[%d] = %s\n”,i,argv[i]);  
  13.   }  
  14.     return 0;  
  15. }  

再此文件中添加部分头文件,在对/command/makefile下增加cmd_toraloo.o的编译项重新再编译一次u-boot,再将其下载即可看见toraloo这个命令了。

U-boot下的内核启动命令:bootm

输入bootm运行时相当于运行了bootcmd,其将会调度do_bootm()完成命令的功能在do_bootm(...)中再调度do_bootm_linux(....)完成内的内核启动前的设定与硬件参数的设定(如SDRAM地址大小等信息...)最终通过如下两句话实现内核的启动:

[cpp]  view plain copy
  1. theKernel = (void (*)(intint, uint))ntohl(hdr->ih_ep);  
  2. theKernel (0, bd->bi_arch_number, bd->bi_boot_params);  

PS:还有注意一下关于镜像文件头结构体:

[cpp]  view plain copy
  1. typedef struct image_header {  
  2.     uint32_t    ih_magic;   /* Image Header Magic Number    */  
  3.     uint32_t    ih_hcrc;    /* Image Header CRC Checksum    */  
  4.     uint32_t    ih_time;    /* Image Creation Timestamp */  
  5.     uint32_t    ih_size;    /* Image Data Size      */  
  6.     uint32_t    ih_load;    /* Data  Load  Address      */  
  7.     uint32_t    ih_ep;      /* Entry Point Address      */  
  8.     uint32_t    ih_dcrc;    /* Image Data CRC Checksum  */  
  9.     uint8_t     ih_os;      /* Operating System     */  
  10.     uint8_t     ih_arch;    /* CPU architecture     */  
  11.     uint8_t     ih_type;    /* Image Type           */  
  12.     uint8_t     ih_comp;    /* Compression Type     */  
  13.     uint8_t     ih_name[IH_NMLEN];  /* Image Name       */  
  14. } image_header_t;  
  15. 这种留意如下三个参数:  
  16.     uint32_t    ih_size;    /* Image Data Size      */  
  17.     uint32_t    ih_load;    /* Data  Load  Address      */  
  18.     uint32_t    ih_ep;      /* Entry Point Address      */  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值