全部博文(218)
分类: 嵌入式
2011-10-27 14:46:51
作者:mutes
源码下载地址:
u-boot支持许多CPU,以及一些常见的开发板。在前面的文章中已经对u-boot1.1.6作了详细的分析,在本文以u-boot-2011.09这个最新版本为例,再来简要介绍一下u-boot在smdk2410上的启动流程。
上述代码的含义是设置cpu为SVC32模式,即超级保护模式,用于操作系统使用。
140 #ifdef CONFIG_S3C24X0
163 str r1, [r0]
该段代码的含义为,先定义几个需要的寄存器,然后关闭开门狗定时器,以及屏蔽所有中断和子中断,最后设置三个时钟频率之间的比值。
181 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
在第182行中,程序跳转到cpu_init_crit中,它也是在start.s文件中,函数的位置在第328行至第356行,它的作用是设置一些重要的寄存器(如MMU和caches等)以及内存时序。其中在第353行,程序又跳转到了lowlevel_init函数,它是在board/samsung/smdk2410目录下的lowlevel_init.s文件中定义的,这个文件的目的就是为了设置内存的时序。
186 call_board_init_f:
从cpu_init_crit返回后,来到了调用board_init_f的函数处。首先进行堆栈的设置,然后就跳转到board_init_f函数,其中传递给该函数的参数为0。board_init_f这个函数是在arch/arm/lib目录下的board.c文件内定义的,函数的位置是在第268行至第422行,它的作用是初始化开发板。需要注意的是,此时程序是在flash中运行的。
下面我们就来分析board_init_f函数。
269 /* Pointer is writable since we allocated a register for it */
278 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
上述代码的作用是循环调用init_sequence函数指针数组中的成员,该数组成员函数主要完成一些初始化的工作,如:
board_early_init_f函数(在board/samsung/smdk2410目录下的smdk2410.c文件内)完成ARM的时钟频率和IO的设置;
timer_init函数(在arch/arm/cpu/arm920t/s3c24x0目录下的timer.c文件内)完成定时器4的设置;
env_init函数(在common目录下的env_flash.c文件内,因为include/configs/smdk2410.h中定义了CONFIG_ENV_IS_IN_FLASH)完成环境变量的设置;
init_baudrate函数(在arch/arm/lib目录下的board.c文件内)完成波特率的设置;
serial_init函数(在drivers/serial目录下的serial_s3c24x0.c文件内,因为include/configs/smdk2410.h中定义了CONFIG_S3C24X0_SERIAL)完成串口通讯的设置;
console_init_f函数(在common目录下的console.c文件内)完成第一阶段的控制台初始化;
display_banner函数(在arch/arm/lib目录下的board.c文件内)用来打印输出一些信息;
dram_init函数(在board/samsung/smdk2410目录下的smdk2410.c文件内)用来配置SDRAM的大小。
303 addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
得到SDRAM的末位物理地址为0x3400 0000,即SDRAM的空间分布为0x3000 0000~0x33FF FFFF。
325 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
分配SDRAM的高64kB区域作为TLB,即0x33FF 0000~0x33FF FFFF,并且该区域也被用于U-Boot。
350 /*
359 #ifndef CONFIG_SPL_BUILD
401
第363行的意思为在SDRAM中又开辟了一块malloc空间,该区域是紧挨着上面定义的U-Boot区域的下面。然后在SDRAM中又分别依次定义了bd结构体空间、gd结构体空间和3个字大小的异常中断堆空间。其中bd结构体的数据原型为bd_t数据结构,它表示的是“板级信息”结构体,这些信息包括开发板的波特率、IP地址、ID、以及DRAM等信息,它是在arch/arm/include/asm目录下的u-boot.h文件中定义的。下图详细描述了SDRAM的空间分配情况:
409 gd->bd->bi_baudrate = gd->baudrate;
上述代码主要的作用是为gd结构体赋值,其中display_dram_config函数的作用是计算SDRAM的大小,并把它通过串口显示在控制台上。
418 memcpy(id, (void *)gd, sizeof(gd_t));
在board_init_f函数的最后是跳转到relocate_code函数体内,这个函数是在arch/arm/cpu/arm920t目录下的start.s文件内,也就是说从最开始的start.s跳到board.c,又从board.c跳回到了start.s中,这是因为此时程序需要重定向,即把代码从flash中搬运到ram中,这个过程是需要汇编这个低级语言来完成的。传递给relocate_code函数的三个参数分别栈顶地址、数据ID(即全局结构gd)在SDRAM中的起始地址和在SDRAM中存储U-Boot的起始地址。需要注意的是relocate_code函数执行完后,并不会返回到relocate_code (addr_sp, id, addr);的下一条语句继续执行。
下面我们再回到start.s文件:
201 .globl relocate_code
取得三个参数,分别放入寄存器r4、r5和r6。
208 stack_setup:
设置堆栈地址。
211 adr r0, _start
判断U-Boot是在什么位置上,如果在SDRAM中,则直接跳到BSS段清零函数处即可;如果在FLASH中,则要把U-Boot复制到SDRAM中指定的位置处。
224 #ifndef CONFIG_SPL_BUILD
247 fixabs:
上述代码的含义是对rel.dyn进行重定向。
265 clear_bss:
对BSS段进行清零的函数。
287 #ifdef CONFIG_NAND_SPL
由于没有定义CONFIG_NAND_SPL,所以程序是从第294行开始执行。该段代码的作用是跳转到board_init_r函数,并且给该函数传递了两个参数:全局结构gd在SDRAM中的起始地址和在SDRAM中存储U-Boot的起始地址。board_init_r函数是在arch/arm/lib目录下的board.c文件中,也就是又回到了上面执行过的board_init_f函数所在的board.c文件中。以后,程序就开始在SDRAM中运行了。
下面我们来分析board_init_r函数:
440 void board_init_r(gd_t *id, ulong dest_addr)
上述代码的作用是对gd和bd进行赋值,其中monitor_flash_len为整个U-Boot的长度。
474
479 #if !defined(CONFIG_SYS_NO_FLASH)
501 } else {
上述代码的作用是计算FLASH的大小,并把它通过串口显示在控制台上。由于没有定义CONFIG_SYS_FLASH_CHECKSUM,所以没有执行CRC的校验和。其中flash_init函数是在drivers/mtd目录下的cfi_flash.c文件内(因为include/configs/smdk2410.h中定义了CONFIG_FLASH_CFI_DRIVER)。
507 #if defined(CONFIG_CMD_NAND)
上述代码的作用是初始化NANDFLASH,并把NANDFLASH的大小通过串口显示在控制台上。其中nand_init函数是在divers/mtd/nand目录下的nand.c文件内定义的。
512 #if defined(CONFIG_CMD_ONENAND)
初始化ONENAND FLASH
526 /* initialize environment */
初始化环境变量,由于gd->env_valid等于0,所以在这里设置的是缺省环境变量。env_relocate函数是在common目录下的env_common.c文件中定义的。
529 #if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI)
初始化PCI。
536 stdio_init(); /* get the devices list going. */
初始化各类外设,如IIC、LCD、键盘、USB等,当然只有在定义了这些外设的前提下,才对这些外设进行初始化。该函数是在common目录下的stdio.c文件中定义的。
537
初始化跳转表gd->jt,该跳转表是一个函数指针数组,它定义了U-Boot中基本的常用函数库。该函数是在common目录下的exports.c文件中定义的。
545 console_init_r(); /* fully init console as a device */
初始化控制台,即标准输入、标准输出和标准错误,在这里都是串口。该函数是在common目录下的console.c文件中定义的。
interrupt_init函数是建立IRQ中断堆栈,enable_interrupts函数是使能IRQ中断,它们都是在arch/arm/lib目录下的interrupts.c文件中定义的。
571 /* Initialize from environment */
从环境变量中获取loadaddr参数,得到需要加载的地址。
576 s = getenv("bootfile");
从环境变量中获取bootfile参数,得到通过TFTP加载的镜像文件名。
589 #if defined(CONFIG_NET_MULTI)
上面代码主要的作用是初始化以太网,其中eth_initialize函数是在net目录下的eth.c文件的第209行至第298行定义的。
board_init_r函数的最后就是执行一个死循环,调用main_loop函数。该函数是在common目录下的main.c文件内定义的。
下面我们就来分析main_loop函数
265 void main_loop (void)
声明一些hush参数。
274 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
声明启动延时需要的参数。
315 #ifdef CONFIG_SYS_HUSH_PARSER
初始化hush功能。
346 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
368 else
第347行和第348行的含义是从环境变量中获取bootdelay参数,得到自动启动缺省镜像文件的延时(单位是秒)。第353行的含义是初始化命令行超时机制。第370行的含义是从环境变量中获取bootcmd参数,得到在启动延时过程中自动执行的命令。当我们得到了bootcmd参数,bootdelay参数也是大于等于0,并且在启动延时过程中没有按下任意键时,执行第382行的parse_string_outer函数,该函数的作用是解释bootcmd参数并执行,它是在common目录下的hush.c文件内定义的。
409 #ifdef CONFIG_SYS_HUSH_PARSER
431 else if (len == -2) {
454 #endif /*CONFIG_SYS_HUSH_PARSER*/
由于在include/configs/smdk2410.h文件中定义了CONFIG_SYS_HUSH_PARSER,所以上面的代码仅仅执行的是第410行至第412行的内容。第410行的parse_file_outer函数是在common目录下的hush.c文件中定义的,它的含义是依次读取命令序列中的命令并执行之,其中在该函数还调用了parse_stream_outer函数,这个函数体内有一个do-while循环,只有发生语法错误的时候才会跳出该循环,因此一般情况下永远也不会执行上面代码中的第412行内容,而是始终在那个do-while循环体内。
u-boot版本:u-boot-2011.09
分析时间:2011.10.26
参考文献: (源于该文件修改)
首先系统是从arch/arm/cpu/arm920t目录下的start.s文件开始执行,并且实际开始执行的代码是从第117行开始:
117 start_code:
118 /*
119 * set the cpu to SVC32 mode
120 */
121 mrs r0, cpsr
122 bic r0, r0, #0x1f
123 orr r0, r0, #0xd3
124 msr cpsr, r0
141 /* turn off the watchdog */
142
143 # if defined(CONFIG_S3C2400)
144 # define pWTCON 0x15300000
145 # define INTMSK 0x14400008 /* Interrupt-Controller base addresses */
146 # define CLKDIVN 0x14800014 /* clock divisor register */
147 #else
148 # define pWTCON 0x53000000
149 # define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */
150 # define INTSUBMSK 0x4A00001C
151 # define CLKDIVN 0x4C000014 /* clock divisor register */
152 # endif
153
154 ldr r0, =pWTCON
155 mov r1, #0x0
156 str r1, [r0]
157
158 /*
159 * mask all IRQs by setting all bits in the INTMR - default
160 */
161 mov r1, #0xffffffff
162 ldr r0, =INTMSK
164 # if defined(CONFIG_S3C2410)
165 ldr r1, =0x3ff
166 ldr r0, =INTSUBMSK
167 str r1, [r0]
168 # endif
169
170 /* FCLK:HCLK:PCLK = 1:2:4 */
171 /* default FCLK is 120 MHz ! */
172 ldr r0, =CLKDIVN
173 mov r1, #3
174 str r1, [r0]
175 #endif /* CONFIG_S3C24X0 */
182 bl cpu_init_crit
183 #endif
187 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
188 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
189 ldr r0,=0x00000000
190 bl board_init_f
270 gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);
271 /* compiler optimization barrier needed for GCC >= 3.4 */
272 __asm__ __volatile__("": : :"memory");
273
274 memset((void *)gd, 0, sizeof(gd_t));
275
276 gd->mon_len = _bss_end_ofs;
277
gd是一个保存在ARM的r8寄存器中的gd_t结构体的指针,该结构体包括了u-boot中所有重要的全局变量,它是在arch/arm/include/asm目录下的global_data.h文件内被定义的。上述代码的作用是为gd分配地址,并清零,最后得到整个u-boot的长度。
279 if ((*init_fnc_ptr)() != 0) {
280 hang ();
281 }
282 }
326 /* reserve TLB table */
327 addr -= (4096 * 4);
328
329 /* round down to next 64 kB limit */
330 addr &= ~(0x10000 - 1);
331
332 gd->tlb_addr = addr;
333 debug("TLB table at: %08lx\n", addr);
334 #endif
335
336 /* round down to next 4 kB limit */
337 addr &= ~(4096 - 1);
338 debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
351 * reserve memory for U-Boot code, data & bss
352 * round down to next 4 kB limit
353 */
354 addr -= gd->mon_len;
355 addr &= ~(4096 - 1);
356
357 debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
分配SDRAM的下一个单元为U-Boot代码段、数据段及BSS段。
360 /*
361 * reserve memory for malloc() arena
362 */
363 addr_sp = addr - TOTAL_MALLOC_LEN;
364 debug("Reserving %dk for malloc() at: %08lx\n",
365 TOTAL_MALLOC_LEN >> 10, addr_sp);
366 /*
367 * (permanently) allocate a Board Info struct
368 * and a permanent copy of the "global" data
369 */
370 addr_sp -= sizeof (bd_t);
371 bd = (bd_t *) addr_sp;
372 gd->bd = bd;
373 debug("Reserving %zu Bytes for Board Info at: %08lx\n",
374 sizeof (bd_t), addr_sp);
375
376 #ifdef CONFIG_MACH_TYPE
377 gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
378 #endif
379
380 addr_sp -= sizeof (gd_t);
381 id = (gd_t *) addr_sp;
382 debug("Reserving %zu Bytes for Global Data at: %08lx\n",
383 sizeof (gd_t), addr_sp);
384
385 /* setup stackpointer for exeptions */
386 gd->irq_sp = addr_sp;
387 #ifdef CONFIG_USE_IRQ
388 addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
389 debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
390 CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
391 #endif
392 /* leave 3 words for abort-stack */
393 addr_sp -= 12;
394
395 /* 8-byte alignment for ABI compliance */
396 addr_sp &= ~0x07;
397 #else
398 addr_sp += 128; /* leave 32 words for abort-stack */
399 gd->irq_sp = addr_sp;
400 #endif
402 debug("New Stack Pointer is: %08lx\n", addr_sp);
410 /* Ram ist board specific, so move it to board code ... */
411 dram_init_banksize();
412 display_dram_config(); /* and display it */
413
414 gd->relocaddr = addr;
415 gd->start_addr_sp = addr_sp;
416 gd->reloc_off = addr - _TEXT_BASE;
417 debug("relocation Offset is: %08lx\n", gd->reloc_off);
419
420 relocate_code(addr_sp, id, addr);
202 relocate_code:
203 mov r4, r0 /* save addr_sp */
204 mov r5, r1 /* save addr of gd */
205 mov r6, r2 /* save addr of destination */
209 mov sp, r4
212 cmp r0, r6
213 beq clear_bss /* skip relocation */
214 mov r1, r6 /* r1 <- scratch for copy_loop */
215 ldr r3, _bss_start_ofs
216 add r2, r0, r3 /* r2 <- source end address */
217
218 copy_loop:
219 ldmia r0!, {r9-r10} /* copy from source address [r0] */
220 stmia r1!, {r9-r10} /* copy to target address [r1] */
221 cmp r0, r2 /* until source end address [r2] */
222 blo copy_loop
225 /*
226 * fix .rel.dyn relocations
227 */
228 ldr r0, _TEXT_BASE /* r0 <- Text base */
229 sub r9, r6, r0 /* r9 <- relocation offset */
230 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
231 add r10, r10, r0 /* r10 <- sym table in FLASH */
232 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
233 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
234 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
235 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
236 fixloop:
237 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
238 add r0, r0, r9 /* r0 <- location to fix up in RAM */
239 ldr r1, [r2, #4]
240 and r7, r1, #0xff
241 cmp r7, #23 /* relative fixup? */
242 beq fixrel
243 cmp r7, #2 /* absolute fixup? */
244 beq fixabs
245 /* ignore unknown type of fixup */
246 b fixnext
248 /* absolute fix: set location to (offset) symbol value */
249 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
250 add r1, r10, r1 /* r1 <- address of symbol in table */
251 ldr r1, [r1, #4] /* r1 <- symbol value */
252 add r1, r1, r9 /* r1 <- relocated sym addr */
253 b fixnext
254 fixrel:
255 /* relative fix: increase location by offset */
256 ldr r1, [r0]
257 add r1, r1, r9
258 fixnext:
259 str r1, [r0]
260 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
261 cmp r2, r3
262 blo fixloop
263 #endif
266 #ifndef CONFIG_SPL_BUILD
267 ldr r0, _bss_start_ofs
268 ldr r1, _bss_end_ofs
269 mov r4, r6 /* reloc addr */
270 add r0, r0, r4
271 add r1, r1, r4
272 mov r2, #0x00000000 /* clear */
273
274 clbss_l:str r2, [r0] /* clear loop... */
275 add r0, r0, #4
276 cmp r0, r1
277 bne clbss_l
278
279 bl coloured_LED_init
280 bl red_led_on
281 #endif
288 ldr r0, _nand_boot_ofs
289 mov pc, r0
290
291 _nand_boot_ofs:
292 .word nand_boot
293 #else
294 ldr r0, _board_init_r_ofs
295 adr r1, _start
296 add lr, r0, r1
297 add lr, lr, r9
298 /* setup parameters for board_init_r */
299 mov r0, r5 /* gd_t */
300 mov r1, r6 /* dest_addr */
301 /* jump to it ... */
302 mov pc, lr
303
304 _board_init_r_ofs:
305 .word board_init_r - _start
306 #endif
441 {
442 char *s;
443 bd_t *bd;
444 ulong malloc_start;
445 #if !defined(CONFIG_SYS_NO_FLASH)
446 ulong flash_size;
447 #endif
448
449 gd = id;
450 bd = gd->bd;
451
452 gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
453
454 monitor_flash_len = _end_ofs;
455
456 /* Enable caches */
457 enable_caches();
458
459 debug("monitor flash len: %08lX\n", monitor_flash_len);
460 board_init(); /* Setup chipselects */
461
475 /* The Malloc area is immediately below the monitor copy in DRAM */
476 malloc_start = dest_addr - TOTAL_MALLOC_LEN;
477 mem_malloc_init (malloc_start, TOTAL_MALLOC_LEN);
对SDRAM中的malloc空间进行清零初始化。
480 puts("Flash: ");
481
482 flash_size = flash_init();
483 if (flash_size > 0) {
484 # ifdef CONFIG_SYS_FLASH_CHECKSUM
485 print_size(flash_size, "");
486 /*
487 * Compute and print flash CRC if flashchecksum is set to 'y'
488 *
489 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
490 */
491 s = getenv("flashchecksum");
492 if (s && (*s == 'y')) {
493 printf(" CRC: %08X", crc32(0,
494 (const unsigned char *) CONFIG_SYS_FLASH_BASE,
495 flash_size));
496 }
497 putc('\n');
498 # else /* !CONFIG_SYS_FLASH_CHECKSUM */
499 print_size(flash_size, "\n");
500 # endif /* CONFIG_SYS_FLASH_CHECKSUM */
502 puts(failed);
503 hang();
504 }
505 #endif
508 puts("NAND: ");
509 nand_init(); /* go init the NAND */
510 #endif
513 onenand_init();
514 #endif
527 env_relocate();
530 arm_pci_init();
531 #endif
532
533 /* IP Address */
534 gd->bd->bi_ip_addr = getenv_IPaddr("ipaddr"); 设置IP地址。
535
538 jumptable_init();
546
547 #if defined(CONFIG_ARCH_MISC_INIT)
548 /* miscellaneous arch dependent initialisations */
549 arch_misc_init();
550 #endif
551 #if defined(CONFIG_MISC_INIT_R)
552 /* miscellaneous platform dependent initialisations */
553 misc_init_r();
554 #endif
555
556 /* set up exceptions */
557 interrupt_init();
558 /* enable exceptions */
559 enable_interrupts();
572 s = getenv("loadaddr");
573 if (s != NULL)
574 load_addr = simple_strtoul(s, NULL, 16);
575 #if defined(CONFIG_CMD_NET)
577 if (s != NULL)
578 copy_filename(BootFile, s, sizeof(BootFile));
579 #endif
590 puts("Net: ");
591 #endif
592 eth_initialize(gd->bd);
593 #if defined(CONFIG_RESET_PHY_R)
594 debug("Reset Ethernet PHY\n");
595 reset_phy();
596 #endif
597 #endif
633 /* main_loop() can return to retry autoboot, if so just run it again. */
634 for (;;) {
635 main_loop();
636 }
266 {
267 #ifndef CONFIG_SYS_HUSH_PARSER
268 static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
269 int len;
270 int rc = 1;
271 int flag;
272 #endif
275 char *s;
276 int bootdelay;
277 #endif
316 u_boot_hush_start ();
317 #endif
347 s = getenv ("bootdelay");
348 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
349
350 debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
351
352 # ifdef CONFIG_BOOT_RETRY_TIME
353 init_cmd_timeout ();
354 # endif /* CONFIG_BOOT_RETRY_TIME */
355
356 #ifdef CONFIG_POST
357 if (gd->flags & GD_FLG_POSTFAIL) {
358 s = getenv("failbootcmd");
359 }
360 else
361 #endif /* CONFIG_POST */
362 #ifdef CONFIG_BOOTCOUNT_LIMIT
363 if (bootlimit && (bootcount > bootlimit)) {
364 printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
365 (unsigned)bootlimit);
366 s = getenv ("altbootcmd");
367 }
369 #endif /* CONFIG_BOOTCOUNT_LIMIT */
370 s = getenv ("bootcmd");
371
372 debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "
373
374 if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
375 # ifdef CONFIG_AUTOBOOT_KEYED
376 int prev = disable_ctrlc(1); /* disable Control C checking */
377 # endif
378
379 # ifndef CONFIG_SYS_HUSH_PARSER
380 run_command (s, 0);
381 # else
382 parse_string_outer(s, FLAG_PARSE_SEMICOLON |
383 FLAG_EXIT_FROM_LOOP);
384 # endif
385
386 # ifdef CONFIG_AUTOBOOT_KEYED
387 disable_ctrlc(prev); /* restore Control C checking */
388 # endif
389 }
410 parse_file_outer();
411 /* This point is never reached */
412 for (;;);
413 #else
414 for (;;) {
415 #ifdef CONFIG_BOOT_RETRY_TIME
416 if (rc >= 0) {
417 /* Saw enough of a valid command to
418 * restart the timeout.
419 */
420 reset_cmd_timeout();
421 }
422 #endif
423 len = readline (CONFIG_SYS_PROMPT);
424
425 flag = 0; /* assume no special flags for now */
426 if (len > 0)
427 strcpy (lastcommand, console_buffer);
428 else if (len == 0)
429 flag |= CMD_FLAG_REPEAT;
430 #ifdef CONFIG_BOOT_RETRY_TIME
432 /* -2 means timed out, retry autoboot
433 */
434 puts ("\nTimed out waiting for command\n");
435 # ifdef CONFIG_RESET_TO_RETRY
436 /* Reinit board to run initialization code again */
437 do_reset (NULL, 0, 0, NULL);
438 # else
439 return; /* retry autoboot */
440 # endif
441 }
442 #endif
443
444 if (len == -1)
445 puts ("
446 else
447 rc = run_command (lastcommand, flag);
448
449 if (rc <= 0) {
450 /* invalid command or not repeatable, forget it */
451 lastcommand[0] = 0;
452 }
453 }
455 }