BIOS/UEFI基础——第一条指令

Reset Vector

本文讲述Intel x86系统启动后执行的最初的指令。

在Intel提供的软件开发者手册《64 ia 32 architectures softerware developer manual》中,有一个小节”First Instruction Executed“专门讲述系统中第一条指令的位置。

BIOS/UEFI基础——第一条指令_第1张图片

上面的文字简单来说阐明了以下的几点:

1. 第一条指令在的位置是0xFFFFFFF0(这个地址有个专有的名称Reset Vector);

2. 解释了CPU起来后是实地址模式为什么能够访问到这么高的位置;

3. 因为2的原因,在最初的代码中不应该有far jump等改变CS值的操作。

 

具体代码

Reset Vector的位置确定后,就可以在这个位置放上我们需要执行的代码。

CPU将这个位置映射到了某些非易失介质上了,比如SpiFlash,而这个介质里面保存着BIOS二进制。(前面这种说法不知道是哪里看来的,准确性不可考了,或者是以前的BIOS的特性。目前的UEFI来说,一般是TXE加载非易失性介质中的BIOS的起始代码部分到SRAM中,而SRAM映射到了从4G往下的一段区域中,这同样保证了Reset Vector 的位置是在0xFFFFFFF0

这里以UEFI代码为例。

UEFI代码按照一定的格式放在二进制中,在Reset Vector指向的位置,放的是SEC阶段的代码,它们是未经过压缩的机器码,CPU可以直接拿来执行。

对应到具体代码,如下:

;------------------------------------------------------------------------------
; @file
; This file includes all other code files to assemble the reset vector code
;
; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.
; This program and the accompanying materials ; are licensed and made available under the terms and conditions of the BSD License ; which accompanies this distribution. The full text of the license may be found at ; http://opensource.org/licenses/bsd-license.php ; ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ; ;------------------------------------------------------------------------------ ; ; If neither ARCH_IA32 nor ARCH_X64 are defined, then try to include ; Base.h to use the C pre-processor to determine the architecture. ; %ifndef ARCH_IA32 %ifndef ARCH_X64 #include #if defined (MDE_CPU_IA32) %define ARCH_IA32 #elif defined (MDE_CPU_X64) %define ARCH_X64 #endif %endif %endif %ifdef ARCH_IA32 %ifdef ARCH_X64 %error "Only one of ARCH_IA32 or ARCH_X64 can be defined." %endif %elifdef ARCH_X64 %else %error "Either ARCH_IA32 or ARCH_X64 must be defined." %endif %include "CommonMacros.inc" %include "PostCodes.inc" %ifdef DEBUG_PORT80 %include "Port80Debug.asm" %elifdef DEBUG_SERIAL %include "SerialDebug.asm" %else %include "DebugDisabled.asm" %endif %include "Ia32/SearchForBfvBase.asm" %include "Ia32/SearchForSecEntry.asm" %ifdef ARCH_X64 %include "Ia32/Flat32ToFlat64.asm" %include "Ia32/PageTables64.asm" %endif %include "Ia16/Real16ToFlat32.asm" %include "Ia16/Init16.asm" %include "Main.asm" %include "Ia16/ResetVectorVtf0.asm"

上面的代码是用nasm写的汇编。

实际上这里也没有涉及到具体的执行代码,真正重要的是ResetVectorVtf0.asm,其中有这样的代码:

resetVector:
;
; Reset Vector
;
; This is where the processor will begin execution
;
    nop
    nop
    jmp     EarlyBspInitReal16

ALIGN   16

这段代码被写到了UEFI二进制的最后一行,刚好对应0xFFFFFFF0的位置,下面是实际二进制中的值:

90 90 E9 AB FF 90 90 90 90 90 90 90 90 90 90 90

前面的90h就是nop的机器码,而后面的E9h ABh FFh是跳转指令的机器码。

跳转到EarlyBspInintReal16的代码去执行。

UEFI的执行过程一般被分为SEC、PEI、DXE和BDS四个阶段。

而这里的代码实际上还在SEC阶段之前,它最终会知道SEC entry并跳入,之后大部分就是C语言代码了。

 

你可能感兴趣的:(UEFI开发基础)