?
main_loop()函数
main_loop()函数做的都是与具体平台无关的工作,主要包括初始化启动次数限制机制、设置软件版本号、打印启动信息、解析命令等。
(1)设置启动次数有关参数。在进入main_loop()函数后,首先是根据配置加载已经保留的启动次数,并且根据配置判断是否超过启动次数。代码如下:
- 295?void?main_loop?(void) ?
-
296?{ ?
- 297?#ifndef?CFG_HUSH_PARSER ?
- 298???static?char?lastcommand[CFG_CBSIZE]?=?{?0,?}; ?
- 299???int?len; ?
- 300???int?rc?=?1; ?
- 301???int?flag; ?
- 302?#endif ?
- 303???
- 304?#if?defined(CONFIG_BOOTDELAY)?&&?(CONFIG_BOOTDELAY?>=?0) ?
- 305???char?*s; ?
- 306???int?bootdelay; ?
- 307?#endif ?
- 308?#ifdef?CONFIG_PREBOOT??
- 309???char?*p; ?
- 310?#endif ?
- 311?#ifdef?CONFIG_BOOTCOUNT_LIMIT ?
- 312???unsigned?long?bootcount?=?0; ?
- 313???unsigned?long?bootlimit?=?0; ?
- 314???char?*bcs; ?
- 315???char?bcs_set[16]; ?
- 316?#endif? ?
-
317? ?
- 318?#if?defined(CONFIG_VFD)?&&?defined(VFD_TEST_LOGO) ?
- 319???ulong?bmp?=?0;???? ?
- 320???extern?int?trab_vfd?(ulong?bitmap); ?
-
321? ?
- 322?#ifdef?CONFIG_MODEM_SUPPORT ?
- 323???if?(do_mdm_init) ?
- 324?????bmp?=?1;?? ?
- 325?#endif ?
- 326???trab_vfd?(bmp); ?
- 327?#endif?? ?
-
328? ?
- 329?#ifdef?CONFIG_BOOTCOUNT_LIMIT ?
-
330???bootcount?=?bootcount_load();?????????//?加载保存的启动次数 ?
-
331???bootcount++;????????????????????????? //?启动次数加1 ?
- 332???bootcount_store?(bootcount);??????????//?更新启动次数 ?
- 333???sprintf?(bcs_set,?"%lu",?bootcount);??//?打印启动次数 ?
- 334???setenv?("bootcount",?bcs_set); ?
- 335???bcs?=?getenv?("bootlimit"); ?
- 336???bootlimit?=?bcs???simple_strtoul?(bcs,?NULL,?10)?:?0; ?
-
??????????????????????????????????????????? //?转换启动次数字符串为UINT类型 ?
- 337?#endif??
第329~337行是启动次数限制功能,启动次数限制可以被用户设置一个启动次数,然后保存在Flash存储器的特定位置,当到达启动次数后,U-Boot无法启动。该功能适合一些商业产品,通过配置不同的License限制用户重新启动系统。
?
(2)程序第339~348行是Modem功能。如果系统中有Modem,打开该功能可以接受其他用户通过电话网络的拨号请求。Modem功能通常供一些远程控制的系统使用,代码如下:
-
339?#ifdef?CONFIG_MODEM_SUPPORT ?
-
340???debug?("DEBUG:?main_loop:???do_mdm_init=%dn",?do_mdm_init); ?
-
341???if?(do_mdm_init)?{???????????????????????????//?判断是否需要初始化Modem ?
-
342?????char?*str?=?strdup(getenv("mdm_cmd"));?????//?获取Modem参数 ?
- 343?????setenv?("preboot",?str);? ?
- 344?????if?(str?!=?NULL) ?
- 345???????free?(str); ?
-
346?????mdm_init(); ? ?//?初始化Modem ?
-
347???} ?
-
348?#endif??
(3)接下来设置U-Boot的版本号,初始化命令自动完成功能等。代码如下:
- 350?#ifdef?CONFIG_VERSION_VARIABLE ?
- 351???{ ?
- 352?????extern?char?version_string[]; ?
-
353? ?
-
354?????setenv?("ver",?version_string);??? ?
-
?????????????????????????????????????????????//?设置版本号 ?
- 355???} ?
- 356?#endif? ?
-
357? ?
- 358?#ifdef?CFG_HUSH_PARSER ?
-
359???u_boot_hush_start?();????????????????//?初始化Hash功能 ?
- 360?#endif ?
-
361? ?
- 362?#ifdef?CONFIG_AUTO_COMPLETE ?
-
363???install_auto_complete();??????????????//?初始化命令自动完成功能 ?
- 364?#endif ?
-
365? ?
- 366?#ifdef?CONFIG_PREBOOT ?
- 367???if?((p?=?getenv?("preboot"))?!=?NULL)?{ ?
- 368?#?ifdef?CONFIG_AUTOBOOT_KEYED ?
-
369?????int?prev?=?disable_ctrlc(1);???
- ??????????????????????????????????????????//?关闭Crtl+C组合键?
- 370?#?endif ?
-
371? ?
- 372?#?ifndef?CFG_HUSH_PARSER ?
-
373?????run_command?(p,?0);?//?运行Boot参数 ?
- 374?#?else ?
- 375?????parse_string_outer(p,?FLAG_PARSE_SEMICOLON?| ?
- 376?????????????FLAG_EXIT_FROM_LOOP); ?
- 377?#?endif ?
-
378? ?
- 379?#?ifdef?CONFIG_AUTOBOOT_KEYED ?
- 380?????disable_ctrlc(prev);?? ?
-
??????????????????????????????????????????//?恢复Ctrl+C组合键 ?
- 381?#?endif ?
- 382???} ?
- 383?#endif??
程序第350~356行是动态版本号功能支持代码,version_string变量是在其他文件定义的一个字符串变量,当用户改变U-Boot版本的时候会更新该变量。打开动态版本支持功能后,U-Boot在启动的时候会显示最新的版本号。
程序第363行设置命令行自动完成功能,该功能与Linux的shell类似,当用户输入一部分命令后,可以通过按下键盘上的Tab键补全命令的剩余部分。
main_loop()函数不同的功能使用宏开关控制不仅能提高代码模块化,更主要的是针对嵌入式系统Flash存储器大小设计的。在嵌入式系统上,不同的系统Flash存储空间不同。对于一些Flash空间比较紧张的设备来说,通过宏开关关闭一些不是特别必要的功能如命令行自动完成,可以减小 U-Boot编译后的文件大小。
?
(4)在进入主循环之前,如果配置了启动延迟功能,需要等待用户从串口或者网络接口输入。如果用户按下任意键打断,启动流程,会向终端打印出一个启动菜单。代码如下:
- 385?#if?defined(CONFIG_BOOTDELAY)?&&?(CONFIG_BOOTDELAY?>=?0) ?
-
386???s?=?getenv?("bootdelay"); ?
-
387???bootdelay?=?s???(int)simple_strtol(s,?10)?:?CONFIG_BOOTDELAY; ?
- ????????????????????????????????????????????????????????//?启动延迟 ?
-
388? ?
-
389???debug?("###?main_loop?entered:?bootdelay=%dnn",?bootdelay); ?
-
390? ?
-
391?#?ifdef?CONFIG_BOOT_RETRY_TIME ?
- 392???init_cmd_timeout?();????? ? //?初始化命令行超时机制 ?
-
393?#?endif ? ?
-
394? ?
-
395?#ifdef?CONFIG_BOOTCOUNT_LIMIT??????? //一般不会检查这破玩意。
-
396???if?(bootlimit?&&?(bootcount?>?bootlimit))?{ ?//?检查是否超出启动次数限制 ?
- 397?????printf?("Warning:?Bootlimit?(%u)?exceeded.?Using?altbootcmd.n",?
- 398?????????????(unsigned)bootlimit); ?
-
399?????s?=?getenv?("altbootcmd"); ?
-
400???} ?
-
401???else ?
-
402?#endif ? ?
-
403?????s?=?getenv?("bootcmd"); ?//?获取启动命令参数 ?
-
404? ?
-
405???debug?("###?main_loop:?bootcmd="%s"n",?s???s?:?"<UNDEFINED>"); ?
-
406? ?
-
407???if?(bootdelay?>=?0?&&?s?&&?!abortboot?(bootdelay))?{?? ?
-
??????????????????????????????????????????????????? ?//检查是否支持启动延迟功能 ?
-
408?#?ifdef?CONFIG_AUTOBOOT_KEYED ?
-
409?????int?prev?=?disable_ctrlc(1);???? ?
-
?????????????????????????????????????????????????? ? //?关闭Ctrl+C组合键 ?
-
410?#?endif ?
-
411? ?
-
412?#?ifndef?CFG_HUSH_PARSER ?
- 413?????run_command?(s,?0);????? //?运行启动命令行 ?
-
414?#?else ?
- 415?????parse_string_outer(s,?FLAG_PARSE_SEMICOLON?| ?
- 416?????????????FLAG_EXIT_FROM_LOOP); ?
-
417?#?endif ?
-
418? ?
-
419?#?ifdef?CONFIG_AUTOBOOT_KEYED ?
- 420?????disable_ctrlc(prev);?? ?
-
???????????????????????????????????????????????????? //?打开Ctrl+C组合键 ?
-
421?#?endif ?
-
422???} ?
-
423? ?
-
424?#?ifdef?CONFIG_MENUKEY ?
-
425???if?(menukey?==?CONFIG_MENUKEY)?{? ?//?检查是否支持菜单键 ?
-
426???????s?=?getenv("menucmd"); ?
- 427???????if?(s)?{ ?
-
428?#?ifndef?CFG_HUSH_PARSER ?
- 429?????run_command?(s,?0); ?
-
430?#?else ?
- 431?????parse_string_outer(s,?FLAG_PARSE_SEMICOLON?| ?
- 432?????????????FLAG_EXIT_FROM_LOOP); ?
-
433?#?endif ?
-
434???????} ?
-
435???} ?
-
436?#endif? ?
-
437?#endif?? ?
-
438? ?
-
439?#ifdef?CONFIG_AMIGAONEG3SE ?
-
440???{ ?
- 441???????extern?void?video_banner(void); ?
- 442???????video_banner();???????????????//?打印启动图标 ?
-
443???} ?
-
444?#endif
(5)在各功能设置完毕后,程序第454行进入一个for死循环,该循环不断使用readline()函数(第463行)从控制台(一般是串口)读取用户的输入,然后解析。有关如何解析命令请参考U-Boot代码中run_command()函数的定义,
-
446????
-
449?#ifdef?CFG_HUSH_PARSER ?
-
450???parse_file_outer(); ?
-
451??? ?
-
452???for?(;;); ?
-
453?#else ?
- 454???for?(;;)?{????????????????????????//?进入命令行循环?
- 455?#ifdef?CONFIG_BOOT_RETRY_TIME ?
-
456?????if?(rc?>=?0)?{ ?
-
457??????? ?
- 460???????reset_cmd_timeout();??????????//?设置命令行超时 ?
- 461?????} ?
-
462?#endif ?
- 463?????len?=?readline?(CFG_PROMPT);????//?读取命令 ?
-
464? ?
-
465?????flag?=?0;? ?
-
466?????if?(len?>?0) ?
- 467???????strcpy?(lastcommand,?console_buffer);?
-
468?????else?if?(len?==?0) ?
- 469???????flag?|=?CMD_FLAG_REPEAT; ?
- 470?#ifdef?CONFIG_BOOT_RETRY_TIME ?
-
471?????else?if?(len?==?-2)?{ ?
- 472??????? ?
- 474???????puts?("nTimed?out?waiting?for?commandn"); ?
- 475?#?ifdef?CONFIG_RESET_TO_RETRY ?
- 476??????? ?
- 477???????do_reset?(NULL,?0,?NULL); ?
- 478?#?else ?
- 479???????return;??? ?
- 480?#?endif?
-
481?????} ?
-
482?#endif ?
-
483? ?
-
484?????if?(len?==?-1) ?
-
485???????puts?("<INTERRUPT>n"); ?
-
486?????else ?
-
487???????rc?=?run_command?(lastcommand,?flag);????//?运行命令?
-
488? ?
-
489?????if?(rc?<=?0)?{ ?
-
490??????? ?
- 491???????lastcommand[0]?=?0; ?
-
492?????} ?
-
493???}??// dead loop
-
494?#endif? ?
- 495?}
U-BOOT的功能设计 基本就在这里