mirror of https://github.com/acidanthera/audk.git
DynamicTablesPkg: Adds ACPI SSDT HPET table generator
Adds X64 ACPI SSDT HPET table generator library. Updates acpi standard table enum with hpet. Generate ACPI HPET device as per specification. Cc: Sami Mujawar <Sami.Mujawar@arm.com> Cc: Pierre Gondois <pierre.gondois@arm.com> Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
This commit is contained in:
parent
fada1cea46
commit
5901f19a87
|
@ -57,6 +57,7 @@
|
|||
#
|
||||
DynamicTablesPkg/Library/Acpi/X64/AcpiWsmtLib/AcpiWsmtLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
|
||||
DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
|
||||
|
||||
#
|
||||
# Dynamic Table Factory Dxe
|
||||
|
@ -68,6 +69,7 @@
|
|||
NULL|DynamicTablesPkg/Library/Acpi/Common/AcpiFadtLib/AcpiFadtLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiWsmtLib/AcpiWsmtLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiHpetLib/AcpiHpetLib.inf
|
||||
NULL|DynamicTablesPkg/Library/Acpi/X64/AcpiSsdtHpetLib/AcpiSsdtHpetLib.inf
|
||||
}
|
||||
|
||||
[Components.ARM, Components.AARCH64]
|
||||
|
|
|
@ -106,6 +106,7 @@ typedef enum StdAcpiTableId {
|
|||
EStdAcpiTableIdTpm2, ///< TPM2 Generator
|
||||
EStdAcpiTableIdWsmt, ///< WSMT Generator
|
||||
EStdAcpiTableIdHpet, ///< HPET Generator
|
||||
EStdAcpiTableIdSsdtHpet, ///< SSDT HPET Generator
|
||||
EStdAcpiTableIdMax
|
||||
} ESTD_ACPI_TABLE_ID;
|
||||
|
||||
|
|
|
@ -0,0 +1,428 @@
|
|||
/** @file
|
||||
|
||||
Generate ACPI HPET table for AMD platforms.
|
||||
|
||||
Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier BSD-2-Clause-Patent
|
||||
**/
|
||||
|
||||
#include <IndustryStandard/HighPrecisionEventTimerTable.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Protocol/AcpiTable.h>
|
||||
|
||||
// Module specific include files.
|
||||
#include <AcpiTableGenerator.h>
|
||||
#include <ConfigurationManagerObject.h>
|
||||
#include <ConfigurationManagerHelper.h>
|
||||
#include <Library/AcpiHelperLib.h>
|
||||
#include <Library/TableHelperLib.h>
|
||||
#include <Library/AmlLib/AmlLib.h>
|
||||
#include <Protocol/ConfigurationManagerProtocol.h>
|
||||
#include <Library/IoLib.h>
|
||||
|
||||
/** This macro defines supported HPET page protection flags
|
||||
*/
|
||||
#define HPET_VALID_PAGE_PROTECTION \
|
||||
(EFI_ACPI_NO_PAGE_PROTECTION | \
|
||||
EFI_ACPI_4KB_PAGE_PROTECTION | \
|
||||
EFI_ACPI_64KB_PAGE_PROTECTION)
|
||||
|
||||
/** This macro expands to a function that retrieves the
|
||||
HPET device information from the Configuration Manager.
|
||||
*/
|
||||
GET_OBJECT_LIST (
|
||||
EObjNameSpaceX64,
|
||||
EX64ObjHpetInfo,
|
||||
CM_X64_HPET_INFO
|
||||
);
|
||||
|
||||
/** Update HPET table information.
|
||||
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol Interface.
|
||||
@param [in, out] ScopeNode The Scope Node for the HPET table.
|
||||
|
||||
@retval EFI_SUCCESS Success.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_NOT_FOUND The required object was not found or
|
||||
the HPET is not enabled.
|
||||
@retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
|
||||
Manager is less than the Object size for the
|
||||
requested object.
|
||||
@retval EFI_UNSUPPORTED If invalid protection and oem flags provided.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SsdtHpetUpdateTableInfo (
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
IN OUT AML_OBJECT_NODE_HANDLE ScopeNode
|
||||
)
|
||||
{
|
||||
CM_X64_HPET_INFO *HpetInfo;
|
||||
EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_BLOCK_ID HpetBlockId;
|
||||
EFI_STATUS Status;
|
||||
AML_OBJECT_NODE_HANDLE CrsNode;
|
||||
AML_OBJECT_NODE_HANDLE HpetNode;
|
||||
UINT32 EisaId;
|
||||
|
||||
ASSERT (CfgMgrProtocol != NULL);
|
||||
|
||||
// Get the HPET information from the Platform Configuration Manager
|
||||
Status = GetEX64ObjHpetInfo (
|
||||
CfgMgrProtocol,
|
||||
CM_NULL_TOKEN,
|
||||
&HpetInfo,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: HPET: Failed to get HPET information." \
|
||||
" Status = %r\n",
|
||||
Status
|
||||
));
|
||||
return Status;
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"HPET: Device base address = 0x%x\n"
|
||||
" : Minimum clock tick in periodic mode = 0x%x\n"
|
||||
" : Page protection and Oem flags = 0x%x\n",
|
||||
HpetInfo->BaseAddressLower32Bit,
|
||||
HpetInfo->MainCounterMinimumClockTickInPeriodicMode,
|
||||
HpetInfo->PageProtectionAndOemAttribute
|
||||
));
|
||||
|
||||
// Validate the page protection flags bit0 to bit3
|
||||
if (((HpetInfo->PageProtectionAndOemAttribute & 0xF) & ~HPET_VALID_PAGE_PROTECTION) != 0) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: HPET: unsupported page protection flags = 0x%x\n",
|
||||
HpetInfo->PageProtectionAndOemAttribute
|
||||
));
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// Get HPET Capabilities ID register value and test if HPET is enabled
|
||||
HpetBlockId.Uint32 = MmioRead32 (HpetInfo->BaseAddressLower32Bit);
|
||||
|
||||
// If mmio address is not mapped
|
||||
if ((HpetBlockId.Uint32 == MAX_UINT32) || (HpetBlockId.Uint32 == 0)) {
|
||||
DEBUG ((DEBUG_ERROR, "HPET Capabilities register read failed.\n"));
|
||||
ASSERT_EFI_ERROR (EFI_NOT_FOUND);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Validate Reserved and Revision ID
|
||||
if (HpetBlockId.Bits.Reserved != 0) {
|
||||
DEBUG ((DEBUG_ERROR, "HPET Reserved bit is set.\n"));
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (HpetBlockId.Bits.Revision == 0) {
|
||||
DEBUG ((DEBUG_ERROR, "HPET Revision is not set.\n"));
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = AmlCodeGenDevice ("HPET", ScopeNode, &HpetNode);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = AmlGetEisaIdFromString ("PNP0103", &EisaId);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = AmlCodeGenNameInteger ("_HID", EisaId, HpetNode, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = AmlCodeGenNameInteger ("_UID", 0x00, HpetNode, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = AmlCodeGenNameResourceTemplate ("_CRS", HpetNode, &CrsNode);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = AmlCodeGenRdMemory32Fixed (
|
||||
FALSE,
|
||||
HpetInfo->BaseAddressLower32Bit,
|
||||
SIZE_1KB,
|
||||
CrsNode,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((HpetInfo->PageProtectionAndOemAttribute & 0xF) != 0) {
|
||||
Status = AmlCodeGenNameInteger (
|
||||
"PAGE",
|
||||
(HpetInfo->PageProtectionAndOemAttribute & 0xF),
|
||||
HpetNode,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if ((HpetInfo->PageProtectionAndOemAttribute >> 4) != 0) {
|
||||
Status = AmlCodeGenNameInteger (
|
||||
"ATTR",
|
||||
(HpetInfo->PageProtectionAndOemAttribute >> 4),
|
||||
HpetNode,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Construct the SSDT HPET table.
|
||||
|
||||
This function invokes the Configuration Manager protocol interface
|
||||
to get the required information for generating the ACPI table.
|
||||
|
||||
If this function allocates any resources then they must be freed
|
||||
in the FreeXXXXTableResources function.
|
||||
|
||||
@param [in] This Pointer to the table generator.
|
||||
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol Interface.
|
||||
@param [out] Table Pointer to the constructed ACPI Table.
|
||||
|
||||
@retval EFI_SUCCESS Table generated successfully.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_NOT_FOUND The required object was not found.
|
||||
@retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
|
||||
Manager is less than the Object size for the
|
||||
requested object.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
BuildSsdtHpetTable (
|
||||
IN CONST ACPI_TABLE_GENERATOR *CONST This,
|
||||
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
AML_ROOT_NODE_HANDLE RootNode;
|
||||
AML_OBJECT_NODE_HANDLE ScopeNode;
|
||||
|
||||
ASSERT (This != NULL);
|
||||
ASSERT (AcpiTableInfo != NULL);
|
||||
ASSERT (CfgMgrProtocol != NULL);
|
||||
ASSERT (Table != NULL);
|
||||
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
||||
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
||||
|
||||
if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
|
||||
(AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
|
||||
{
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: HPET: Requested table revision = %d, is not supported."
|
||||
"Supported table revision: Minimum = %d, Maximum = %d\n",
|
||||
AcpiTableInfo->AcpiTableRevision,
|
||||
This->MinAcpiTableRevision,
|
||||
This->AcpiTableRevision
|
||||
));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*Table = NULL;
|
||||
|
||||
Status = AddSsdtAcpiHeader (
|
||||
CfgMgrProtocol,
|
||||
This,
|
||||
AcpiTableInfo,
|
||||
&RootNode
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = AmlCodeGenScope ("\\_SB_", RootNode, &ScopeNode);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
goto exit_handler;
|
||||
}
|
||||
|
||||
// Update HPET table info
|
||||
Status = SsdtHpetUpdateTableInfo (CfgMgrProtocol, ScopeNode);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
goto exit_handler;
|
||||
}
|
||||
|
||||
Status = AmlSerializeDefinitionBlock (
|
||||
RootNode,
|
||||
Table
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"ERROR: SSDT-HPET: Failed to Serialize SSDT Table Data."
|
||||
" Status = %r\n",
|
||||
Status
|
||||
));
|
||||
}
|
||||
|
||||
exit_handler:
|
||||
// Delete the RootNode and its attached children.
|
||||
AmlDeleteTree (RootNode);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Free any resources allocated for constructing the
|
||||
SSDT HPET ACPI table.
|
||||
|
||||
@param [in] This Pointer to the table generator.
|
||||
@param [in] AcpiTableInfo Pointer to the ACPI Table Info.
|
||||
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
|
||||
Protocol Interface.
|
||||
@param [in, out] Table Pointer to the ACPI Table.
|
||||
|
||||
@retval EFI_SUCCESS The resources were freed successfully.
|
||||
@retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FreeSsdtHpetTableResources (
|
||||
IN CONST ACPI_TABLE_GENERATOR *CONST This,
|
||||
IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
|
||||
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
|
||||
IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table
|
||||
)
|
||||
{
|
||||
ASSERT (This != NULL);
|
||||
ASSERT (AcpiTableInfo != NULL);
|
||||
ASSERT (CfgMgrProtocol != NULL);
|
||||
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
|
||||
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
|
||||
|
||||
if ((Table == NULL) || (*Table == NULL)) {
|
||||
DEBUG ((DEBUG_ERROR, "ERROR: SSDT-HPET: Invalid Table Pointer\n"));
|
||||
ASSERT ((Table != NULL) && (*Table != NULL));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
FreePool (*Table);
|
||||
*Table = NULL;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** This macro defines the HPET Table Generator revision.
|
||||
*/
|
||||
#define HPET_GENERATOR_REVISION CREATE_REVISION (1, 0)
|
||||
|
||||
/** The interface for the HPET Table Generator.
|
||||
*/
|
||||
STATIC
|
||||
CONST
|
||||
ACPI_TABLE_GENERATOR SsdtHpetGenerator = {
|
||||
// Generator ID
|
||||
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtHpet),
|
||||
// Generator Description
|
||||
L"ACPI.STD.SSDT.HPET.GENERATOR",
|
||||
// ACPI Table Signature
|
||||
EFI_ACPI_6_5_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
|
||||
// ACPI Table Revision supported by this Generator
|
||||
0,
|
||||
// Minimum supported ACPI Table Revision
|
||||
0,
|
||||
// Creator ID
|
||||
TABLE_GENERATOR_CREATOR_ID,
|
||||
// Creator Revision
|
||||
HPET_GENERATOR_REVISION,
|
||||
// Build Table function
|
||||
BuildSsdtHpetTable,
|
||||
// Free Resource function
|
||||
FreeSsdtHpetTableResources,
|
||||
// Extended build function not needed
|
||||
NULL,
|
||||
// Extended build function not implemented by the generator.
|
||||
// Hence extended free resource function is not required.
|
||||
NULL
|
||||
};
|
||||
|
||||
/** Register the Generator with the ACPI Table Factory.
|
||||
|
||||
@param [in] ImageHandle The handle to the image.
|
||||
@param [in] SystemTable Pointer to the System Table.
|
||||
|
||||
@retval EFI_SUCCESS The Generator is registered.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_ALREADY_STARTED The Generator for the Table ID
|
||||
is already registered.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AcpiSsdtHpetLibConstructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = RegisterAcpiTableGenerator (&SsdtHpetGenerator);
|
||||
DEBUG ((DEBUG_INFO, "HPET: Register Generator. Status = %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Deregister the Generator from the ACPI Table Factory.
|
||||
|
||||
@param [in] ImageHandle The handle to the image.
|
||||
@param [in] SystemTable Pointer to the System Table.
|
||||
|
||||
@retval EFI_SUCCESS The Generator is deregistered.
|
||||
@retval EFI_INVALID_PARAMETER A parameter is invalid.
|
||||
@retval EFI_NOT_FOUND The Generator is not registered.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AcpiSsdtHpetLibDestructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = DeregisterAcpiTableGenerator (&SsdtHpetGenerator);
|
||||
DEBUG ((DEBUG_INFO, "HPET: Deregister Generator. Status = %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
## @file
|
||||
# Creates ACPI SSDT HPET device for AMD platforms.
|
||||
#
|
||||
# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 1.30
|
||||
BASE_NAME = AcpiSsdtHpetLib
|
||||
FILE_GUID = CEC214FF-A9F1-4C3F-B084-BC8AFBEE7EA2
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = NULL|DXE_DRIVER
|
||||
CONSTRUCTOR = AcpiSsdtHpetLibConstructor
|
||||
DESTRUCTOR = AcpiSsdtHpetLibDestructor
|
||||
|
||||
[Sources]
|
||||
AcpiSsdtHpetLib.c
|
||||
|
||||
[Packages]
|
||||
DynamicTablesPkg/DynamicTablesPkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DebugLib
|
||||
IoLib
|
Loading…
Reference in New Issue