ramstage阶段涉及比较多的操作,比如枚举板子上的外围设备,分配资源(PCI),使能设备。本文根据该阶段的主干函数流程做分析,细节方面不涉及。理顺这个主干,从全局上把控大致流程。

romstage阶段执行完毕,在arch_prog_run函数中,使用jmp指令跳转到ramstge的入口地址。代码如下:

__asm__ volatile (
#ifdef __x86_64__
"jmp  *%%rdi\n"
#else
"jmp  *%%edi\n"
#endif

:: "D"(prog_entry(prog))
);

之后就是ramstage阶段的运行了。主体代码在src\lib\hardwaremain.c中,主函数为main。该文件使用启动状态结构体(struct boot_state)定义了所有要执行的函数。定义如下:

struct boot_state {const char *name;boot_state_t id;u8 post_code;struct boot_phase phases[2];boot_state_t (*run_state)(void *arg);void *arg;int complete : 1;
#if CONFIG_HAVE_MONOTONIC_TIMERstruct boot_state_times times;
#endif
};#define BS_INIT(state_, run_func_)                \{                          \.name = #state_,              \.id = state_,                 \.post_code = POST_ ## state_,         \.phases = { { NULL, 0 }, { NULL, 0 } },       \.run_state = run_func_,               \.arg = NULL,                  \.complete = 0,                    \}
#define BS_INIT_ENTRY(state_, run_func_)    \[state_] = BS_INIT(state_, run_func_)// 此结构体定义ramstage依次执行的函数
// 前一函数结束后会返回下一阶段要执行的函数id
static struct boot_state boot_states[] = {BS_INIT_ENTRY(BS_PRE_DEVICE, bs_pre_device),BS_INIT_ENTRY(BS_DEV_INIT_CHIPS, bs_dev_init_chips),BS_INIT_ENTRY(BS_DEV_ENUMERATE, bs_dev_enumerate),BS_INIT_ENTRY(BS_DEV_RESOURCES, bs_dev_resources),BS_INIT_ENTRY(BS_DEV_ENABLE, bs_dev_enable),BS_INIT_ENTRY(BS_DEV_INIT, bs_dev_init),BS_INIT_ENTRY(BS_POST_DEVICE, bs_post_device),BS_INIT_ENTRY(BS_OS_RESUME_CHECK, bs_os_resume_check),BS_INIT_ENTRY(BS_OS_RESUME, bs_os_resume),BS_INIT_ENTRY(BS_WRITE_TABLES, bs_write_tables),BS_INIT_ENTRY(BS_PAYLOAD_LOAD, bs_payload_load),BS_INIT_ENTRY(BS_PAYLOAD_BOOT, bs_payload_boot),
};

每个函数运行结束后,都会返回下一次要执行的函数ID,这样就可以顺序地执行每个小阶段的函数。其实现是在最关键的函数:bs_walk_state_machine():

static void bs_walk_state_machine(void)
{while (1) {static int cnt = 1;struct boot_state *state;boot_state_t next_id;// 拿到一个statestate = &boot_states[current_phase.state_id];if (state->complete) {printk(BIOS_EMERG, "BS: %s state already executed.\n",state->name);break;}if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE))printk(BIOS_DEBUG, "BS: Entering %s state.\n",state->name);bs_run_timers(0);bs_sample_time(state);bs_call_callbacks(state, current_phase.seq);/* Update the current sequence so that any calls to block the* current state from the run_state() function will place a* block on the correct phase. */current_phase.seq = BS_ON_EXIT;bs_sample_time(state);ll_printk("%s() state %d start==============================\n", __func__, state->id);post_code(state->post_code);// 真正调用boot_states定义好的函数// 函数返回后,得到下一次要执行的idnext_id = state->run_state(state->arg);if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE))printk(BIOS_DEBUG, "BS: Exiting %s state.\n",state->name);bs_sample_time(state);bs_call_callbacks(state, current_phase.seq);if (IS_ENABLED(CONFIG_DEBUG_BOOT_STATE))printk(BIOS_DEBUG,"----------------------------------------\n");/* Update the current phase with new state id and sequence. */current_phase.state_id = next_id;current_phase.seq = BS_ON_ENTRY;bs_sample_time(state);bs_report_time(state);state->complete = 1;}
}

可以看到,首先从boot_states拿到一个结构体(根据current_phase结构,此时获取到的实际上是第一个要执行的,即BS_PRE_DEVICE的结构体),然后调用该结构的run_state函数指针(比如第一个状态即为bs_pre_device函数),该函数返回的是下一状态ID,赋值给next_id,再更改current_phase中的值。不断的循环,直到结束。——事实上,coreboot最终的状态将会是payload,而payload之后,就是操作系统了,这些不再是coreboot管控范围了。因此,这个函数虽然由while(1)不断循环执行,实质上到payload后即结束了。

关于启动的状态过程,在头文件src\include\bootstate.h的注释讲得十分清楚,摘录如下:

/** The boot state machine provides a mechanism for calls to be made through-* out the main boot process. The boot process is separated into discrete* states. Upon a state's entry and exit and callbacks can be made. For* example:**      Enter State*           +*           |*           V*   +-----------------+*   | Entry callbacks |*   +-----------------+*   | State Actions   |*   +-----------------+*   | Exit callbacks  |*   +-------+---------+*           |*           V*       Next State** Below is the current flow from top to bottom:**        start*          |*    BS_PRE_DEVICE*          |*    BS_DEV_INIT_CHIPS*          |*    BS_DEV_ENUMERATE*          |*    BS_DEV_RESOURCES*          |*    BS_DEV_ENABLE*          |*    BS_DEV_INIT*          |*    BS_POST_DEVICE*          |*    BS_OS_RESUME_CHECK -------- BS_OS_RESUME*          |                          |*    BS_WRITE_TABLES              os handoff*          |*    BS_PAYLOAD_LOAD*          |*    BS_PAYLOAD_BOOT*          |*      payload run** Brief description of states:*   BS_PRE_DEVICE - before any device tree actions take place*   BS_DEV_INIT_CHIPS - init all chips in device tree*   BS_DEV_ENUMERATE - device tree probing*   BS_DEV_RESOURCES - device tree resource allocation and assignment*   BS_DEV_ENABLE - device tree enabling/disabling of devices*   BS_DEV_INIT - device tree device initialization*   BS_POST_DEVICE - all device tree actions performed*   BS_OS_RESUME_CHECK - check for OS resume*   BS_OS_RESUME - resume to OS*   BS_WRITE_TABLES - write coreboot tables*   BS_PAYLOAD_LOAD - Load payload into memory*   BS_PAYLOAD_BOOT - Boot to payload*/typedef enum {BS_PRE_DEVICE,BS_DEV_INIT_CHIPS,BS_DEV_ENUMERATE,BS_DEV_RESOURCES,BS_DEV_ENABLE,BS_DEV_INIT,BS_POST_DEVICE,BS_OS_RESUME_CHECK,BS_OS_RESUME,BS_WRITE_TABLES,BS_PAYLOAD_LOAD,BS_PAYLOAD_BOOT,
} boot_state_t;

总体流程图如下:

注:
由于coreboot方面资料较少,笔者第一次尝试分析代码,还有众多未能参透的地方,难免出错。任何问题,欢迎一起交流学习。

李迟 2016.3.16 周三 夜

coreboot学习5:启动流程跟踪之ramstage阶段主干分析相关推荐

  1. coreboot学习4:启动流程跟踪之romstage阶段

    romstage是coreboot的第二个执行阶段.本文分别介绍基于qemu模拟环境的x86的跟踪,以及基于Intel baytrail平台的跟踪. 在romstage阶段,由于内存还未初始化好,所以 ...

  2. coreboot学习3:启动流程跟踪之bootblock阶段

    coreboot的第一个启动阶段为bootblock.该阶段均使用汇编语言编写.下面根据执行文件顺序介绍. 一.reset16.inc bootlbock的最开始执行的文件为src\cpu\x86\1 ...

  3. I.MX6 Linux Qt 启动流程跟踪

    /*************************************************************************** I.MX6 Linux Qt 启动流程跟踪* ...

  4. BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) author:wolfenstein Tracker在BT中是一个很重要的部分.这个名词我注意到以前的文章中都是直接引用,没 ...

  5. BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化)

    BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) 发信人: wolfenstein (NeverSayNever), 个人文集 标  题: BT源代码学习心得(六):跟踪服务 ...

  6. BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) -- 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) author: wolfenstein (NeverSayNever) 上次我们分析了Tracker类初始化的 ...

  7. BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) - 转贴自 wolfenstein (NeverSayNever)

    BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) author: wolfenstein 通过上一次的分析,我们已经知道了Tracker采用http协议和客户端通 ...

  8. U-Boot启动流程(Linux内核)的分析

    http://www.360doc.com/content/12/0816/10/7775902_230452499.shtml     前面一段时间一直在移植U-Boot,Linux内核和构建根文件 ...

  9. U-Boot启动流程(Linux内核)的分析(写得好)

    前面一段时间一直在移植U-Boot,Linux内核和构建根文件系统,其中有些地方还不是很明白,现在回过头来,理解一下U-boot的启动流程,以及 u-Boot是如何加载引导内核启动的.这里的分析也都是 ...

最新文章

  1. 关于一个CCIE考试题目的研究(重分发)
  2. Linux查看utmp文件,linuxc操作utmp和wtmp文件接口
  3. 调查谋杀案以换取Obra Dinn
  4. react form表单 input和textarea用法
  5. linux卸载emc硬盘,关于EMC symmetrix新分磁盘在Linux主机无法fdisk? 求助
  6. 视频教程-通俗易懂的JavaScript高级教程(含资料)-JavaScript
  7. 模式识别 算法练习(一)——C均值算法
  8. 网络盘的计算机密码是什么,如何让win7映射网络驱动器记住密码
  9. 网路岗v1.2简单使用
  10. 大图书馆 #2 大教堂与集市
  11. 狂神SSM项目整合(含完整代码免费)
  12. win10计算机名和计算机物理地址,Win10系统查询电脑MAC地址方法【图文】
  13. python中def demo是什么意思_Python def函数的定义、使用及参数传递实现代码
  14. Nginx和HA负载
  15. 健康小贴士:喝酒时别点哪些菜_新闻中心_新浪网
  16. WordPress安装教程
  17. swift之汤姆猫实现(UIImageView动画播放)
  18. 如何与低智商的人相处?
  19. |函数相乘分离 函数增长速度|day6
  20. 某直播APP逆向TCP协议分析

热门文章

  1. 用PHP控制您的浏览器cache
  2. 有啥区别?谷歌Chrome浏览器图标8年来首次更新
  3. 贾跃亭:FF未来主义者们最终所要创造的社会价值 一定会得到资本市场的认可...
  4. 苹果任命软件主管凯文•林奇为“苹果汽车”项目负责人
  5. 5G的To C 应用还是没有和消费者强关联
  6. 小米平板5采用120Hz高刷LCD屏:纯平中框+侧面指纹
  7. 3月起这些新规将实施:从事网络招聘服务应取得许可证
  8. 微软将发布新版Win10 可能以“新 Windows”之名公布
  9. 运营九年,这款音乐手游宣布停服!将从应用商店下架...
  10. 腾讯未成年保护措施再优化,专治孩子忽悠家长帮过人脸识别