• bootz启动 Linux内核过程中涉及的 do_bootm_states 函数


    一.  bootz启动Linux

    uboot 启动Linux内核使用bootz命令。当然还有其它的启动命令,例如,bootm命令等等。

    本文只分析 bootz命令启动 Linux内核的过程中涉及的几个重要函数。具体分析  do_bootm_states 函数执行过程。

    本文继上一篇文章,地址如下:

    bootz启动 Linux内核过程中涉及的 bootz_start 函数-CSDN博客

    二.  bootz 启动 Linux 内核涉及函数

    bootz 命令的执行函数为 do_bootz函数。而 do_bootz函数主要调用如下函数:

    bootz_start 函数,bootm_disable_interrupts 函数,设置 images.os.os ,do_bootm_states 函数。

    1.  do_bootm_states 函数

    do_bootz函数 最 后 调 用 的 就 是 do_bootm_states函 数,而且 在 bootz_start 中 也 调 用 了
    do_bootm_states 函数 ,看 来 do_bootm_states 函数 还 是很重要的函数。此函 数 定 义 在 文件
    common/bootm.c 中。
    do_bootz 函数中,会用到 BOOTM_STATE_OS_PREP BOOTM_STATE_OS_FAKE_GO
    BOOTM_STATE_OS_GO 这三个 BOOT 状态。
    bootz_start 函数中会用到 BOOTM_STATE_START 一个 BOOT 状态。为了精简代码,方便分析。 do_bootm_states 进行精简,只留下下面这 4 BOOT 状态对应:
    1. BOOTM_STATE_OS_PREP
    2. BOOTM_STATE_OS_FAKE_GO
    3. BOOTM_STATE_OS_GO
    4. BOOTM_STATE_START
    四种 BOOT 状态对应的部分代码如下:
    1. int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
    2. int states, bootm_headers_t *images, int boot_progress)
    3. {
    4. boot_os_fn *boot_fn;
    5. ulong iflag = 0;
    6. int ret = 0, need_boot_fn;
    7. images->state |= states;
    8. ............
    9. /* From now on, we need the OS boot function */
    10. if (ret)
    11. return ret;
    12. boot_fn = bootm_os_get_boot_func(images->os.os);
    13. need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
    14. BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
    15. BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
    16. if (boot_fn == NULL && need_boot_fn) {
    17. if (iflag)
    18. enable_interrupts();
    19. printf("ERROR: booting os '%s' (%d) is not supported\n",
    20. genimg_get_os_name(images->os.os), images->os.os);
    21. bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
    22. return 1;
    23. }
    24. ............
    25. if (!ret && (states & BOOTM_STATE_OS_PREP))
    26. ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);
    27. #ifdef CONFIG_TRACE
    28. /* Pretend to run the OS, then run a user command */
    29. if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
    30. char *cmd_list = getenv("fakegocmd");
    31. ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
    32. images, boot_fn);
    33. if (!ret && cmd_list)
    34. ret = run_command_list(cmd_list, -1, flag);
    35. }
    36. #endif
    37. /* Check for unsupported subcommand. */
    38. if (ret) {
    39. puts("subcommand not supported\n");
    40. return ret;
    41. }
    42. /* Now run the OS! We hope this do not return */
    43. if (!ret && (states & BOOTM_STATE_OS_GO))
    44. ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
    45. images, boot_fn);
    46. .............
    47. return ret;
    48. }

    第15行,在BOOT状态时即 BOOTM_STATE_START 阶段, bootz_start 会执行这一段代码,这里调用 bootm_start 函数。
    20 行非常重要!通过函数 bootm_os_get_boot_func 来查找系统启动函数,参数 images->os.os 就是系统类型,根据这 个系统类型来选择对应的启动函数,在 do_bootz 中设置 images.os.os= IH_OS_LINUX 。函数返 回值就是找到的系统启动函数,这里找到的 Linux 系统启动函数为 do_bootm_linux boot_fn=do_bootm_linux ,后面执行 boot_fn 函数的地方实际上是执行的 do_bootm_linux 函数。
    26 行,处理 BOOTM_STATE_OS_PREP 状态,调用函数 do_bootm_linux do_bootm_linux 函数也是调用 boot_prep_linux 来完成具体的处理过程。
    boot_prep_linux 主要用于处理环境变量 bootargs bootargs 保存着传递给 Linux kernel 的参数。
    34~37 行,是处理 BOOTM_STATE_OS_FAKE_GO 状态的,因为我们没使能 TRACE
    功能,因此,宏 CONFIG_TRACE 也就没有定义,所以这段程序不会编译。

    第 49 行,调用 boot_selected_os函数启动 Linux 内核,此函数第 4 个参数为 Linux 系统镜 像头,第 5 个参数就是 Linux 系统启动 do_bootm_linux 函数 boot_selected_os 函数定义在文件common/bootm_os.c 中,函数内容如下:
    1. int boot_selected_os(int argc, char * const argv[], int state, bootm_headers_t *images, boot_os_fn *boot_fn)
    2. {
    3. arch_preboot_os();
    4. boot_fn(state, argc, argv, images);
    5. /* Stand-alone may return when 'autostart' is 'no' */
    6. if (images->os.type == IH_TYPE_STANDALONE ||
    7. state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
    8. return 0;
    9. bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
    10. #ifdef DEBUG
    11. puts("\n## Control returned to monitor - resetting...\n");
    12. #endif
    13. return BOOTM_ERR_RESET;
    14. }

    4 行,调用 boot_fn 函数,也就是 do_bootm_linux 函数来启动 Linux 内核。

    do_bootm_linux 函数简化代码如下,这里只列出此处会执行到代码:

    1. int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
    2. int states, bootm_headers_t *images, int boot_progress)
    3. {
    4. boot_os_fn *boot_fn;
    5. ulong iflag = 0;
    6. int ret = 0, need_boot_fn;
    7. images->state |= states;
    8. .............
    9. if (!ret && (states & BOOTM_STATE_OS_GO))
    10. ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
    11. images, boot_fn);
    12. .............
    13. return ret;
    14. }

  • 相关阅读:
    安卓快速实现流式布局(RecyclerView+ FlexboxLayout)
    eS6常用语法
    十倍增量的海外客户开发新方式来了!外贸企业可直接照做
    /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21‘ not found (required by
    Flutter | bloc 之 state 使用优化
    Python+selenium自动化生成测试报告
    C语言 | Leetcode C语言题解之第148题排序链表
    算法每日一题(python,2024.05.27) day.9
    Go短网址项目实战---上
    手写java冒泡、插入、选择、快速、归并排序算法
  • 原文地址:https://blog.csdn.net/wojiaxiaohuang2014/article/details/133773478