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)加载过程框图如下: 获取解析执行启动命令的过程如下