romstage是coreboot的第二个执行阶段。本文分别介绍基于qemu模拟环境的x86的跟踪,以及基于Intel baytrail平台的跟踪。
在romstage阶段,由于内存还未初始化好,所以使用cache作为内存,此项技术称为“cache as ram”,简称为“CAR”。网络上有较多文章涉及此方面,可以查阅以了解更多。
一、qemu-i440fx
cache_as_ram文件:src\mainboard\emulation\qemu-i440fx\cache_as_ram.inc
1、保存BIST
BIST值会作为romstage主函数的参数。
/* Save the BIST result. */
movl %eax, %ebp
2、设置CAR
(注:这段代码还不是太理解)
cache_as_ram:
post_code(0x20)
/* Clear the cache memory region. This will also fill up the cache */
movl $CACHE_AS_RAM_BASE, %esi
movl %esi, %edi
movl $(CACHE_AS_RAM_SIZE >> 2), %ecx
// movl $0x23322332, %eax
xorl %eax, %eax
/* 使用 EAX 填写位于 ESI:EDI 的 ECX 个双字 */
/* 将CACHE_AS_RAM_BASE地址的大小为CACHE_AS_RAM_SIZE区域初始化为0 */
rep stosl
post_code(0x21)
/* Set up the stack pointer. */
movl $(CACHE_AS_RAM_SIZE + CACHE_AS_RAM_BASE - 4), %eax
movl %eax, %esp
3、恢复BIST值
/* Restore the BIST result. */
movl %ebp, %eax
movl %esp, %ebp
/* eax为BIST值,将其压栈,作为main的参数,然后调用main函数 */
pushl %eax
/*测试 pushl $0xdeadbeaf*/
4、调用romstage主函数
上段代码恢复BIST值到eax寄存器后,即将eax压入栈中,接着调用main函数,这个函数在romstage.c文件中定义。
before_romstage:
post_code(0x29)
/* 跳转到romstage的主函数 */
/* Call romstage.c main function. */
call main
5、跳转到ramstage阶段
在main函数返回后,调用copy_and_run函数,之后就到了ramstage阶段了。
/* 调用完main后,就到了copy_and_run,即ramstage阶段了 */
__main:
post_code(POST_PREPARE_RAMSTAGE)
cld /* Clear direction flag. */
movl $CONFIG_RAMTOP, %esp
movl %esp, %ebp
/* 此处为调试用
movl $9, %eax
pushl %eax
*/
/* 调用copy_and_run */
call copy_and_run
.Lhlt:
post_code(POST_DEAD_CODE)
hlt
jmp .Lhlt
至此,分析结束。
下面看看romstage的主函数。
4.1、main函数
代码如下:
// bist为blockboot传递的参数,intel在启动时会进行自检,正常情况下bist为0
// 在cache_as_ram.inc中会调用到此处的main
void main(unsigned long bist)
{
int cbmem_was_initted;
/* init_timer(); */
post_code(0x05);
console_init();
ll_printk("qemu-i440fx romstage --BIST: 0x%x\n", (unsigned int)bist);
/* Halt if there was a built in self test failure */
report_bist_failure(bist);
//print_pci_devices();
//dump_pci_devices();
cbmem_was_initted = !cbmem_recovery(0);
timestamp_init(timestamp_get());
timestamp_add_now(TS_START_ROMSTAGE);
}
很简单,调用console_init函数初始化终端,在该函数中会打印coreboot的版本号以及编译时间。如果传入的参数的bist值不为0,则出错,直接挂机。
注:ll_printk为代码使用的打印函数,本文中使用bist值(即cache_as_ram.inc的eax寄存器)以跟踪执行流程。
流程图示如下:
二、baytrail-fsp
(李迟按:留空待写)
注:
由于coreboot方面资料较少,笔者第一次尝试分析代码,还有众多未能参透的地方,难免出错。任何问题,欢迎一起交流学习。
李迟 2016.3.15 周二 夜