本文共 5539 字,大约阅读时间需要 18 分钟。
UEFI(Unified Extensible Firmware Interface,通用可扩展固件接口)是现代计算机系统中核心的固件接口规范。其架构中最为关键且复杂的部分便是系统表(System Table)。本文将深入探讨UEFI系统表的相关内容,包括其构建过程、 Boot Service Table 和 Runtime Service Table 的功能划分,以及如何利用这些服务表开发与UEFI兼容的系统程序。
系统表(System Table)是UEFI固件的构建基石,里面包含了运行时服务表、设备控制表、 Guthiิศ ซ. 等多个重要接口和数据结构。系统表的主要内容包括:
QE128值,用于验证系统表的完整性,确保它是可信的UEFI系统表。
QE16值,表示系统表的版本。
QE32值,表示系统表的头部大小。
QE32值,用来校验系统表的完整性。
QE32值,用于系统表的VESA(视频电子记忆排序)等轻量级引导程 SHOWDEVICES 接口。
指向一个设备地址,存储了当前固件的供应商ID和相关信息。
QE16值,表示固件的版本信息。
指向与控制台相关的输入接口。
指向与控制台相关的输出接口。
指向与标准错误设备相关的输入接口。
这是系统表中最重要的字段之一。这个指针指向了UEFI运行时服务表,里面包含了大量常用固件接口,如 Start
、ExitBootServices
等。
QE32值,表示系统表中包含的其他配置表的数量。
这是一个可选字段,可用于存储系统某些特定固件实现的补充信息。
通过以上结构可以看出,系统表的核心作用是作为固件编程的入口,程序通过它来访问系统所需的各种服务和资源。
系统表的创建过程是UEFI启动阶段(DXE,Differentiated Execution Environment)中的关键步骤。系统表需要在固件运行的早期阶段初始化,以供后续 drivers 和程序使用。
以下是DXE主调度(DxeMain.c)中一个简单的系统表初始化代码段:
// DXE主调度(DxeMain.c)中创建系统表的代码示例EFI_SYSTEM_TABLE mEfiSystemTableTemplate = { { EFI_SYSTEM_TABLE_SIGNATURE, // 签名 EFI_SYSTEM_TABLE_REVISION, // 修订编号 sizeof(EFI_SYSTEM_TABLE), // 头部大小 0, // CRC32值 0 // 保留值 }, NULL, // 固件供应商标识 0, // 固件修订编号 NULL, // 控制输入设备的磁引环 NULL, // 控制输出设备的输入流 NULL, // 标准错误设备的输入流 NULL, // 运行时服务表指针 &mBootServices, // Boot服务表指针 0, // 配置表条目数 NULL // 配置表指针};
在实际实现中,系统表需要通过 AllocateRuntimeCopyPool
函数分配内存,并进行数据初始化。完成后的系统表会被 DXE 核心用于后续服务的建立与运行。
Boot Service Table 是系统表中最基本的服务表类型之一,里面包含了UEFI启动过程中常用的接口和函数。这些服务包括事件管理、内存管理、协议安装等。以下是 Boot Service Table 中的主要函数分类:
CreateEvent
CreateEventEx
CloseEvent
SignalEvent
WaitForEvent
CheckEvent
SetTimer
RaiseTPL
RestoreTPL
这些函数为系统在启动过程中提供了事件管理的能力,常用于启动进程调度、任务优先级控制等场景。
AllocatePages
FreePages
GetMemoryMap
AllocatePool
FreePool
这些函数为系统提供了内存管理的基本接口,可以用来分配和释放物理内存或虚拟内存。
InstallProtocolInterface
UninstallProtocolInterface
ReinstallProtocolInterface
RegisterProtocolNotify
LocateHandle
HandleProtocol
LocateDevicePath
OpenProtocol
CloseProtocol
OpenProtocolInformation
ConnectController
DisconnectController
这些函数让系统能够管理设备协议,安装和删除协议接口,定位支持特定协议的设备。
LoadImage
StartImage
UnloadImage
EFI_IMAGE_ENTRY_POINT
Exit
ExitBootServices
这些函数控制着图像的加载与运行,确保固件能够正确执行各个阶段的程序。
SetWatchDogTimer
Stall
CopyMem
SetMem
GetNextMonotonicCount
InstallConfigurationTable
CalculateCrc32
这些函数提供了一系列通用接口,可用于时间管理、调度控制、数据校验等。
与 Boot Service Table 不同, Runtime Service Table 在启动完成后进入运行时阶段仍然有效。它提供了一系列用于操作系统级别的服务接口,如变量管理、时间控制、虚拟内存管理等。
GetVariable
GetNextVariableName
SetVariable
QueryVariableInfo
这些函数用于管理和访问系统中定义的 EFI 变量,常用于存储和运行时配置信息。
GetTime
SetTime
GetWakeupTime
SetWakeupTime
这些函数用于管理系统时间和唤醒时间,确保系统能够正确进行时间更新和恢复。
SetVirtualAddressMap
ConvertPointer
这些函数用于转换物理地址和虚拟地址,便于操作系统在虚拟化环境中使用物理内存。
GetNextHighMonotonicCount
ResetSystem
UpdateCapsule
QueryCapsuleCapabilities
这些函数提供了平台运行时的高级功能,如重置系统、管理加密硬件等。
UEFI运行时所依赖的核心协议也需要在系统表中进行注册和初始化。这些协议包括:
EFI_CORE_PROTOCOL_NOTIFY_ENTRY{ gEfiSecurityArchProtocolGuid, // 安全架构协议 gCpuArchProtocolGuid, // CPU 架构协议 gMetronomeArchProtocolGuid, // 时钟架构协议 gTimerArchProtocolGuid, // 定时器架构协议 gBdsArchProtocolGuid, // 启动设备架构协议 gWatchdogTimerArchProtocolGuid, // 软件车子架构协议 gRuntimeArchProtocolGuid, // 运行时架构协议 gVariableArchProtocolGuid, // 变量架构协议 gVariableWriteArchProtocolGuid, // 变量写入架构协议 gCapsuleArchProtocolGuid, // 系统补丁架构协议 gMonotonicCounterArchProtocolGuid, // 单调计数器架构协议 gResetArchProtocolGuid, // 重置架构协议 gRealTimeClockArchProtocolGuid, // 实时钟架构协议 NULL
这些协议的安装顺序非常关键,通常要求遵循一定的优先级顺序进行安装,以确保系统的稳定性和一致性。
系统表和运行时服务表中的具体接口在 EFIST(EFI引导体)运行的不同阶段会逐步被初始化。例如,以下是 RealTimeClock
模块中初始化时间服务的代码片段:
EFI_STATUSInitializeRealTimeClock( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_STATUS Status; Status = LibRtcInitialize(ImageHandle, SystemTable); if (Status != EFI_SUCCESS) { return Status; } // 初始化时间相关的运行时服务接口 SystemTable->RuntimeServices->GetTime = GetTime; SystemTable->RuntimeServices->SetTime = SetTime; SystemTable->RuntimeServices->GetWakeupTime = GetWakeupTime; SystemTable->RuntimeServices->SetWakeupTime = SetWakeupTime; // 注册多个协议接口 Status = gBS->InstallMultipleProtocolInterfaces( &mHandle, gEfiRealTimeClockArchProtocolGuid, NULL, NULL ); return Status;}
这个代码段展示了如何将实时钟功能初始化到系统表中,并确保时间服务能够正确运行。类似的步骤会在各个模块中按照自己的需求进行。
通过以上详细的解读,我们可以清楚地看到,系统表和相关服务表在UEFI系统中的核心作用。理解和使用这些表在开发 UE speaker 的固件drv或其他 UE-Compatible 系统程序中至关重要。随着 UEInstaller 和其它工具的不断成熟,随着对 UE_ARCH_PROTOCOL 的深入理解,开发 UE-Compatible 系统将变得越来越高效和自动化。
在实际开发中,建议对上述的每个接口和协议进行深入理解,利用相关工具和调试方法进行验证,以确保系统的稳定性和兼容性。
转载地址:http://ryodz.baihongyu.com/