前面我们分析了uboot的配置过程、编译过程、执行流程、解析了main_loop()函数、分析了uboot的命令结构。今天我们进一步分析uboot是如何启动内核的,也就是do_bootm/ do_bootz具体做了哪些事。
U-Boot环境变量如下。main_loop函数中会获取bootcmd环境变量,并执行命令,从而启动内核,所以我们主要分析do_bootm/ do_bootz函数。
U-Boot 2016.03-mys-6ulx+g4ade113 (Sep 16 2017 - 23:49:21 +0800)
CPU: Freescale i.MX6UL rev1.1 528 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 36C
Reset cause: POR
Board: MX6UL 14x14 EVK
I2C: ready
DRAM: 256 MiB
NAND: 256 MiB
MMC: FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment
Display: TFT43AB (480x272)
Video: 480x272x24
In: serial
Out: serial
Err: serial
Net: FEC0
Error: FEC0 address not set.
Normal Boot
Hit any key to stop autoboot: 0
=> pri
baudrate=115200
board_name=MYS6UL
board_rev=14X14
bootargs=console=ttymxc0,115200 ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs)
bootcmd=nand read ${loadaddr} 0x500000 0xA00000;nand read ${fdt_addr} 0xF00000 0x100000;bootz ${loadaddr} - ${fdt_addr}
bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};
bootdelay=3
console=ttymxc0
ethact=FEC0
ethprime=FEC
fdt_addr=0x83000000
fdt_high=0xffffffff
initrd_addr=0x83800000
initrd_high=0xffffffff
loadaddr=0x80800000
mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc g_mass_storage.stall=0 g_mass_storage.removable=1 g_mass_storage.file=/fat g_mass_storage.ro=1 g_mass_storage.idVendor=0x066F g_mass_storage.idProduct=0x37FF g_mass_storage.iSerialNumber="" mtdparts=gpmi-nand:5m(boot),10m(kernel),1m(dtb),-(rootfs) clk_ignore_unused
panel=TFT43AB
Environment size: 930/131068 bytes
=>
函数前期执行流程如下:
(1)_start(arch/arm/lib/vector.S)
b reset
(2)reset(arch/arm/cpu/armv7/start.S)
bl cpu_init_cp15
bl cpu_init_crit
bl _main
(3)_main(arch\arm\lib\crt0.S)
board_init_f(common\Board_f.c)
b relocate_code
ldr lr, =board_init_r(common/Board_r.c)
run_main_loop()
main_loop()
(4)main_loop()
(5)启动内核:
main_loop->autoboot_command->run_command_list->cli_simple_run_command_list->cli_simple_run_command-> cmd_process-> find_cmd/ cmd_call(result= (cmdtp->cmd)(cmdtp, flag, argc, argv))
cmd_call会执行nand read和bootz/bootm函数,接下来主要分析bootz/bootm函数。
调用流程如下:
do_bootz->bootz_start->do_bootm_states->bootm_start/bootm_find_os/bootm_find_other/bootm_load_os(加载内核到指定位置上)/bootm_os_get_boot_func(获取到对应操作系统的启动函数,被存储到boot_fn 中)->boot_os->do_bootm_linux->boot_prep_linux/boot_jump_linux->kernel_entry(跳转到kernel中,离开uboot)
打印Starting kernel ...
boot_jump_linux->announce_and_cleanup:
printf("\nStartingkernel ...%s\n\n", fake ? "(fakerun for tracing)" : "");
详细函数分析待后续整理。。。