1. 程式人生 > >實現uboot 命令自動補全 及 修正設定環境變數時自啟動核心

實現uboot 命令自動補全 及 修正設定環境變數時自啟動核心

語文地址:http://blog.csdn.net/liukun321/article/details/6641478

習慣了了linux下的命令自動補全,換做uboot下的單個字元的輸入長串命令,實在是不太習慣。常常在uboot下習慣性的按TAB鍵。為了習慣,下面來實現uboot的命令的自動補全。

這個功能的實現非常容易,只是在/include/configs/開發板標頭檔案.h(我的是micro2440.h)新增一個配置巨集:

#define CONFIG_CMDLINE_EDITING//#ifdef CONFIG_CMDLINE_EDITING
//#undef CONFIG_AUTO_COMPLETE
//#else
#define CONFIG_AUTO_COMPLETE //開啟命令自動補全函式的編譯

編譯,執行,功能實現

另外還碰到了一個奇怪的問題,把我卡了很久。每次在我執行這個命令後

setenv bootcmd "nand read 31000000 0x60000 500000;bootm 31000000"

會出現uboot立即自啟動核心,也就是立即執行了bootm 31000000 這個命令。

原因找了很久,最後定為在/include/configs/開發板標頭檔案.h(我的是micro2440.h)這個檔案。這個檔案某個巨集定義有問題或者是未定義導致這個問題的出現。是哪一個巨集呢?

看uboot 原始碼 不難找到問題所在 檔案/cmmon/main.c

[cpp] view plaincopyprint?
  1. #ifdef <span style="color:#ff0000;">CFG_HUSH_PARSER</span>
  2.     parse_file_outer();  
  3.     /* This point is never reached */
  4.     for (;;);  
  5. #else
  6.     for (;;) {  
  7. <span style="color:#ff0000;">#ifdef CONFIG_BOOT_RETRY_TIME  
  8.         if (rc >= 0) {  
  9.             /* Saw enough of a valid command to 
  10.              * restart the timeout. 
  11.              */
  12.             reset_cmd_timeout();  
  13.         }  
  14. #endif
  15.         len = readline (CFG_PROMPT);  
  16.         flag = 0;   /* assume no special flags for now */
  17.         if (len > 0)  
  18.             strcpy (lastcommand, console_buffer);  
  19.         elseif (len == 0)  
  20.             flag |= CMD_FLAG_REPEAT;  
  21. #ifdef CONFIG_BOOT_RETRY_TIME
  22.         elseif (len == -2) {  
  23.             /* -2 means timed out, retry autoboot 
  24.              */
  25.             puts ("\nTimed out waiting for command\n");  
  26. # ifdef CONFIG_RESET_TO_RETRY
  27.             /* Reinit board to run initialization code again */
  28.             do_reset (NULL, 0, 0, NULL);  
  29. # else
  30.             return;     /* retry autoboot */
  31. # endif
  32.         }  
  33. #endif
  34.         if (len == -1)  
  35.             puts ("<INTERRUPT>\n");  
  36.         else
  37.             rc = run_command (lastcommand, flag);  
  38.         if (rc <= 0) {  
  39.             /* invalid command or not repeatable, forget it */
  40.             lastcommand[0] = 0;  
  41.         }</span>  
  42.     }  
  43. #endif /*

如果不定義巨集 CFG_HUSH_PARSER  就將執行紅色部分程式碼,分析這部分程式碼在CFG_PROMPT>=0時執行strcpy (lastcommand, console_buffer);函式,即等待串列埠緩衝區得資料 ,如果有資料,將把資料複製到lastcommand這個串中,然後執行rc = run_command (lastcommand, flag);而恰恰就是run_command (lastcommand, flag);這個函式有問題,函式內把帶有 ; 號的命令作為下一個命令執行了,所以出現了bootm 自啟動核心的問題.

而定義 CFG_HUSH_PARSER  巨集將執行parse_file_outer();函式,函式內最後呼叫,cmmon/hush.c 檔案的int parse_stream_outer(struct in_str *inp, int flag)函式

[cpp] view plaincopyprint?
  1. <span style="color:#ff0000;">do</span> {  
  2.         ctx.type = flag;  
  3.         initialize_context(&ctx);  
  4.         update_ifs_map();  
  5.         if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";{1}|", 0);  
  6.         inp->promptmode=1;  
  7.         rcode = parse_stream(&temp, &ctx, inp, '\n');  
  8. #ifdef __U_BOOT__
  9.         if (rcode == 1) flag_repeat = 0;  
  10. #endif
  11.         if (rcode != 1 && ctx.old_flag != 0) {  
  12.             syntax();  
  13. #ifdef __U_BOOT__
  14.             flag_repeat = 0;  
  15. #endif
  16.         }  
  17.         if (rcode != 1 && ctx.old_flag == 0) {  
  18.             done_word(&temp, &ctx);  
  19.             done_pipe(&ctx,PIPE_SEQ);  
  20. #ifndef __U_BOOT__
  21.             run_list(ctx.list_head);  
  22. #else
  23.             code = run_list(ctx.list_head);  
  24.             if (code == -2) {   /* exit */
  25.                 b_free(&temp);  
  26.                 code = 0;  
  27.                 /* XXX hackish way to not allow exit from main loop */
  28.                 if (inp->peek == file_peek) {  
  29.                     printf("exit not allowed from main input shell.\n");  
  30.                     continue;  
  31.                 }  
  32.                 break;  
  33.             }  
  34.             if (code == -1)  
  35.                 flag_repeat = 0;  
  36. #endif
  37.         } else {  
  38.             if (ctx.old_flag != 0) {  
  39.                 free(ctx.stack);  
  40.                 b_reset(&temp);  
  41.             }  
  42. #ifdef __U_BOOT__
  43.             if (inp->__promptme == 0) printf("<INTERRUPT>\n");  
  44.             inp->__promptme = 1;  
  45. #endif
  46.             temp.nonnull = 0;  
  47.             temp.quote = 0;  
  48.             inp->p = NULL;  
  49.             free_pipe_list(ctx.list_head,0);  
  50.         }  
  51.         b_free(&temp);  
  52.     } <span style="color:#ff0000;">while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP));   </span>  

會發現條件rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)是一直滿足的,就進入了另一個命令提示輸入迴圈,這個迴圈避免上面那個現象。

程式碼沒看的太仔細,分析的可能還存在問題,希望遇到同樣問題的朋友如果發現分析錯誤能夠多多指正。