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寄存器)以跟踪执行流程。
流程图示如下:

coreboot学习4:启动流程跟踪之romstage阶段_第1张图片

二、baytrail-fsp

(李迟按:留空待写)


注:

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


李迟 2016.3.15 周二 夜

你可能感兴趣的:(微机/硬件底层/BIOS)