uefi-master\IntelFrameworkModulePkg\Universal\Acpi\AcpiSupportDxe
从inf文件可以看出这是一个DXE_DRIVER,其入口函数是InstallAcpiSupport
[Defines]
MODULE_TYPE = DXE_DRIVER
ENTRY_POINT = InstallAcpiSupport
在InstallAcpiSupport 中使用AllocateZeroPool 申请memory
然后调用AcpiSupportAcpiSupportConstructor初始化ACPI表,最终调用
Status = gBS->InstallMultipleProtocolInterfaces (
&mHandle,
&gEfiAcpiTableProtocolGuid,
&PrivateData->AcpiTableProtocol,
NULL
);
来注册gEfiAcpiTableProtocolGuid。
这样在后续中就可以通过
//
// Get AcpiTable Protocol.
//
Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
来找到gEfiAcpiTableProtocolGuid的interface,然后就可以使用gEfiAcpiTableProtocolGuid提供的函数了。
Status = AcpiTableProtocol->InstallAcpiTable (
AcpiTableProtocol,
&mFirmwarePerformanceTableTemplate,
mFirmwarePerformanceTableTemplate.Header.Length,
&mFirmwarePerformanceTableTemplateKey
);
我们来看看gEfiAcpiTableProtocolGuid提供了哪些函数。
EFI_STATUS
AcpiSupportAcpiSupportConstructor (
IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance
)
{
InitializeListHead (&AcpiSupportInstance->TableList);
AcpiSupportInstance->CurrentHandle = 1;
AcpiSupportInstance->AcpiSupport.GetAcpiTable = GetAcpiTable;
AcpiSupportInstance->AcpiSupport.SetAcpiTable = SetAcpiTable;
AcpiSupportInstance->AcpiSupport.PublishTables = PublishTables;
AcpiSupportInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable;
AcpiSupportInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
}
通过trace AcpiSupportAcpiSupportConstructor,就可以知道gEfiAcpiTableProtocolGuid提供了哪些函数。
在AcpiSupportAcpiSupportConstructor 中还会申请RSDP的memory,并将AcpiSupportInstance->Rsdp1
指向申请的Pointer。从下面的code中可以看出同时支持ACPI_1/ACPI_3
//
// Create RSDP table
//
RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
PageAddress = 0xFFFFFFFF;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIReclaimMemory,
EFI_SIZE_TO_PAGES (RsdpTableSize),
&PageAddress
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
Pointer = (UINT8 *) (UINTN) PageAddress;
ZeroMem (Pointer, RsdpTableSize);
AcpiSupportInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
AcpiSupportInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
还support Rsdt1/Rsdt3/Rsdp1/Rsdp3等子表。
最后会调用
EFI_STATUS
ChecksumCommonTables (
IN OUT EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance
)
{
//
// RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure
//
AcpiPlatformChecksum (
AcpiSupportInstance->Rsdp1,
sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
Checksum)
);
}
来为每张子表计算checksum,这样如果怀疑uefi传递给kernel的acpi表有误,可以通过计算checksum的方式确定
从inf文件可以看出这是一个DXE_DRIVER,其入口函数是InstallAcpiSupport
[Defines]
MODULE_TYPE = DXE_DRIVER
ENTRY_POINT = InstallAcpiSupport
在InstallAcpiSupport 中使用AllocateZeroPool 申请memory
然后调用AcpiSupportAcpiSupportConstructor初始化ACPI表,最终调用
Status = gBS->InstallMultipleProtocolInterfaces (
&mHandle,
&gEfiAcpiTableProtocolGuid,
&PrivateData->AcpiTableProtocol,
NULL
);
来注册gEfiAcpiTableProtocolGuid。
这样在后续中就可以通过
//
// Get AcpiTable Protocol.
//
Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
if (EFI_ERROR (Status)) {
return Status;
}
来找到gEfiAcpiTableProtocolGuid的interface,然后就可以使用gEfiAcpiTableProtocolGuid提供的函数了。
Status = AcpiTableProtocol->InstallAcpiTable (
AcpiTableProtocol,
&mFirmwarePerformanceTableTemplate,
mFirmwarePerformanceTableTemplate.Header.Length,
&mFirmwarePerformanceTableTemplateKey
);
我们来看看gEfiAcpiTableProtocolGuid提供了哪些函数。
EFI_STATUS
AcpiSupportAcpiSupportConstructor (
IN EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance
)
{
InitializeListHead (&AcpiSupportInstance->TableList);
AcpiSupportInstance->CurrentHandle = 1;
AcpiSupportInstance->AcpiSupport.GetAcpiTable = GetAcpiTable;
AcpiSupportInstance->AcpiSupport.SetAcpiTable = SetAcpiTable;
AcpiSupportInstance->AcpiSupport.PublishTables = PublishTables;
AcpiSupportInstance->AcpiTableProtocol.InstallAcpiTable = InstallAcpiTable;
AcpiSupportInstance->AcpiTableProtocol.UninstallAcpiTable = UninstallAcpiTable;
}
通过trace AcpiSupportAcpiSupportConstructor,就可以知道gEfiAcpiTableProtocolGuid提供了哪些函数。
在AcpiSupportAcpiSupportConstructor 中还会申请RSDP的memory,并将AcpiSupportInstance->Rsdp1
指向申请的Pointer。从下面的code中可以看出同时支持ACPI_1/ACPI_3
//
// Create RSDP table
//
RsdpTableSize = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) +
sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
PageAddress = 0xFFFFFFFF;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIReclaimMemory,
EFI_SIZE_TO_PAGES (RsdpTableSize),
&PageAddress
);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
Pointer = (UINT8 *) (UINTN) PageAddress;
ZeroMem (Pointer, RsdpTableSize);
AcpiSupportInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
Pointer += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
AcpiSupportInstance->Rsdp3 = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
还support Rsdt1/Rsdt3/Rsdp1/Rsdp3等子表。
最后会调用
EFI_STATUS
ChecksumCommonTables (
IN OUT EFI_ACPI_SUPPORT_INSTANCE *AcpiSupportInstance
)
{
//
// RSDP ACPI 1.0 checksum for 1.0 table. This is only the first 20 bytes of the structure
//
AcpiPlatformChecksum (
AcpiSupportInstance->Rsdp1,
sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
OFFSET_OF (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER,
Checksum)
);
}
来为每张子表计算checksum,这样如果怀疑uefi传递给kernel的acpi表有误,可以通过计算checksum的方式确定