Uboot之hush方式解析用戶命令

uboot命令解析流程簡析

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

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

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

voidmain_loop(void)

{

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

#ifdefCONFIG_SYS_HUSH_PARSER
parse_file_outer();
/* This point isnever reached */
for (;;);
#else
for (;;)
{
#ifdefCONFIG_BOOT_RETRY_TIME
if (rc >= 0) {
/* Saw enough of avalid command to
* restart thetimeout.
*/
reset_cmd_timeout();
}
#endif
len =readline (CONFIG_SYS_PROMPT);
printf("afterreadline:%d\n",len);
flag = 0; /* assume no special flags fornow */
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");
# ifdefCONFIG_RESET_TO_RETRY
/* Reinit board to run initialization codeagain */
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_PARSERmain_loop會調用parse_file_outer(),進入hush,然後裏面是一大堆和hush相關的機制,暫時不做分析,最終會調用到hush中的run_pipe_real(structpipe *pi),在該函數中經過一些列解析,最終會調用到對應的命令執行函數,代碼如下:

staticrun_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的結構,定義如下:

structcmd_tbl_s

{
char*name; /* Command Name */
intmaxargs; /* maximum number of arguments */
intrepeatable; /* autorepeat allowed? */
int(*cmd)(struct cmd_tbl_s *, int, int, char *[]); /* Implementationfunction */
char*usage; /* Usage message (short) */
#ifdefCONFIG_SYS_LONGHELP
char*help; /* Help message (long) */
#endif
#ifdefCONFIG_AUTO_COMPLETE
/*do auto completion on the arguments */
int(*complete)(int argc, char *argv[], char last_char, int maxv, char*cmdv[]);
#endif
};

typedefstruct cmd_tbl_s cmd_tbl_t;

#defineU_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 - addroff|partition size\n"
"nand write - addr off|partitionsize\n"
" read/write 'size' bytes starting at offset'off'\n"
" to/from memory address 'addr', skipping badblocks.\n"
"nand erase [clean] [off size] - erase 'size'bytes from\n"
" offset 'off' (entire device if notspecified)\n"
#if defined(ENABLE_CMD_NAND_YAFFS)
"nandread[.yaffs[1]] is not provide temporarily!\n"
"nandwrite[.yaffs[1]] addr off size - write the `size' byte yaffs imagestarting\n"
" at offset `off' from memory address `addr'(.yaffs1 for 512+16 NAND)\n"
#endif
"nand bad - showbad blocks\n"
"nand dump[.oob] off - dump page\n"
"nandscrub - really clean NAND erasing bad blocks (UNSAFE)\n"
"nandmarkbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
"nandbiterr off - make a bit error at offset (UNSAFE)"
#ifdefCONFIG_CMD_NAND_LOCK_UNLOCK
"\n"
"nand lock[tight] [status]\n"
" bring nand to lock state ordisplay locked pages\n"
"nand unlock [offset] [size] -unlock section"
#endif
);

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

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章