uboot源碼分析(1)uboot 命令解析流程簡析


                                                                    uboot 命令解析流程簡析

      uboot正常啟動后,會調用main_loop(void)函數,進入main_loop()之后,如果在規定的時間(CONFIG_BOOTDELAY)內,沒有檢查到任何按鍵事件的發生,就會去加載OS,並啟動系統,比如把linux內核壓縮鏡像從nand flash中讀到sdram ,然后執行它。

     如果在CONFIG_BOOTDELAY時間內,用戶按下鍵盤上的任意一個按鍵,uboot就會進入與用戶交互的狀態。如果用戶在配置文件中定義了CONFIG_SYS_HUSH_PARSER,就會通過parse_file_outer(),去接收並解析用戶命令,否則進入一個for(;;)循環中,通過

readline (CONFIG_SYS_PROMPT)接收用戶命令,然后調用run_command(cmd,flag)去解析並執行命令。代碼如下:  

void main_loop(void)

{ 

 

   ..............................

  #ifdef CONFIG_SYS_HUSH_PARSER
       parse_file_outer();
      /* This point is never reached */
     for (;;);
 #else
    for (;;)
   {
         #ifdef CONFIG_BOOT_RETRY_TIME
               if (rc >= 0) {
               /* Saw enough of a valid command to
              * restart the timeout.
              */
             reset_cmd_timeout();
           }
     #endif
     len = readline (CONFIG_SYS_PROMPT);
     printf("after readline:%d\n",len);
     flag = 0; /* assume no special flags for now */
    if (len > 0)
       strcpy (lastcommand, console_buffer);
    else if (len == 0)
      flag |= CMD_FLAG_REPEAT;
  #ifdef CONFIG_BOOT_RETRY_TIME
    else if (len == -2) {
   /* -2 means timed out, retry autoboot
    */
   puts ("\nTimed out waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY
   /* Reinit board to run initialization code again */
   do_reset (NULL, 0, 0, NULL);
# else
   return;  /* retry autoboot */
# endif
  }
#endif

  if (len == -1)
       puts ("<INTERRUPT>\n");
  else
      rc = run_command (lastcommand, flag);

 

.....................................

}

     如果定義了CONFIG_SYS_HUSH_PARSER,命令接收和解析講采用busybox 中的hush(對應hush.c)工具來實現,與uboot原始的命令解析方法相比,該工具更加智能。這里主要講uboot中基於hush的命令解析流程。不過hush的實現太過復雜 ,鑒於自己水平太次,只是簡單追蹤下流程。

      當在配置文件中定義了CONFIG_SYS_HUSH_PARSER,main_loop會調用parse_file_outer(),進入hush,然后里面是一大堆和hush相關的機制,暫時不做分析,最終會調用到hush中的run_pipe_real(struct pipe *pi),在該函數中經過一些列解析 ,最終會調用到對應的命令執行函數,代碼如下:

static run_pipe_real(struct pipe *pi)
{

   ........................................

    rcode = (cmdtp->cmd)(cmdtp, flag,child->argc-i,&child->argv[i]);
    if ( !cmdtp->repeatable )
       flag_repeat = 0;

  ...................................
}

cmdtp 是對應命令的結構指針,cmd就是該命令對應的執行函數指針。在uboot中,對所有的命令,有一個cmd_tbl_t的結構,定義如下:

struct cmd_tbl_s

 {
     char  *name;  /* Command Name   */
     int  maxargs; /* maximum number of arguments */
    int  repeatable; /* autorepeat allowed?  */
    int  (*cmd)(struct cmd_tbl_s *, int, int, char *[]);   /* Implementation function */
   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 *argv[], char last_char, int maxv, char *cmdv[]);
   #endif
};

typedef struct cmd_tbl_s cmd_tbl_t;

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}

   對於uboot支持的每一個命令,是通過U_BOOT_CMD宏定義的,他定義了該命令對應的名稱name,支持的最大參數rep,重復次數,實現函數cmd,以及輸入help命令時,顯示的幫助信息usage。例如,在cmd_nand中,定義nand命令的方法如下:

   U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand,
 "NAND sub-system",
 "info - show available NAND devices\n"
 "nand device [dev] - show or set current device\n"
 "nand read - addr off|partition size\n"
 "nand write - addr off|partition size\n"
 "    read/write 'size' bytes starting at offset 'off'\n"
 "    to/from memory address 'addr', skipping bad blocks.\n"
 "nand erase [clean] [off size] - erase 'size' bytes from\n"
 "    offset 'off' (entire device if not specified)\n"
#if defined(ENABLE_CMD_NAND_YAFFS)
 "nand read[.yaffs[1]] is not provide temporarily!\n"
 "nand write[.yaffs[1]]    addr off size - write the `size' byte yaffs image starting\n"
 "     at offset `off' from memory address `addr' (.yaffs1 for 512+16 NAND)\n"
#endif
 "nand bad - show bad blocks\n"
 "nand dump[.oob] off - dump page\n"
 "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
 "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
 "nand biterr off - make a bit error at offset (UNSAFE)"
#ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
 "\n"
 "nand lock [tight] [status]\n"
 "    bring nand to lock state or display locked pages\n"
 "nand unlock [offset] [size] - unlock section"
#endif
);

    命令名稱為nand,支持的最大參數個數為CONFIG_SYS_MAXARGS,命令重復次數為1,對應的實現函數為do_nand,后面的是用戶輸入nand -help時,將顯示的幫助信息。

    在執行函數cmd中,第一個參數對應該命令結構本身的指針,第二個參數對應flag標記,第三個參數對應參數數目,第四個參數是指針數組,里面存儲的是對應參數的指針。比如我們輸入命令“nand read 30008000 0x80000 300000”,在run_pipe_real中,解析到該命令為nand ,有五個參數,這些參數對應的指針存儲在argv數組中,nand命令對應的實現函數cmd為do_nand,在實現函數do_nand中,會從argv中取得對應的參數並解析,然后執行相應的命令。這些實現在do_nand函數中都可以看到。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM