# BIOS 阶段划分
SEC:Security(安全) : 处理平台重事件,创造一个临时的内存区 (此时内存还未初始化),在系统中作为一个可信的 root,传递信息到PEIPEI:pre-efi initialization(预 EFI 初始化):初始化一些永久的内存HOBS (hand-off BLocks) 中内存,以及在 HOBS 里面的FV(firmware volume) 位置,传递控制权到DXE阶段DXE:driver execution environment(驱动程序执行环境) :重点关注,服务器上硬件驱动的执行环境,与后期外设的使用,有极大的关系BDS:boot device select(引导设备选择) 初始化console设备;加载设备驱动;尝试加载和执行启动项。RT:run time service(运行时服务) :此时与bootloader关系紧密AL:after life(transition from the os back to the environment)of system
# 与 BMC 通信
# 基础了解
# 平台管理
- 平台管理 (
platform managemet): 平台管理表示一系列的监视和控制功能,操作的对象是系统硬件,比如监视系统的温度,电压,风扇,电源等,并做响应的调节工作,以保证系统处于健康状态。若系统不正常,通过复位方式重启
BMC:Baseboard Management Controller): 把上面的功能集成到一个控制器上,称为基板管理控制器,BMC是一个独立的系统,它不依赖系统上的其它硬件(如CPU,内存),也不依赖于BIOS,OS等,但BMC可以与BIOS和OS交互。BMC 本身也是一个带外处理器(一般都是 ARM 处理器) 的小系统,单独用来处理某些工作,其中重点还是平台管理
BMC通过不同的接口与系统中其它组件连接,LPC,I2C,SMBUS,Serial等基本接口
IPMI, 它是与BMC匹配的接口,所有BMC都需要实现这种接口
# IPMI
IPMI全称Intelligent Platform Management Interface智能平台管理接口,IPM是对平台管理概念的具体规范,该规范定义了平台管理的软硬件架构,交互指令,事件格式,数据记录,能力集等,而BMC是IPMI中的一个核心部分,属于IPMI硬件架构。
# BIOS 通信
BIOS与BMC之间的通信,主要使用IPMI。共有两个阶段PEI和DXE(包括DXE后面的),用的是不同的IPMI函数 (重点注意)虽然后使用
IPMI,但使用两个通道分别是KCS,BT,一般使用KCS通道。
BMC不会主动与 BIOS 通信,BIOS 会发送IPMI命令给BMC,BMC如果成功接收的话,就会有个返回信息给BIOS。
# 如果 BMC 与 BIOS 产生了通信故障
- 确认
BIOS是否发送了IPMI命令给BMC, 可以查看BMC返回的completion code; - 确认
BMC是否收到了BIOS发送的IPMI命令 - 如果
BIOS发送了IPMI命令,但是BMC未接收:可能是BMC的IPMI进程正处于忙碌状态,所以丢掉了这条IPMI命令 (BIOS 如果发送失败,可以尝试多次发送;另外可以稍微调高KCS通道的延时);当然,也有可能是 BMC 的IPMI进程挂了 - (极少见)
一条IPMI命令通常设计2个底层实现函数,SendDataToBmcPort()和ReceiveBmcDataFormPort()。接收时,BIOS 从KCS的I/O端口读取数据,读完后,会检测KCS寄存器中OBF状态寄存器,如果BMC没有写数据,就会计数-1,延时5ms,然后重试,当BMC一直不写数据时,计数到0, 就认为BMC有故障,返回Device Error;
# ACPI
Advanced Configuration and Power Interface简称ACPI,高级配置与电源接口,提供操作系统应用程序管理所有电源管理接口。对于 BIOS 而言,
ACPI最直观的就是电源功耗,从而影响CPU性能,
# OS Loader
操作系统加载器:
引导加载程序
OS loader可以通过BS(Boot Services)和RT使用UEFI提供的服务,并且将计算机的资源转移到自己手中,此过程称为TSL(Transient System Loader)。在此阶段结束之后,OS Loader会调用ExitBootServices()函数,结束BS并且回收BS占用的资源,然后BIOS会进入RT阶段,然后OS loader会加载操作系统内核,逐渐进入 OS,此过程称为TSL(Transient System Load)在
BDS阶段,BIOS会选择可启动项,按照设置的顺序,逐一尝试,经过校验之后,加载OS Loader
BIOS(BDS阶段)---->OS Loader---->OS引导区位于
FAT32格式分区。一般 FAT32 位于磁盘的最开始,大小 1MB 左右。
UEFI 会把
FAT32的格式都当做启动磁盘都添加到启动菜单中在启动盘
UEFI/Boot/BootX64.efi中加载
# 硬盘启动盘文件也都位于此 EFI/Boot/BootX64.efi# 32 位系统无需 + X64
# UEFI
UEFI(Unified Extensible Firmware Interface, 统一可扩展固件接口) 提供给操作系统的接口包括启动服务(Boot Service,BS) 和运行时服务 (Runtime Service,RT) 以及隐藏在BS之后的丰富的Protocol(协议),BS和RT以表的形式 (C 语言中的结构体) 存在。UEFI 的实现分为两部分
平台初始化固件- 操作系统接口
# 组成
OS Loader可以通过BS和RT使用UEFI提供的服务,将计算机资源逐渐转移到自己手中,这个过程为TSL(Transient System Load)
当
OS Loader完全掌握了计算机资源时,BS也就完成了它的使命。OS Loader调用ExitBootServices()结束BS并回收BS占用的资源,之后计算机系统进入UEFI Runtime阶段
# BS 提供的服务 (TSL 阶段)
UEFI提供给操作系统的接口,包括启动服务(Boot Services,BS)
事件服务:事件时异步操作的基础,有了事件的支持,才能够在UEFI系统内执行并发操作内存管理:提供内存的分配与释放,管理系统内存映射Protocol管理:提供了安装与卸载Protocol 的服务,注册通知函数的服务Protocol使用类服务:Protocol的打开与关闭,查找支持Protocol控制,例打开设备上PciloProtocol, 用PciIo->Io.Read()服务读取设备上的寄存器驱动管理:包括用于将驱动安装到控制器的connect服务,以及将驱动从控制器上卸载的disconnect服务。若启动时,需要网络服务,通过 loadImage 将驱动加载到内存,通过connect服务将驱动安装到设备Image管理:加载,卸载,启动和退出 UEFI 应用程序或驱动ExitBootServices:用于结束启动服务
# RT 提供的服务
UEFI 提供给操作系统的
运行时服务
时间服务:读取 / 设定系统时间,- 读取
UEFI系统变量:读取 / 设置系统变量,例如BootOrder用于指定启动项顺序,通过系统变量保存系统配置 虚拟内存服务: 将物理地址转换为虚拟地址- 其它服务:包含
重启系统的ResetSystem, 获取系统提供的下一个单调单增值。
# UEFI 启动过程
# SEC 阶段
Security Phase, 当 CPU 收到ResetVector信号后,开始执行第一行代码, 平台初始化的第一个阶段,安全阶段,最早运行的固件代码,此模块相当部分使用汇编语言开发。电脑的开机或者重启,
本质上是给 CPU 发送了一个ResetVector信号。由于
没有初始化内存,会临时使用CPU的缓存,内嵌在 CPU 中,初始化好的,SEC 作为整个系统执行的起点,可能遇到各种异常,就需要设置
IDT,有了中断描述符表接受异常,就能让系统遭遇意外情况时,不至于崩溃,为 PEI 阶段设置临时内存的基地址和长度并传给 PEI,同时将 PEI 代码的入口点,将控制权移交过去,并且处理临时内存。
# 位于 EDK2 如下目录 UefiCpuPkg/ResetVector/Vtf0
# SEC 阶段任务
- 接受并处理系统
启动和重启信号,以及运行过程中的严重异常信号初始化临时存储区域,启动系统需要的一些临时RAM,空间资源仍然稀缺- 作为
可信系统根传递给下一个阶段PEI
# Reset Vector
- 进入
固件入口- …..
# PEI 阶段
PEI :
Pre-EFI Initialization
资源十分有限,PEI后期进行内存初始化- 为
DXE准备执行环境,将需要传递的信息组成HOB列表,将控制权移交到DXE手中
PEI Foundation: 负责接受SEC发送的交换数据,并扮演模块分发的角色PEIMs-EFI Initlization Modules是模块化的,PEI阶段的 4 档事情就是交给PEIMs完成,完成后就来到了DXE阶段。
对
系统的初始化,找出系统中所有的PEIM,并根据PEIM之间的依赖关系按照顺序执行PEIM,
# PEI 入口函数
- 系统当前的状态,判断
系统健康状况 - 可启用
固件的地址和大小 - 临时
RAM区域的地址和大小 栈的地址和大小
# PEI 执行流程
在
PEI阶段,PEIM,PPI,HOM组成了 PEI 阶段,PEI 阶段的module可理解为Driver就是PEIM,PEI阶段就是由一个一个的 PEIM 组成的;PPI是PEIM之间相互调用的接口,由唯一的GUID(全局统一标识符) 引导,内部也包含一些接口,HOB 相当于信件在 PEI 阶段创建,会记录当前系统的信息,可以自定义HOB,然后在DXE阶段读出
PEIM:PEI Module,会被编译成efi binary在一套的
BIOS code编译完之后,进入到build目录就可以找到PEIM具体的efi
PPIs:PEIM-to-PEIM Interfaces,PEIMs 被调用通过PPI,Interface。调用函数必须通过 PPI 接口
- PPI 名称:
GUID(128-bits)PPIs结构体,PPI 就是一个结构体,可能包含的功能,数据。- PEIM 会把 PPI 注册到
PEI Foundation。 (PEI Foundation管理着庞大的PPI数据库)
Core Services包含后面 phase 用到的各种 Services。在 PEI 阶段 get 当前计算机启动的 boot Mode 有直接定义的 PEI Service 函数,在 DXE 以及后面的阶段要通过 HOB 方式通过get HOB LIST 然后拆解信息进行ge启动boot ModeCore Dispatcher负责派发个PEIMs, 将PEIM按照既定的顺序Load并执行,Dependency顺序,就是inf文件里面的depx, 满足条件可执行- 各
PEIM Entry可能使用其它PEIM和PPI PEI Core最后会找到DXE获得之前phase Data是从 HOB 里拿到,PEI Core 会创建 HOB,PEI 和 DXE 都可以使用HOB的Data
函数:
InstallPPI安装 PPI 到PEI foundation,Protocol install安装完毕后放到Handle Database里LocatePPI():根据 PPI 名称GUID从PEI foundation找InterfaceNotifyPPI(): PPI 里的function不会在派发时就执行,通知系统此 PPI 会在某个 PPI 被安装时才执行
# Install PPI
/** | |
Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi. | |
这是个 service,PEI foundation 提供的。 通过 GUID 安装。目的是让别人调用。 | |
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. | |
标准格式,入口第一人参数是铁定的 EFI_PEI_SERVICES 指针 | |
@param PpiList Pointer to PPI array that want to be installed. | |
第二个参数是 PPI List, LIST 里包括 Flag、GUID 和函数 参考.h 里的 EFI_PEI_PPI_DESCRIPTOR 定义 | |
@retval EFI_SUCCESS if all PPIs in PpiList are successfully installed. | |
@retval EFI_INVALID_PARAMETER if PpiList is NULL pointer | |
if any PPI in PpiList is not valid | |
@retval EFI_OUT_OF_RESOURCES if there is no more memory resource to install PPI | |
**/ | |
EFI_STATUS | |
EFIAPI | |
PeiInstallPpi ( | |
IN CONST EFI_PEI_SERVICES **PeiServices, | |
IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList | |
); |
# HOB
HOB(
Hand-Off Blocks):传输信息的载体,PEI和DXE联系薄弱,DXE需要知到PEI初始化的硬件内存等数据,HOB作为桥梁。
HOB实际就是一个链表,当我们找到 hoblist 的头,那么整个链表的数据都能得到,GetHobList()获取hoblist的指针,
- 第
一个HOB总是PHIT==Phase Handoff GetHobList(),里面是boot mode- 其它
HOB可能出现在List任意位置,最重要的是System Memory HOB & Firmware Volumes,HOB列表总是会以END_OF_HOB_LIST结束
# 添加新的 HOB
/** | |
Add a new HOB to the HOB List. | |
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. | |
@param Type Type of the new HOB. | |
@param Length Length of the new HOB to allocate. | |
@param Hob Pointer to the new HOB. | |
@return EFI_SUCCESS Success to create HOB. | |
@retval EFI_INVALID_PARAMETER if Hob is NULL | |
@retval EFI_NOT_AVAILABLE_YET if HobList is still not available. | |
@retval EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
PeiCreateHob ( | |
IN CONST EFI_PEI_SERVICES **PeiServices, | |
IN UINT16 Type, // 对于自定义的 HOB 一般使用 EFI_HOB_GUID_TYPE | |
IN UINT16 Length, | |
IN OUT VOID **Hob | |
); |
# DXE 阶段
Driver Execution Environment驱动执行环境,主要任务是把基本驱动程序加载起来,建立两者之间的联系。执行
大部分系统初始化的工作,此阶段内存已经完全被初始化,
DXE内核:复杂 DEX 基础服务和执行流程DXE派遣器:负责调度执行EXE驱动,初始化系统设备
typedef EFI_STATUS(EFIAPI *EFI_IMAGE_ENTRY_POINT) | |
( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) |
驱动之间通过Protocol进行通信。
Protocol特殊结构体保存着对应的GUID,利用系统BootServices的OpenProtocol,并根据GUID打开对应的Protocol,进而使用对应的服务。当所有的driver执行完毕,系统完成初始化,
# DXE Core
DxeMain()是 DXE 阶段执行的主函数,同时以参数形式接受 PEI 阶段的HOB表
- 创建
EFI System Table在随后的DXE Driver 中逐步完善 table- 生成
Boot Services / Run Time Services / DXE Services- 调用
Dispatcher,所有的DXE Driver在这个函数中被检测并执行Driver执行完毕之后,执行特殊的DXE Driver进而进入 BDS 阶段
# DXE Dispatcher
- 去
BIOS芯片中搜寻DXE Driver- 检测并按照相应的顺序执行所有的
DXE Driver, 在每个driver的inf文件的driver依赖条件都成立时,该 driver 才被执行
# BDS 阶段
全程:
Boot Device SelectU 盘就是寻找具有
FAT32分区的设备执行启动策略 BDS 三大任务:
console初始化,Driver初始化,BootDeviceSelect:用户选择BDS加载启动选项里的OS loader,最后移交真正的控制权给OS loader,由 OS Loader 将
- 初始化控制台设备:查看系统有
多少加载必要的设备驱动:启动所有检测到的设备,加载driver- 根据系统设置加载和执行启动项 (若加载失败,系统将重新执行
DXE dispatcher以加载更多的驱动,然后重新尝试加载启动项)
# BDS Steps
- 初始化
语言和字符串数据库 - 获得
当前启动模式 - 基于
启动模式建立设备清单 - 连接
设备 - 检测
input output设备 - 执行
内存测试 - 进程
引导选项
# TSL 阶段
Transient System Load: 操作系统OS Loader执行的第一阶段,首先作为UEFI程序运行,之后 TSL 退出,系统进入Run Time阶段。OS loader 的主战场,TSL 是正式操作系统加载前的预备阶段,需要 Loader 找到并加载 OS
# RT 阶段
Run Time: 系统控制权从UEFI内核转交到OS Loader手中,UEFI 资源回收到 OS Loader。在 OS Loader 中 OS 获取系统控制权。
# AL 阶段
After Life如果系统 / 软件遇到灾难性错误,系统固件需要提供错误处理和灾难性恢复机制,此机制运行在AL(After Life) 阶段。由
常驻UEFI驱动组成,计算机关机休眠睡眠重启过程中的系统信息都会在这一阶段保存。
# 源码部分基础
# 源码类型定义
typedef unsigned __int64 UINT64; | |
typedef __int64 INT64; | |
typedef unsigned __int32 UINT32; | |
typedef __int32 INT32; | |
typedef unsigned short UINT16; | |
typedef unsigned short CHAR16; | |
typedef short INT16; | |
typedef unsigned char BOOLEAN; | |
typedef unsigned char UINT8; | |
typedef char CHAR8; | |
typedef signed char INT8; |
# 一些硬件补充
# Hardware Monitor
读出所有计算进访问
传感器的测试值
- 不同地点的
temperature读数CPU and system temperature智能风扇控制:风扇转速侦测和风扇控制输出电压监控
# 分时复用
是采用
一物理链接的不同时段来传输不同的信号,能达到多路复用的目的。通过事件上交叉发送每一路信号的一部分来实现一条电路传送多路信号。将整个传输时间分割为
互不重叠的时间间隔,又称为时隙
- 同步分时复用(
STDM,Synchronous Time Division Multiplexing):采用固定间隙分配方式,即将传输信号按特定长度连续地划分特定的时间段或者一个周期- 异步分时复用(ATDM,
Asynchronous Time Division Multiplexing):根据用户市级需要动态分配资源的分时复用记数。
# PCI
- 局部总线:局部总线是在
ISA和CPU总线之间添加一级总线或管理层。这样可将一些高速外设如图形卡,硬件控制器等从 ISA 总线上卸下而通过局部总线直接挂接在 CPU 总线上,使之余高速能与 CPU 总线相匹配。- PCI (Peripheral Component Interconnect) :
Intel 1991年推出的用于定义局部总线的标准。PCI不同于 ISA 总线,PCI 数据地址总线于数据总线是分时复用。以方便可以节省接插件的管脚数,另一方便便于实现数据传输。
# USB
USB总线提供中低速率外围设备的扩充能力,像键盘,鼠标,遥感,喇叭,麦克风等设备,只要是 USB 接口设计,就可以以热拔插(Hot Plug) 的方式,直接跟计算机连接或拆除 (离线),计算机与OS会自动检测并启用 / 禁用该设备,达到真正的即插即用。新近的
BIOS直接提供了USB设备驱动与读写功能,比如开始就可以使用USB键盘,鼠标以及USB软盘,硬盘甚至USB CD-ROM来开机。
# ACPI
高级配置和电源管理接口:
Advance Configuration and Power Management Interface. 早先 ACPI 将电源管理几乎全部分配给了BIOS控制,限制了操作系统在控制电脑。系统可能进入极地功耗消耗状态,这些就是可利用多数桌面型电脑上睡眠和休眠设置节电方式:
- 显示屏
自动断电- 系统把当前信息存储在
内存中,只有内存等几个关键部件通电,即挂起到内存挂起到硬盘,计算机自动关机,关机千将当前数据存储在硬盘上。
# 中断向量表
中断向量表在内存中保存,其中放着256个中断源所对应的中断处理程序入口
# 英语
Keyboard Power On: 键盘开机Wake on LAN: 网卡遥控开机- 调制解调器 / 传真机来电开机(
Modem Ring On) - CPU 过热防护:
CPU Overheat Protection - 超频功能:
Overclocking
# 参考资料
- 什么是 BMC
- gxh1992 博客
- 《UEFI 原理与编程》
- PEI 阶段扩展
- DXE
- 图表化呈现
