coreboot学习5:启动流程跟踪之ramstage阶段主干分析
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阶段主干分析相关推荐
- coreboot学习4:启动流程跟踪之romstage阶段
romstage是coreboot的第二个执行阶段.本文分别介绍基于qemu模拟环境的x86的跟踪,以及基于Intel baytrail平台的跟踪. 在romstage阶段,由于内存还未初始化好,所以 ...
- coreboot学习3:启动流程跟踪之bootblock阶段
coreboot的第一个启动阶段为bootblock.该阶段均使用汇编语言编写.下面根据执行文件顺序介绍. 一.reset16.inc bootlbock的最开始执行的文件为src\cpu\x86\1 ...
- I.MX6 Linux Qt 启动流程跟踪
/*************************************************************************** I.MX6 Linux Qt 启动流程跟踪* ...
- BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) -- 转贴自 wolfenstein (NeverSayNever)
BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) author:wolfenstein Tracker在BT中是一个很重要的部分.这个名词我注意到以前的文章中都是直接引用,没 ...
- BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化)
BT源代码学习心得(六):跟踪服务器(Tracker)的代码分析(初始化) 发信人: wolfenstein (NeverSayNever), 个人文集 标 题: BT源代码学习心得(六):跟踪服务 ...
- BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) -- 转贴自 wolfenstein (NeverSayNever)
BT源代码学习心得(七):跟踪服务器(Tracker)的代码分析(HTTP协议处理对象) author: wolfenstein (NeverSayNever) 上次我们分析了Tracker类初始化的 ...
- BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) - 转贴自 wolfenstein (NeverSayNever)
BT源代码学习心得(八):跟踪服务器(Tracker)的代码分析(用户请求的实际处理) author: wolfenstein 通过上一次的分析,我们已经知道了Tracker采用http协议和客户端通 ...
- U-Boot启动流程(Linux内核)的分析
http://www.360doc.com/content/12/0816/10/7775902_230452499.shtml 前面一段时间一直在移植U-Boot,Linux内核和构建根文件 ...
- U-Boot启动流程(Linux内核)的分析(写得好)
前面一段时间一直在移植U-Boot,Linux内核和构建根文件系统,其中有些地方还不是很明白,现在回过头来,理解一下U-boot的启动流程,以及 u-Boot是如何加载引导内核启动的.这里的分析也都是 ...
最新文章
- 关于一个CCIE考试题目的研究(重分发)
- Linux查看utmp文件,linuxc操作utmp和wtmp文件接口
- 调查谋杀案以换取Obra Dinn
- react form表单 input和textarea用法
- linux卸载emc硬盘,关于EMC symmetrix新分磁盘在Linux主机无法fdisk? 求助
- 视频教程-通俗易懂的JavaScript高级教程(含资料)-JavaScript
- 模式识别 算法练习(一)——C均值算法
- 网络盘的计算机密码是什么,如何让win7映射网络驱动器记住密码
- 网路岗v1.2简单使用
- 大图书馆 #2 大教堂与集市
- 狂神SSM项目整合(含完整代码免费)
- win10计算机名和计算机物理地址,Win10系统查询电脑MAC地址方法【图文】
- python中def demo是什么意思_Python def函数的定义、使用及参数传递实现代码
- Nginx和HA负载
- 健康小贴士:喝酒时别点哪些菜_新闻中心_新浪网
- WordPress安装教程
- swift之汤姆猫实现(UIImageView动画播放)
- 如何与低智商的人相处?
- |函数相乘分离 函数增长速度|day6
- 某直播APP逆向TCP协议分析
热门文章
- 用PHP控制您的浏览器cache
- 有啥区别?谷歌Chrome浏览器图标8年来首次更新
- 贾跃亭:FF未来主义者们最终所要创造的社会价值 一定会得到资本市场的认可...
- 苹果任命软件主管凯文•林奇为“苹果汽车”项目负责人
- 5G的To C 应用还是没有和消费者强关联
- 小米平板5采用120Hz高刷LCD屏:纯平中框+侧面指纹
- 3月起这些新规将实施:从事网络招聘服务应取得许可证
- 微软将发布新版Win10 可能以“新 Windows”之名公布
- 运营九年,这款音乐手游宣布停服!将从应用商店下架...
- 腾讯未成年保护措施再优化,专治孩子忽悠家长帮过人脸识别