天天看点

UEFI原理与编程第一章学习汇总

BIOS

BIOS功能:

  • 加电自检程序,用于开机时对硬件的检测。
  • 系统初始化代码,包括硬件设备的初始化,创建 BIOS 中断向量等。
  • 基本的外围I/O处理的子程序代码。
  • CMOS程序设置。

BIOS工作流程:

  1. 加电自检(Power On Self Test,POST):检测关机设备是否正常工作,设备设置是否与CMOS(CMOS是是电脑主板上的一块可读写的RAM芯片,常用来保存BIOS设置完电脑硬件参数后的数据)中的设置一致。如果出现硬件错误则发出警报(鸣笛)。POST检测通过后进行初始化
  2. 初始化:初始化显示设备、显示显卡信息,然后初始化其他设备。
  3. 检查CPU和内存并显示检测结果。进行标准设备检测(如:硬盘、光驱、串口设备等)。结束标准设备检测后进行即插即用设备,并为其分配中断号、I/O端口号和DMA通道等资源。硬件设备发生改变时将变化记录到CMOS中。
  4. 根据配置的启动顺序从设备启动,将启动设备主引导记录的启动代码通过BIOS终端读入内存,然后将控制权交至引导程序,最终引导进入操作系统。

BIOS缺点:

  1. 开发效率较低:大部分BIOS使用汇编语言开发,使用汇编语言开发与硬件的耦合度过高,使得开发出来的BIOS严重受硬件影响。
  2. 性能差:BIOS基本输入/输出服务需要依靠中断来完成,而且BIOS没有异步工作模式,有大量的时间被消耗在等待。
  3. 不易进行功能扩展:在添加硬件功能时,必须将16位的代码放置在0x0C0000~0x0DFFFF间,初始化时才能将其设置为约定的中断处理程序。而且BIOS不能动态的加载设备驱动方案。
  4. 安全性较差:BIOS没有考虑运行过程中执行代码的安全性。
  5. 不支持从硬盘2 TB及以上的地址进行引导:BIOS硬盘采用32位地址,因此引导扇区的最大逻辑块地址是232(字节地址为:(232)*512=2 TB)

UEFI(Unified Extensible Firmware Interface)

UEFI简介:

  • UEFI是统一可扩展固件接口,定义了操作系统和平台固件之间交互的接口,它是UEFI Forum发布的一种标准,并没有提供实现。
  • UEFI的实现可以分为两部分:
    1. 平台初始化。
    2. 固件-操作系统接口。

UEFI系统组成:

  • UEFI供系统调用的接口:
    • 启动时服务(Boot Service,BS)
    • 运行时服务(Runtime Service,RT)
  • 隐藏在BS后的Protocol

    其中BS和RT以表的形式(C语言中的结构体)存在,UEFI驱动和服务以Protocol的形式通过BS提供给操作系统。

UEFI模式的启动的几个阶段:

  1. 操作系统加载器(OS Loader)被加载。
  2. OS Loader执行ExitBootServices()。

    从1->2的过程是从UEFI环境向操作系统过渡的过程,在该过程中,OS Loader可以通过BS和RT使用UEFI提供的服务,将计算机资源逐渐从UEFI转至操作系统。该过程被称为TSL(Transient System Load)

    当OS Loader完全掌握计算机系统资源是,BS便完成了其使命。OS Loader调用ExitBootServices()结束BS并回收BS占用的资源。计算机系统进入UEFI Runtime阶段。在Runtime阶段中只有RT继续为OS提供服务,BS已经被计算机系统销毁。

TSL阶段系统通过BS管理系统资源,此时BS提供的服务有:

  • 事件服务:事件是异步操作的基础。有了事件的支持,才可以在UEFI系统内执行并发操作。
  • 内存管理:主要提供内存的分配与释放,管理系统的内存映射。
  • Protocol管理:提供了安装Protocol与卸载Protocol的服务,以及注册Protocol通知函数(该函数会在Protocol安装时调用)的服务。【UEFI驱动和服务通过Protocol的形式通过BS提供给系统】
  • Protocol的实用类服务:包括Protocol的打开与关闭,查找支持Protocol的控制器。(比如:需要读写某个PCI设备的寄存器,可以通过OpenProtocol服务打开这个设备上的PciIo Protocol,用PciIo->Io.Read()服务读取这个设备上的寄存器。
  • 驱动管理:包括用于将驱动安装到控制器的connect服务,及将驱动从控制器上卸载的disconnect服务。(例如:如果我们启动时需要网络支持,则可以通过loadImage将驱动加载到内存,然后通过connect服务将驱动安装到设备)。
  • Image管理:此类服务包括加载、卸载、启动和推出UEFI应用程序或驱动。
  • ExitBootServices:用于结束启动服务,注销BS。

RT主要提供以下几个方面的业务:

  • 时间服务:读取/设置系统时间
  • 读写UEFI系统变量:读取/设置系统变量。(例如:BootOrder用于指定启动项顺序)更改这些系统变量可以改变系统配置。
  • 虚拟内存服务:将物理地址转换为虚拟地址。
  • 其它服务:重启系统、获取系统提供的下一个单调单增值等。

UEFI的优点

  1. UEFI具有较高的开发效率:BIOS一般采用汇编语言,代码多是与硬件相关的代码。而UEFI中大部分的代码可以用C语言进行编写,UEFI的应用程序和驱动也可以用C++编写。UEFI通过固件-操作系统接口(BS和RT服务)为OS和OS Loader屏蔽了底层硬件细节,使UEFI的上层应用可以重用。
  2. UEFI系统的可扩展性:UEFI系统的可扩展性主要体现在 驱动的模块化设计以及软硬件升级的兼容性。UEFI模式中驱动的模块化设计在于,大部分硬件的初始化通过UEFI驱动实现。每个驱动都是一个独立的模块,可以包含在固件中,也可以放在设备上,运行时根据需要来动态加载。软硬件升级的兼容性体现在,UEFI中每个表、每个Protocol(包括驱动)都有版本号,这使得系统可以很方便的进行平滑升级。
  3. UEFI系统的性能较高:相比于BIOS,UEFI有很大的性能提升,从启动到进入操作系统的事件大大缩短。原因主要有一下几点
    • 1、UEFI支持基于事件的异步操作,提高了CPU的效率,减少了总的等待时间;
    • 2、关于中断,UEFI仅保留了时钟中断,舍弃了其余的中断操作外部设备的方式,改为“事件+异步操作”;
    • 3、高效遍历设备的方式,启动时可以仅遍历启动所需的设备,从而加速系统启动;
    • 4、UEFI具有更高的安全性:相比于BIOS,UEFI的一个重要突破就是其在安全性方面的考虑。在系统的安全启动模式下UEFI在执行应用程序和驱动前会先检测程序和驱动的证书,仅当证书被信任时才会执行该程序或驱动。(UEFI的应用程序和驱动采用PE/COFF格式,其签名放在签名块中)

UEFI系统的启动过程

UEFI系统从加电到关机可分为以下七个阶段:

SEC(安全验证)->PEI(EFI前期初始化)->DXE(驱动执行环境)

->BDS(BS?)(启动设备选择)->TSL(操作系统加载前期)

->RT(Run Time)

->AL(系统灾难恢复期)

其中,前三个阶段为UEFI初始化加载阶段,DXE阶段结束后UEFI环境已经准备完毕。

BDS和TSL是UEFI运行OS Loader的阶段。

OS Loader调用ExitBootServices()服务后系统启动进入RT阶段,操作系统加载后期和操作系统运行期均属于RT阶段。

硬件系统或操作系统出现严重错误不能继续正常运行时,固件会尝试进行修复,此时系统进入AL期。但是PI规范和UEFI规范都没有规定AL期的行为。AL期的系统行为由系统供应商自行定义。

上述过程可见下图:

UEFI原理与编程第一章学习汇总

每个阶段具体的功能和流程:

  1. SEC(Security Phase,安全阶段)阶段

    SEC阶段是平台初始话的第一个阶段,计算机系统加电后首先进入这个阶段。

    • SEC阶段的功能:UEFI系统开机或重启后首先进入SEC阶段,SEC阶段系统执行以下四种任务:
      • 接收并处理系统启动和重启信号,系统加电信号、系统重启信号、系统运行过程中的异常信号。
      • 初始化临时存储区域:系统运行在SEC阶段时,仅CPU和CPU内部资源被初始化,而各种外部设备和内存都没有被初始化。因此系统需要一部分临时内存用于代码和数据的存储,一般称为临时RAM,临时RAM只能位于CPU内部(CPU和CPU内部的资源最先被初始化)。最常用的临时RAM是Cache,通过将Cache设置为no-eviction模式,来把其当成内存使用(此时读取命中则返回Cache中的数据,读取缺失并不会向主存发出缺失事件;写命中时写入Cache,写缺失时也不会向主存发出缺失事件),这种技术称为CAR(Cache As RAM)。
      • SEC阶段是可信系统的根:作为系统启动的第一部分,只有SEC能被系统信任,以后的各个阶段才有被信任的基础。因此,大部分情况下SEC再转交控制权给PEI前可以验证PEI是否可信。
      • 传递系统参数给下一阶段:SEC阶段的一切工作都是为PEI阶段做准备的,最重要把系统的控制权转交给PEI,并将SEC阶段的运行信息汇报给PEI。SEC通过将以下信息作为参数传递给PEI的入口程序来向PEI汇报信息:
        • 系统当前状态,PEI根据状态值判断系统当前的健康情况。
        • 可启动固件(Boot Firmware Volume)的地址和大小,PEI据此判断可用硬件。
        • 临时RAM区域的地址和大小。
        • 栈的地址和大小。
    • SEC阶段执行流程:

      根据临时RAM是否初始化为界限,SEC阶段分为两部分:临时RAM初始化前称为Reset Vector阶段;临时RAM初始化后调用SEC入口函数从而进入SEC功能区。其流程如下图:

      UEFI原理与编程第一章学习汇总
      其中Reset Vector的执行流程如下:
      1. 进入固件接口。
      2. 从实模式转换到32位平坦模式。
      3. 定位固件中的BFV(Boot Firmware Volume)。
      4. 定位BFV中的SEC影响。
      5. 如果是64位系统,则从32位模式转换至64位模式。
      6. 调用SEC入口函数。
      7. 在SEC功能区中初始化 临时RAM ,完成其功能后找到PEI的入口函数(PEI Image?)
  2. PEI(Pre-EFI Initialization,预先EFI初始化)阶段

    虽然SEC阶段对CPU和CPU内的资源进行了初始化,但是PEI阶段可用的资源依旧十分有限,该阶段对内存进行初始化,主要功能是为DXE阶段准备执行环境,将所需要传递给DXE的信息组成HOB(Hand Off Block)列表,最终将控制权转交到DXE。

    UEFI具有模块化设计的特点,PEI就是一个模块。PEI Image的入口函数调用PEI模块的入口函数PEICore。

    • PEI阶段的功能:
      • 初始化内存。
      • 为DXE阶段准备执行环境。
    • PEI划分:
      • PEI内核(PEI Foundation):负责PEI基础服务和流程。
      • PEIM(PEI Module)派遣器:找出系统中的所有PEIM,并根据PEIM之间的依赖关系按顺序执行PEIM。PEI阶段对系统的初始化主要由PEIM完成。

        每个PEIM都是一个独立的模块。通过PEIServices,PEIM可以调用PEI阶段(UEFI?)提供的系统服务。通过调用这些服务,PEIM可以访问PEI内核。PEIM之间的的通信通过PPI(PEIM-to-PEIM Interfaces)完成。

    • PEI阶段执行流程:
      1. 进入PEI入口。
      2. 根据SEC阶段传入的信息初始化PS(PEI Core Service)。
      3. 调度系统中的PEIM(PEI Module),准备HOB列表。

        具体调用的系统中的PEIM有:CPU PEIM(提供CPU相关功能,如进行Cache设置、主频设置等);平台相关PEIM(初始化内存控制器、I/O控制器等);内存初始化PEIM(对内存进行初始化,此时内存才可用,之前使用的CPU模拟的临时内存)。

      4. 调用PEIServices得到DEX IPL PPI的Entry服务(即DEXLoadCore)。

        注:PPI与DEX阶段的Protocol类似,每个PPI都是一个结构体,包含有函数指针和变量。每个PPI都有一个GUID。通过PEIServices的LocatePPI服务可以找到GUID对应的PPI实例。

      5. DXELoadCore服务找出并运行DXEImage的入口函数,将HOB列表传递给DXE。

      PEI阶段执行流程完整描述:SEC模块找到PEI Image的入口函数 _ModuleEntryPoint(该函数位于MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c), _ModuleEntryPoint函数最终调用PEI模块的入口函数PEICore(该函数位于MdeModulePkg/Core/Pei/PeiMain/PeiMain.c),进入PEICore后,首先根据从SEC阶段出入的信息设置PEI Core Services,然后调用PEIDispatcher执行系统总的PEIM,在内存初始化完成后,系统切换栈并重新进入PEICore。重新进入PEICore后使用的不再是 临时RAM 而是真正的内存。在所有PEIM执行完成后,调用PEIServices的LocatePPI服务得到DXE IPL PPI,并调用DXE IPL PPI的Entry服务(即DEXLoadCore),找出DEX Image的入口函数,执行DXE Image函数并将HOB列表传递给DXE。

      PEI阶段执行流程如下图:

      UEFI原理与编程第一章学习汇总
  3. DXE(Driver Execution Environment,执行驱动配置环境)阶段

    DXE阶段执行系统大部分的初始化工作。由于此阶段内存已经可以被正常使用,因此该阶段可以执行大量复杂的工作。从程序设计角度DXE阶段与PEI阶段相似。

    • DXE阶段的功能:
      • 执行系统大部分的初始化工作
      • 提供系统表、启动服务以及Run Time Services。
    • DXE划分:
      • DXE内核:负责DXE的基础服务和执行流程
      • DXE派遣器:负责调度执行DXE驱动,初始化系统设备。
    • DXE执行流程:
      1. 从DXE入口进入DXE阶段。
      2. 根据HOB列表初始化系统服务。
      3. 调度系统中的Driver。

        详:遍历固件中所有的Driver,当Driver所依赖的资源得到满足时,调度Driver到执行队列执行,直到所有满足条件的Driver都被执行。

      4. 打开EFI_BDS_ARCH_PROTOCOL。
      5. EFI_BDS_ARCH_PROTOCOL->Entry。

      DXE驱动之间通过Protocol通信。Protocol是一种特殊的结构体,每个Protocol都有一个GUID,通过系统BootServices的OpenProtocol,可以根据GUID调用对应的Protocol,从而使用这个Protocol提供的服务。

      在所有的Driver都执行完成后,系统完成初始化,DEX通过EFI_BDS_ARCH_PROTOCOL找到BDS并屌用BDS的入口函数,从而进入BDS阶段(从本质上讲BDS是一种贴无数的DXE)。

      DXE的执行流程如下图所示:

      UEFI原理与编程第一章学习汇总
  4. BDS(Boot Device Selection,选择boot设备)阶段
    • BDS阶段的功能有:
      • 执行启动策略(主要功能)。
      • 初始化控制台设备。
      • 加载必要的设备驱动。
      • 根据系统设置加载和执行启动项。
      当加载项其启动失败时,系统将重新执行DXE dispatcher以加载更多的驱动,然后重新尝试加载驱动项。BDS策略通过全局NVRAM变量配置,这些变量可以被运行时服务的GetVariable()读取,通过SetVariable()设置(如BootOrder定义了启动顺序,Boot####对应不同的启动项,#为十六进制数)。当用户选中某个启动项(或进入系统默认启动项)后,OS Loader启动,系统进入TSL阶段。
  5. TSL(Transient System Load)阶段

    TSL阶段是OS Loader(操作系统加载器)执行的第一阶段,这一阶段的OS Loader作为一个UEFI应用程序运行,系统资源有UEFI内核控制。但是当ExitBootServices()服务被调用后,系统将进入Run Time阶段。

    TSL阶段被称为临时系统的原因在于,其存在的目的就是为操作系统加载器准备执行环境。虽然是临时系统,但已经具备操作系统的雏形,UEFI Shell是这个临时系统的人机交互界面。正常运行中,系统不会进入UEFI Shell,而是直接执行OS Loader,只有在用户干预或是操作系统加载器出现严重问题时才会进入UEFI Shell。

  6. RT(Run Time,运行)阶段

    系统进入RT阶段后系统控制权从UEFI内核转交至OS Loader,UEFI占用的各种资源被OS Loader接管。随着OS Loader的继续执行,操作系统将完全取得对电脑的控制权。

  7. AL(After Life)阶段

    在RT阶段如果系统(硬件或是软件)遇到灾难性错误,系统固件需要提供错误处理以及灾难恢复机制,这种机制运行在AL阶段。UEFI和UEFI PI均未对AL阶段的行为和规范进行定义。

总结

与BIOS相比,UEFI具有更好的可编程性(PPI、Protocol)、更高的安全性(SEC)、更强的可扩展性,并且其设计相比BIOS能更好的适应64位平台,这使得UEFI能迅速的取代BIOS。

UEFI定义了操作系统和平台间的接口。UEFI接口可以分为以下两个部分:

  1. 启动服务:启动时服务的主要对象是操作系统(OS)、操作系统加载器(OS Loader)以及其他UEFI应用程序和UEFI驱动。操作系统加载器(OS Loader)通过启动服务逐步取得对整个计算机资源的控制。当加载器完全控制计算机软硬件资源后,系统会结束启动服务,进入运行时服务。启动服务主要包括有:时间服务、内存管理、Protocol管理、Protocol使用类服务、驱动管理、Image管理及ExitBootServices服务。
  2. 运行时服务:运行时服务主要的服务对象是操作系统、操作系统加载器以及UEFI应用和UEFI驱动。运行时服务主要包括:时间服务、读写UEFI系统变量服务、虚拟内存服务以及重启系统服务。

继续阅读