U-Boot2017.01的启动过程比较复杂,本文分为6部分讲述,笔者将主要过程和函数调用关系整理成一个文档方便查看,文档链接为
U-Boot2017.01启动过程分析pdf
U-Boot2017.01源码分析及启动命令解析
启动过程6部分内容如下
01-U-Boot2017.01 启动过程概述
02-U-Boot2017.01 SPL阶段分析
03-U-Boot2017.01 U-Boot阶段分析
04-U-Boot2017.01 加载内核过程
05-U-Boot2017.01 bootz加载过程
06-U-Boot2017.01 读取uEnv.txt过程
U-Boot2017.01 加载内核过程的函数调用关系如下:
/* u-boot启动内核阶段 */
|--> main_loop(common/main.c)
|--> setenv("ver", version_string) /* 设置版本变量 */
|--> version_string[](cmd/version.c) /* u-boot版本号,编译日期和时间,以及时间区 */
|--> #define U_BOOT_VERSION_STRING U_BOOT_VERSION(include/version.h)
|--> run_preboot_environment_command(common/main.c) /* 从环境变量中获取"preboot"的定义,一般环境变量中不包含该项配置 */
|--> bootdelay_process(common/autoboot.c) /* 从环境变量中取出"bootdelay"和"bootcmd"的配置值 */
|--> s = getenv("bootcmd")(common/autoboot.c)
|--> autoboot_command(common/autoboot.c) /* 倒计时按下执行,没有操作执行bootcmd的参数 */
|--> abortboot(stored_bootdelay)(common/autoboot.c)
|--> __abortboot(bootdelay)(common/autoboot.c) /* 判断倒计时有无按下 */
|--> Press SPACE to abort autoboot in %d seconds /* 启动信息打印这句话 */
|--> run_command_list(s, -1, 0)(common/cli.c) /* 运行命令 */
====》 |--> parse_string_outer(common/cli_hush.c)
|| |--> parse_stream_outer(common/cli_hush.c) /* hush shell的命令解释器 */
|| |--> do{...}while(..);(common/cli_hush.c) /*循环命令解析器的"命令输入解析--执行"运行模式*/
|| |--> parse_stream(common/cli_hush.c) /* 读取一行输入命令,并解析 */
|| |--> run_list(common/cli_hush.c) /* 运行命令 */
|| |--> run_list_real(common/cli_hush.c)
|| |--> run_pipe_real(common/cli_hush.c)
|| |--> cmd_process(common/command.c) /* 处理命令 */
|| |--> find_cmd(argv[0])(common/command.c)
|| |--> find_cmd_tbl(common/command.c)
|| |--> for (cmdtp = table; cmdtp != table + table_len; cmdtp++) ... return cmd_tbl_t *; /* 返回命令表项指针 */
|| |--> cmd_call(cmdtp, flag, argc, argv)(common/command.c)
|| |--> (cmdtp->cmd)(cmdtp, flag, argc, argv) /* 执行命令 */
|| |--> 例如:do_bootz(cmd/bootz.c) /* bootz加载uImage */
|| |--> bootz_start(cmd/bootz.c)
|| |--> do_bootm_states(common/bootm.c) /* states = BOOTM_STATE_START */
|| |--> images->ep =0x82000000 /* entry point of OS */
|| |--> bootz_setup(arch/arm/lib/zimage.c)
|| |--> bootm_find_images(common/bootm.c) /* 内核和设备树的获取 */
|| |--> bootm_disable_interrupts(common/bootm.c)
|| |--> images.os.os = IH_OS_LINUX;
|| |--> do_bootm_states(common/bootm.c) /* states = BOOTM_STATE_OS_PREP |BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO */
|| /* 这个函数最主要的功能是获取kernel的启动函数,执行寻找设备树并进入执行kernel启动函数 */
|| |--> bootm_start(common/bootm.c) /* return 0; states = BOOTM_STATE_START */
|| |--> bootm_os_get_boot_func(common/bootm_os.c) /* 获取内核加载函数 */
|| /* return do_bootm_linux; 也就是 boot_fn = do_bootm_linux; */
|| |--> boot_selected_os(common/bootm_os.c)
|| |--> boot_fn(state, argc, argv, images) /* boot_fn = do_bootm_linux 所以执行下一行 */
|| |--> do_bootm_linux(arch/arm/lib/bootm.c)
|| |--> boot_jump_linux(arch/arm/lib/bootm.c)
|| |--> announce_and_cleanup(0)(arch/arm/lib/bootm.c)
|| |--> printf("\nStarting kernel ...%s\n\n", fake ? "(fake run for tracing)" : ""); /* 打印Starting kernel ... */
|| |--> kernel_entry()
|| |--> cli_loop(common/cli.c) /* 倒计时按下space键,执行用户输入命令 */
|| |--> parse_file_outer(common/cli_hush.c)
|| |--> setup_file_in_str(common/cli_hush.c)
|| |--> file_get(common/cli_hush.c)
|| |--> get_user_input(common/cli_hush.c)
|| |--> uboot_cli_readline(common/cli_hush.c)
|| |--> cli_readline(common/cli_readline.c)
|| |--> cli_readline_into_buffer(common/cli_readline.c)
====》 |--> parse_stream_outer(common/cli_hush.c)
加载过程框图如下:
获取解析执行启动命令的过程如下