一、概述
在 UEFI 系统表中,有几个关键的表用于提供系统信息、服务和硬件抽象。这些表可以通过 EFI_SYSTEM_TABLE 访问,常见的 UEFI 系统表如下:
1、EFI_SYSTEM_TABLE (系统表)
EFI_SYSTEM_TABLE 是一个指针,包含多个服务和系统信息。
包含以下几个重要表:
2、EFI_BOOT_SERVICES (引导服务表):
提供在引导期间可用的功能(如内存分配、事件管理、协议处理等)。
3、EFI_RUNTIME_SERVICES (运行时服务表):
提供操作系统加载后仍可使用的服务(如变量管理、时间功能和固件更新等)。
4、EFI_CONFIGURATION_TABLE (配置表):
包含各种硬件信息和平台信息,包含 ACPI、SMBIOS、HOB(Hand-off Block)等表。
二、遍历ACPI表
VOID ListAllAcpiTables(VOID)
{
UINTN i, j, EntryCount;
CHAR8 strBuff[20];
UINT64 *EntryPtr;
EFI_GUID AcpiTableGuid = ACPI_TABLE_GUID;
EFI_GUID Acpi2TableGuid = EFI_ACPI_TABLE_GUID;
EFI_CONFIGURATION_TABLE *configTab = NULL;
EFI_ACPI_DESCRIPTION_HEADER *XSDT, *Entry;
EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Root;
Print(L"List All ACPI Tables:\n");
configTab = gST->ConfigurationTable;
for (i = 0; i < gST->NumberOfTableEntries; i++) {
// Step1: 查找 ACPI 表
if ((CompareGuid(&configTab->VendorGuid, &AcpiTableGuid) == 0) ||
(CompareGuid(&configTab->VendorGuid, &Acpi2TableGuid) == 0)) {
Print(L"Found ACPI table: %g\n", &configTab->VendorGuid);
Root = configTab->VendorTable;
Print(L"ROOT SYSTEM DESCRIPTION @[0x%p]\n", Root);
// Step2: 检查修订版本(只接受修订版本 >= 2)
if (Root->Revision >= EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
// Step3: 获取 XSDT 表地址
XSDT = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Root->XsdtAddress;
EntryCount = (XSDT->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);
Print(L"XSDT address = [0x%p]\n", XSDT);
Print(L"XSDT-Length = 0x%x\n", XSDT->Length);
Print(L"Number of ACPI Tables = %d\n", EntryCount);
// Step4: 遍历每个 ACPI 表并输出信息
EntryPtr = (UINT64 *)(XSDT + 1);
for (j = 0; j < EntryCount; j++, EntryPtr++) {
Entry = (EFI_ACPI_DESCRIPTION_HEADER *)((UINTN)(*EntryPtr));
// 输出每个表的签名、长度和校验和等基本信息
ZeroMem(strBuff, sizeof(strBuff));
CopyMem(strBuff, &(Entry->Signature), sizeof(UINT32));
Print(L"Table Signature: %a\n", strBuff);
Print(L"Table Address: 0x%p\n", Entry);
Print(L"Table Length: 0x%x\n", Entry->Length);
Print(L"Table Checksum: 0x%x\n", Entry->Checksum);
}
}
}
configTab++;
}
}
整个函数 ListAllAcpiTables 的逻辑是:
1)遍历系统配置表。
2) 查找 ACPI 表,并验证 RSDP 的版本。
3) 从 RSDP 获取 XSDT 表的地址,并计算其中的 ACPI 表数量。
4) 遍历所有 ACPI 表,打印它们的基本信息