u-boot-1.1.6 tq2440
u-boot有两个功能: 调试功能,启动内核。
调试功能实现是通过u-boot /common下定义的大量的命令的来实现的。
用户通过u-boot命令行来告诉要输入的命令,命令行交互是通过u-boot的main_loop来实现的。接下来我们就看看main_loop是怎么实现命令行交互的吧!
将tq2440修改过的main_loop代码根据宏定义,掐头去尾后代码如下:
main_loop命令行
/common/main.c 掐头去尾后代码如下 void main_loop (void) { #ifndef CFG_HUSH_PARSER static char lastcommand[CFG_CBSIZE] = { 0, }; int len; int rc = 1; int flag; #endif #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) char *s; int bootdelay; #endif #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) s = getenv ("bootdelay");//获得环境变量的bootdelay的值 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;//确定最后的bootdelay的值 s = getenv ("bootcmd");//获得超时后u-boot自启动的命令 if (bootdelay >= 0 && s && !abortboot (bootdelay)) //调用abortboot 倒计时计数 { if (bBootFrmNORFlash())//从nor flash启动,执行menu命令,显示调试界面,用户自定义 run_command("menu", 0); else //从nand flash启动,执行boot_zImage命令,启动内核,用户自定义 { printf("Booting Linux ...\n"); run_command("boot_zImage", 0); } } #endif/* CONFIG_BOOTDELAY */ //当abortboot 倒计时不为0时,按下键盘,则nand启动模式就进入命令行模式 //初始化mtd(不是很懂这个)标准的源码没有这个 #ifdef CONFIG_JFFS2_CMDLINE extern int mtdparts_init(void); if (!getenv("mtdparts")) run_command("mtdparts default", 0); else mtdparts_init(); #endif for (;;) { len = readline (CFG_PROMPT);//获取用户输入的内容 flag = 0; if (len > 0) strcpy (lastcommand, console_buffer);//将用户输入保存在lastcommand数组中 else if (len == 0) flag |= CMD_FLAG_REPEAT;//用户如果只是按了回车,那么重复执行上次那个命令 if (len == -1) puts ("<INTERRUPT>\n");//中断执行 else rc = run_command (lastcommand, flag);//执行用户输入的命令 if (rc <= 0) lastcommand[0] = 0;//无效的命令,清空lastcommand内容 }/*end for*/ }/*end main_loop*/
abortboot 倒计时显示
/common/main.c 掐头去尾后的代码如下 static __inline__ int abortboot(int bootdelay) { int abort = 0;//默认不终止倒计时 char c; printf("Press any key to stop autoboot: %2d ", bootdelay);//在串口终端显示倒计时 while ((bootdelay > 0) && (!abort)) { int i; --bootdelay;//倒计时减1 for (i=0; !abort && i<100; ++i) { if (tstc()) //检查是否有按键输入 { abort = 1; //终止倒计时 bootdelay = 0; //倒计时清零 (void) getc(); break; //退出for循环 } udelay (10000); //延时0.01s }/*end for*/ printf ("\b\b\b%2d ", bootdelay); }/*end while*/ } putc ('\n'); return abort; }
readline读取用户输入
/common/main.c 掐头去尾结果 int readline (const char *const prompt) { char *p = console_buffer; //p指向当前要输入的字符的地址 int n = 0; //n输入的字符数 int plen = 0; //使用提示符大小 smdk2410# int col; //输入的字符显示时相对开始的偏移量 char c; //每次读到的字符 if (prompt) { plen = strlen (prompt); puts (prompt); //打印出输入提示符 } col = plen; for (;;) { c = getc(); //获得输入 switch (c) { //特殊字符的处理 case '\r'://按下enter键,输入结束 case '\n': *p = '\0'; puts ("\r\n"); return (p - console_buffer);//返回输入的字符数 case '\0': continue; case 0x03://按下ctrl+c,放弃输入 console_buffer[0] = '\0'; return (-1); case 0x15://按下ctrl+u,删除输入行 while (col > plen){ puts (erase_seq); --col;} p = console_buffer; n = 0; continue; case 0x17://按下ctrl+w,删除输入行的一个字 p=delete_char(console_buffer, p, &col, &n, plen); while ((n > 0) && (*p != ' ')) { p=delete_char(console_buffer, p, &col, &n, plen);} continue; case 0x08://按下ctr+h backspace case 0x7F://按下del backspace p=delete_char(console_buffer, p, &col, &n, plen); continue; default://默认处理 if (n < CFG_CBSIZE-2){ if (c == '\t') {//按下tab键 puts (tab_seq+(col&07)); col += 8 - (col&07);} else {//可见字符处理 ++col; putc (c);}//屏幕回显输入的字符 *p++ = c; //保存输入的字符 ++n; } //字符数加1 else //输入缓冲满 putc ('\a'); }/*end switch*/ }/*end for*/ }/*end readline*/run_command执行命令( 点击访问u-boot命令实现)
/common/main.c int run_command (const char *cmd, int flag) { cmd_tbl_t *cmdtp; char cmdbuf[CFG_CBSIZE]; char *token; char *sep; char finaltoken[CFG_CBSIZE]; char *str = cmdbuf; char *argv[CFG_MAXARGS + 1]; int argc, inquotes; int repeatable = 1; int rc = 0; clear_ctrlc(); if (!cmd || !*cmd) return -1; if (strlen(cmd) >= CFG_CBSIZE) { puts ("## Command too long!\n"); return -1;} strcpy (cmdbuf, cmd); while (*str) { for (inquotes = 0, sep = str; *sep; sep++) { if ((*sep=='\'') && (*(sep-1) != '\\')) inquotes=!inquotes; if (!inquotes &&(*sep == ';') &&(sep != str) &&(*(sep-1) != '\\')) break; } token = str; if (*sep) { str = sep + 1;*sep = '\0';} else str = sep; if ((argc = parse_line (finaltoken, argv)) == 0) {//解析命令缓冲中的参数 rc = -1; continue;} if ((cmdtp = find_cmd(argv[0])) == NULL) {//根据名称查找是否定义了该命令 printf ("Unknown command '%s' - try 'help'\n", argv[0]); rc = -1; continue;} if (argc > cmdtp->maxargs){ printf ("Usage:\n%s\n", cmdtp->usage); rc = -1; continue;} if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0)//调用命令执行 rc = -1; repeatable &= cmdtp->repeatable; if (had_ctrlc ()) return 0; } return rc ? rc : repeatable; }
上面就是main_loop的大致过程了。