ramstage阶段涉及比较多的操作,比如枚举板子上的外围设备,分配资源(PCI),使能设备。本文根据该阶段的主干函数流程做分析,细节方面不涉及。理顺这个主干,从全局上把控大致流程。
romstage阶段执行完毕,在arch_prog_run函数中,使用jmp指令跳转到ramstge的入口地址。代码如下:
1 | __asm__ volatile ( |
之后就是ramstage阶段的运行了。主体代码在src\lib\hardwaremain.c中,主函数为main。该文件使用启动状态结构体(struct boot_state)定义了所有要执行的函数。定义如下:
1 | struct boot_state { |
每个函数运行结束后,都会返回下一次要执行的函数ID,这样就可以顺序地执行每个小阶段的函数。其实现是在最关键的函数:bs_walk_state_machine():
1 | static void bs_walk_state_machine(void) |
可以看到,首先从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的注释讲得十分清楚,摘录如下:
1 | /* |
总体流程图如下:
注:由于coreboot方面资料较少,笔者第一次尝试分析代码,还有众多未能参透的地方,难免出错。任何问题,欢迎一起交流学习。
李迟 2016.3.16 周三 夜