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

来源:互联网 发布:t-sql语法基础知识 编辑:程序博客网 时间:2024/04/30 10:10

Reset Vector

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

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


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

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.<BR>; 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 <Base.h>    #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     EarlyBspInitReal16ALIGN   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语言代码了。


0 0