概述
uboot的主要作用是用来启动linux内核。
CPU不能直接从块设备中执行代码,因此需要把块设备中的程序复制到内存中,而复制之前还需要进行很多初始化工作,如初始化时钟、串口、dram等。这些初始化工作,都是由uboot完成的。
这些初始化工作完成后,uboot将块设备中的内核代码复制到某个内存地址,然后再执行“bootm xxx”命令以启动内核代码。
uboot启动后自动运行,打印出很多信息,然后uboot进入倒数bootdelay秒,如下所示。
root@ubuntu:/home/ubuntu/Desktop/u-boot-2017.05-rc2# qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot -nographic
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
U-Boot 2017.05-rc2 (Nov 05 2023 - 04:42:36 -0800)
DRAM: 512 MiB
WARNING: Caches not enabled
Flash: 128 MiB
MMC: MMC: 0
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: smc911x-0
Hit any key to stop autoboot: 0
=>
此时,如果用户没有按键操作时,则uboot会读取bootcmd这个环境变量,并使用rum_command函数来执行这个环境变量对应的命令,进入自动启动内核流程。
如果用户打断uboot的自启动过程,则进入uboot的命令行,然后uboot一直工作在命令行下,不断地重复执行“接收命令、解析命令、执行命令”的流程。
main_loop函数
uboot通过调用run_main_loop函数执行循环命令程序
static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
sandbox_main_loop_init();
#endif
/* main_loop() can return to retry autoboot, if so just run it again */
for (;;)
main_loop();
return 0;
}
main_loop函数定义如下:
/* We come here after U-Boot is initialised and ready to process commands */
void main_loop(void)
{
const char *s;
bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
#ifdef CONFIG_VERSION_VARIABLE
setenv("ver", version_string); /* set version variable */
#endif /* CONFIG_VERSION_VARIABLE */
cli_init();
run_preboot_environment_command();
#if defined(CONFIG_UPDATE_TFTP)
update_tftp(0UL, NULL, NULL);
#endif /* CONFIG_UPDATE_TFTP */
s = bootdelay_process();
if (cli_process_fdt(&s))
cli_secure_