coreboot学习4:启动流程跟踪之romstage阶段
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 周二 夜