3 学习笔记——函数void main_loop (void)注释

来源:互联网 发布:淘宝有没有投诉电话 编辑:程序博客网 时间:2024/06/05 12:49

  • 版本号:2010.06
  • 所有的初始化完毕后,要进入命令行模式,等待输入参数或者引导内核启动
  • void main_loop (void)
  • {
  • #ifndefCONFIG_SYS_HUSH_PARSER
  •        static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
  •        int len;
  •        int rc = 1;
  •        int flag;
  • #endif
  •  
  • #ifdefined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  •        char *s;
  •        int bootdelay;
  • #endif
  • #ifdef CONFIG_PREBOOT
  •        char*p;
  • #endif
  • #ifdefCONFIG_BOOTCOUNT_LIMIT
  •        unsigned long bootcount = 0;
  •        unsigned long bootlimit = 0;
  •        char *bcs;
  •        char bcs_set[16];
  • #endif /*CONFIG_BOOTCOUNT_LIMIT */
  •  
  • #if defined(CONFIG_VFD)&& defined(VFD_TEST_LOGO)
  •        ulong bmp = 0;             /*default bitmap */
  •        extern int trab_vfd (ulong bitmap);
  •  
  • #ifdefCONFIG_MODEM_SUPPORT
  •        if (do_mdm_init)
  •               bmp = 1; /*alternate bitmap */
  • #endif
  •        trab_vfd(bmp);
  • #endif     /*CONFIG_VFD && VFD_TEST_LOGO */
  •  
  • #ifdef CONFIG_BOOTCOUNT_LIMIT开发板没有配置该信息
  •        bootcount = bootcount_load(); 加载保存的启动次数
  •        bootcount++;   启动次数加1
  •        bootcount_store (bootcount); 更新启动次数
  •        sprintf (bcs_set, "%lu", bootcount); 打印启动次数
  •        setenv ("bootcount", bcs_set);
  •        bcs = getenv ("bootlimit");
  •        bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
  • #endif /*CONFIG_BOOTCOUNT_LIMIT */
  • //启动次数限制功能,限制用户的启动次数,主要是license限制用户启动系统
  • #ifdefCONFIG_MODEM_SUPPORT  开发板没有配置
  •        debug ("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);
  •        if (do_mdm_init) {
  •               char *str = strdup(getenv("mdm_cmd"));
  •               setenv ("preboot", str);  /* set or delete definition */
  •               if (str != NULL)
  •                      free (str);
  •               mdm_init(); /* wait for modem connection */
  •        }
  • #endif  /* CONFIG_MODEM_SUPPORT */
  •  
  • #ifdefCONFIG_VERSION_VARIABLE
  •        {
  •               extern char version_string[];
  •  
  •               setenv ("ver", version_string);  /* set version variable */设置版本号信息变量
  •        }
  • #endif /*CONFIG_VERSION_VARIABLE */
  •  
  • #ifdef CONFIG_SYS_HUSH_PARSER
  •        u_boot_hush_start ();// 不知什么功能
  • #endif
  •  
  • #ifdefined(CONFIG_HUSH_INIT_VAR)
  •        hush_init_var ();//
  • #endif
  •  
  • #ifdefCONFIG_AUTO_COMPLETE
  •        install_auto_complete();//安装自动补全函数
  • #endif
  •  
  • #ifdef CONFIG_PREBOOT
  •        if ((p = getenv ("preboot")) != NULL) {
  • # ifdef CONFIG_AUTOBOOT_KEYED
  •               int prev = disable_ctrlc(1);    /* disable Control C checking */使能组合键功能
  • # endif
  •  
  • # ifndef CONFIG_SYS_HUSH_PARSER
  •               run_command (p, 0);
  • # else
  •               parse_string_outer(p,FLAG_PARSE_SEMICOLON |
  •                                 FLAG_EXIT_FROM_LOOP);
  • # endif
  •  
  • # ifdef CONFIG_AUTOBOOT_KEYED
  •               disable_ctrlc(prev); /* restore Control C checking */
  • # endif
  •        }
  • #endif /* CONFIG_PREBOOT */
  •  
  • #ifdefined(CONFIG_UPDATE_TFTP)// 设置版本号信息变量
  •        update_tftp ();
  • #endif /*CONFIG_UPDATE_TFTP */
  • //在进入主循环之前,如果配置了启动延迟功能,等待用户从串口或者网络输入,
  • #ifdefined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
  •        s = getenv ("bootdelay");
  •        bootdelay = s ? (int)simple_strtol(s, NULL, 10) :CONFIG_BOOTDELAY;// 启动延迟
  •  
  •        debug ("### main_loop entered: bootdelay=%d\n\n",bootdelay);
  •  
  • # ifdefCONFIG_BOOT_RETRY_TIME
  •        init_cmd_timeout ();// 初始化命令行超时机制
  • # endif    /* CONFIG_BOOT_RETRY_TIME */
  •  
  • #ifdef CONFIG_POST
  •        if (gd->flags & GD_FLG_POSTFAIL) {
  •               s = getenv("failbootcmd");
  •        }
  •        else
  • #endif /* CONFIG_POST*/
  • #ifdefCONFIG_BOOTCOUNT_LIMIT
  •        if (bootlimit && (bootcount > bootlimit)) {// 检查是否超过启动次数限制
  •               printf ("Warning: Bootlimit (%u) exceeded. Usingaltbootcmd.\n",
  •                      (unsigned)bootlimit);
  •               s = getenv ("altbootcmd");
  •        }
  •        else
  • #endif /*CONFIG_BOOTCOUNT_LIMIT */
  •               s = getenv("bootcmd");// 获取引导命令到S变量中
  •  
  •        debug ("### main_loop: bootcmd=\"%s\"\n",s ? s : "<UNDEFINED>");
  •  
  •        if (bootdelay >= 0 && s && !abortboot(bootdelay))
  • {//如果延时大于等于0,并且在延时过程中没有接收到按键,则引导内核启动
  • # ifdef CONFIG_AUTOBOOT_KEYED
  •            intprev = disable_ctrlc(1);    /* disableControl C checking */禁止组合键功能
  • # endif
  •  
  • # ifndef CONFIG_SYS_HUSH_PARSER
  •            run_command (s, 0);//无输入命令,则执行bootcmd
  • # else
  •            parse_string_outer(s,FLAG_PARSE_SEMICOLON |
  •                              FLAG_EXIT_FROM_LOOP); //不知什么功能
  • # endif
  •  
  • # ifdef CONFIG_AUTOBOOT_KEYED
  •            disable_ctrlc(prev); /* restore Control C checking */禁止组合键功能
  • # endif
  •        }
  •  
  • # ifdef CONFIG_MENUKEY
  •        if (menukey == CONFIG_MENUKEY) {//检查是否支持菜单按键
  •            s = getenv("menucmd");
  •            if (s) {
  • # ifndefCONFIG_SYS_HUSH_PARSER
  •               run_command (s, 0); //执行menucmd
  • # else
  •               parse_string_outer(s, FLAG_PARSE_SEMICOLON |
  •                                FLAG_EXIT_FROM_LOOP);
  • # endif
  •            }
  •        }
  • #endif /*CONFIG_MENUKEY */
  • #endif     /* CONFIG_BOOTDELAY */
  •  
  • #ifdefCONFIG_AMIGAONEG3SE  开发板没有配置
  •        {
  •            extern voidvideo_banner(void);
  •            video_banner();
  •        }
  • #endif
  •  
  •        /*
  •         * Main Loop for Monitor Command Processing
  •         */
  • //循环使用readline函数从控制台即串口读取用户的输入,然后解析,如何解析参考run_command()函数的定义
  • #ifdef CONFIG_SYS_HUSH_PARSER
  •        parse_file_outer();
  •        /*This point is never reached */永远执行不到这里
  •        for(;;);
  • #else
  • for (;;)
  • {
  • #ifdefCONFIG_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);
  • // CONFIG_SYS_PROMPT = "U-Boot> ",判断输入的命令的长度
  •  
  •               flag= 0;  /* assume no special flags for now*/置一个标记位,有新的命令输入
  •               if(len > 0) // 对不同的输入命令的长度做出不同的处理
  •                      strcpy(lastcommand, console_buffer);//将命令拷贝到lastcommand中
  •               elseif (len == 0)
  •                      flag|= CMD_FLAG_REPEAT;//未输入命令,标记为最后输入的那个命令
  • #ifdef CONFIG_BOOT_RETRY_TIME
  •               elseif (len == -2) { //超时处理
  •                      /*-2 means timed out, retry autoboot
  •                       */
  •                             puts ("\nTimed out waiting forcommand\n");
  • # ifdefCONFIG_RESET_TO_RETRY
  •                             /* Reinit board to run initializationcode 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);
  • //进入正常的命令处理,输入的命令,保存在lastcommand中,flag标记有新的命令输入
  •  
  •               if (rc <= 0) {
  •                      /*invalid command or not repeatable, forget it *///命令无效,不能执行丢弃
  •                      lastcommand[0]= 0;
  •               }
  • }
  • #endif/*CONFIG_SYS_HUSH_PARSER*/
  • }
  •  
  • 着重分析run_command
  • 该函数主要是对用户输入的命令或者是自启动命令的语法分析,从中获取命令参数等信息,并查找一张系统保存的命令表,找到该命令对应的处理函数,调用相应的命令处理
  • /****************************************************************************
  •  * returns:
  •  *    1  - command executed, repeatable
  •  *    0  - command executed but not repeatable,interrupted commands are
  •  *         always considered not repeatable
  •  *    -1 -not executed (unrecognized, bootd recursion or too many args)
  •  *          (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
  •  *          considered unrecognized)
  •  *
  •  * WARNING:
  •  *
  •  * We must create a temporary copy of thecommand since the command we get
  •  * may be the result from getenv(), whichreturns a pointer directly to
  •  * the environment data, which may changemagicly when the command we run
  •  * creates or modifies environment variables(like "bootp" does).
  •  */
  •  
  • int run_command (const char *cmd, int flag)
  • {
  •        cmd_tbl_t *cmdtp;
  •        char cmdbuf[CONFIG_SYS_CBSIZE];       /* working copy of cmd        */工作命令拷贝区
  •        char *token;                  /*start of token in cmdbuf    */ 指向cmdbuf的首地址
  •        char *sep;                     /*end of token (separator) in cmdbuf */指向cmdbuf的尾地址
  •        char finaltoken[CONFIG_SYS_CBSIZE];
  •        char *str = cmdbuf;
  •        char *argv[CONFIG_SYS_MAXARGS + 1];      /* NULL terminated       */
  •        int argc, inquotes;
  •        int repeatable = 1;
  •        int rc = 0;
  • #ifdef DEBUG_PARSER  调试阶段使用,打印信息调试
  •        printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
  •        puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */
  •        puts ("\"\n");
  • #endif
  •  
  •        clear_ctrlc();          /*forget any previous Control C */去掉组合键
  •        if (!cmd || !*cmd) {       //对输入命令的有效性进行判断
  •               return -1; /*empty command */ 空命令之间返回-1
  •        }
  •        if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {// 命令长度太长,不执行,之间返回-1
  •               puts ("## Command too long!\n");
  •               return -1;
  •        }
  •        strcpy (cmdbuf, cmd);// 将命令从cmd拷贝到工作区cmdbuf中
  •        /*Process separators and check for invalid
  •         * repeatable commands
  •         */
  • #ifdef DEBUG_PARSER
  •        printf ("[PROCESS_SEPARATORS] %s\n", cmd);
  • #endif
  •        while (*str) { // char *str = cmdbuf;判断输入命令是否到结束符
  •               /*
  •                * Findseparator, or string end
  •                * Allow simpleescape of ';' by writing "\;"
  •                */
  •               for (inquotes = 0, sep = str; *sep; sep++) { // 对输入命令的语法分析
  •                      if ((*sep=='\'') &&
  •                         (*(sep-1) != '\\'))
  •                             inquotes=!inquotes;
  •                      if (!inquotes &&
  •                          (*sep== ';') &&     /* separator            */
  •                          ( sep!= str) &&     /* past stringstart   */
  •                         (*(sep-1) != '\\'))    /* and NOTescaped       */
  •                             break;
  •               }
  •               /*
  •                * Limit the token to data between separators
  •                */
  •               token = str;  //指向命令的开始位置
  •               if (*sep) {
  •                      str = sep + 1;  /*start of command for next pass */
  •                      *sep = '\0';
  •               }
  •               else
  •                      str = sep; /*no more commands for next pass */
  • #ifdef DEBUG_PARSER   调试阶段使用,打印信息调试
  •               printf ("token: \"%s\"\n", token);
  • #endif
  •               /* find macros in this token and replace them */
  •               process_macros(token, finaltoken);//找个输入命令中的宏并且替换它
  •               /* Extract arguments */ 
  •               if ((argc = parse_line (finaltoken,argv))== 0) {// 提取参数,将参数用/0隔开,并将处理过的命令格式存入argv[17]数组中
  •                      rc = -1;   /*no command at all */
  •                      continue;
  •               }
  •               /* Look up command in command table *///在命令列表中查找命令
  •               if ((cmdtp = find_cmd(argv[0])) == NULL) {
  •                      printf ("Unknown command '%s' - try'help'\n", argv[0]);
  •                      rc = -1;   /*give up after bad command */
  •                      continue; //命令错误不执行
  •               }
  •               /* found - check max args *///检测最大参数是否正常
  •               if (argc > cmdtp->maxargs) {
  •                      cmd_usage(cmdtp);
  •                      rc = -1;
  •                      continue;
  •               }
  • #if defined(CONFIG_CMD_BOOTD)
  •               /* avoid "bootd" recursion *///避免"bootd"递归
  •               if (cmdtp->cmd == do_bootd) {
  • #ifdef DEBUG_PARSER  调试阶段使用,打印信息调试
  •                      printf ("[%s]\n", finaltoken);
  • #endif
  •                      if (flag & CMD_FLAG_BOOTD) {
  •                             puts ("'bootd' recursiondetected\n");
  •                             rc = -1;
  •                             continue;
  •                      } else {
  •                             flag |= CMD_FLAG_BOOTD;
  •                      }
  •               }
  • #endif
  •               /* OK - call function to do the command *///该命令正确,调用函数执行该命令
  •               if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
  •                      rc = -1;
  •               }
  •               repeatable &= cmdtp->repeatable;
  •               /* Did the user stop this? *///用户执行到此停止
  •               if (had_ctrlc ())
  •                      return -1; /*if stopped then not repeatable */
  •        }
  •        return rc ? rc : repeatable;
  • }