/** @file | |
PCCT Table Generator | |
Copyright (c) 2022, Arm Limited. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
@par Reference(s): | |
- ACPI 6.4 Specification - January 2021 | |
s14 PLATFORM COMMUNICATIONS CHANNEL (PCC) | |
**/ | |
#include <Library/AcpiLib.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/TableHelperLib.h> | |
#include <Protocol/ConfigurationManagerProtocol.h> | |
#include "PcctGenerator.h" | |
/** ARM standard PCCT Generator | |
Requirements: | |
The following Configuration Manager Object(s) are required by | |
this Generator: | |
- EArmObjPccSubspaceType0Info | |
- EArmObjPccSubspaceType1Info | |
- EArmObjPccSubspaceType2Info | |
- EArmObjPccSubspaceType3Info | |
- EArmObjPccSubspaceType4Info | |
- EArmObjPccSubspaceType5Info | |
*/ | |
/** This macro expands to a function that retrieves the PCC | |
Subspace of Type 0 Information from the Configuration Manager. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceArm, | |
EArmObjPccSubspaceType0Info, | |
CM_ARM_PCC_SUBSPACE_TYPE0_INFO | |
); | |
/** This macro expands to a function that retrieves the PCC | |
Subspace of Type 1 Information from the Configuration Manager. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceArm, | |
EArmObjPccSubspaceType1Info, | |
CM_ARM_PCC_SUBSPACE_TYPE1_INFO | |
); | |
/** This macro expands to a function that retrieves the PCC | |
Subspace of Type 2 Information from the Configuration Manager. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceArm, | |
EArmObjPccSubspaceType2Info, | |
CM_ARM_PCC_SUBSPACE_TYPE2_INFO | |
); | |
/** This macro expands to a function that retrieves the PCC | |
Subspace of Type 3 Information from the Configuration Manager. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceArm, | |
EArmObjPccSubspaceType3Info, | |
CM_ARM_PCC_SUBSPACE_TYPE3_INFO | |
); | |
/** This macro expands to a function that retrieves the PCC | |
Subspace of Type 4 Information from the Configuration Manager. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceArm, | |
EArmObjPccSubspaceType4Info, | |
CM_ARM_PCC_SUBSPACE_TYPE4_INFO | |
); | |
/** This macro expands to a function that retrieves the PCC | |
Subspace of Type 5 Information from the Configuration Manager. | |
*/ | |
GET_OBJECT_LIST ( | |
EObjNameSpaceArm, | |
EArmObjPccSubspaceType5Info, | |
CM_ARM_PCC_SUBSPACE_TYPE5_INFO | |
); | |
/** The Platform is capable of generating an interrupt | |
to indicate completion of a command. | |
Cf: s14.1.1 Platform Communications Channel Global Flags | |
Platform Interrupt flag | |
and s14.1.6 Extended PCC subspaces (types 3 and 4) | |
If a responder subspace is included in the PCCT, | |
then the global Platform Interrupt flag must be set to 1 | |
Set this variable and populate the PCCT flag accordingly if either: | |
- One of the PCCT Subspace uses interrupts. | |
- A PCC Subspace of type 4 is used. | |
*/ | |
STATIC BOOLEAN mHasPlatformInterrupt; | |
/** Initialize the MappingTable. | |
@param [in] MappingTable The mapping table structure. | |
@param [in] Count Number of entries to allocate in the | |
MappingTable. | |
@retval EFI_SUCCESS Success. | |
@retval EFI_INVALID_PARAMETER Invalid parameter. | |
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
MappingTableInitialize ( | |
IN MAPPING_TABLE *MappingTable, | |
IN UINT32 Count | |
) | |
{ | |
VOID **Table; | |
if ((MappingTable == NULL) || | |
(Count == 0)) | |
{ | |
ASSERT (0); | |
return EFI_INVALID_PARAMETER; | |
} | |
Table = AllocateZeroPool (sizeof (*Table) * Count); | |
if (Table == NULL) { | |
ASSERT (0); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
MappingTable->Table = Table; | |
MappingTable->MaxIndex = Count; | |
return EFI_SUCCESS; | |
} | |
/** Free the MappingTable. | |
@param [in, out] MappingTable The mapping table structure. | |
**/ | |
STATIC | |
VOID | |
EFIAPI | |
MappingTableFree ( | |
IN OUT MAPPING_TABLE *MappingTable | |
) | |
{ | |
ASSERT (MappingTable != NULL); | |
ASSERT (MappingTable->Table != NULL); | |
if (MappingTable->Table != NULL) { | |
FreePool (MappingTable->Table); | |
} | |
} | |
/** Add a new entry for CmArmPccSubspace at Index. | |
@param [in] MappingTable The mapping table structure. | |
@param [in] CmArmPccSubspace Pointer to a CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO. | |
@param [in] Index Index at which CmArmPccSubspace must be added. | |
This is the Subspace Id. | |
@retval EFI_SUCCESS Success. | |
@retval EFI_BUFFER_TOO_SMALL Buffer too small. | |
@retval EFI_INVALID_PARAMETER Invalid parameter. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
MappingTableAdd ( | |
IN MAPPING_TABLE *MappingTable, | |
IN VOID *CmArmPccSubspace, | |
IN UINT32 Index | |
) | |
{ | |
if ((MappingTable == NULL) || | |
(MappingTable->Table == NULL) || | |
(CmArmPccSubspace == NULL)) | |
{ | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
if ((Index >= MappingTable->MaxIndex) || | |
(MappingTable->Table[Index] != 0)) | |
{ | |
ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); | |
return EFI_BUFFER_TOO_SMALL; | |
} | |
// Just map the Pcc Subspace in the Table. | |
MappingTable->Table[Index] = CmArmPccSubspace; | |
return EFI_SUCCESS; | |
} | |
/** Parse the CmPccArray objects and add them to the MappingTable. | |
@param [in] MappingTable The mapping table structure. | |
@param [in] CmPccArray Pointer to an array of CM_ARM_PCC_SUBSPACE_TYPE[X]_INFO. | |
@param [in] CmPccCount Count of objects in CmPccArray. | |
@retval EFI_SUCCESS Success. | |
@retval EFI_BUFFER_TOO_SMALL Buffer too small. | |
@retval EFI_INVALID_PARAMETER Invalid parameter. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
MapPccSubspaceId ( | |
IN MAPPING_TABLE *MappingTable, | |
IN VOID *CmPccArray, | |
IN UINT32 CmPccCount | |
) | |
{ | |
EFI_STATUS Status; | |
UINT8 *PccBuffer; | |
UINT32 Index; | |
UINT32 CmObjSize; | |
PCC_SUBSPACE_GENERIC_INFO *GenericPcc; | |
if (CmPccCount == 0) { | |
return EFI_SUCCESS; | |
} | |
if ((CmPccArray == NULL) || (MappingTable == NULL)) { | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)CmPccArray; | |
switch (GenericPcc->Type) { | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: | |
CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE0_INFO); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: | |
CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE1_INFO); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: | |
CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE2_INFO); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: | |
CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE3_INFO); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: | |
CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE4_INFO); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: | |
CmObjSize = sizeof (CM_ARM_PCC_SUBSPACE_TYPE5_INFO); | |
break; | |
default: | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
PccBuffer = (UINT8 *)CmPccArray; | |
// Map the Pcc channel to their Subspace Id. | |
for (Index = 0; Index < CmPccCount; Index++) { | |
GenericPcc = (PCC_SUBSPACE_GENERIC_INFO *)PccBuffer; | |
Status = MappingTableAdd ( | |
MappingTable, | |
PccBuffer, | |
GenericPcc->SubspaceId | |
); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
return Status; | |
} | |
PccBuffer += CmObjSize; | |
} | |
return EFI_SUCCESS; | |
} | |
/** Add one PCCT Subspace structure of Type 0 (Generic). | |
@param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. | |
@param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. | |
@retval EFI_SUCCESS Table generated successfully. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
AddSubspaceStructType0 ( | |
IN CM_ARM_PCC_SUBSPACE_TYPE0_INFO *PccCmObj, | |
IN EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *PccAcpi | |
) | |
{ | |
PCC_MAILBOX_REGISTER_INFO *Doorbell; | |
PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; | |
if ((PccCmObj == NULL) || | |
(PccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC) || | |
(PccAcpi == NULL)) | |
{ | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
Doorbell = &PccCmObj->DoorbellReg; | |
ChannelTiming = &PccCmObj->ChannelTiming; | |
PccAcpi->Type = PccCmObj->Type; | |
PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); | |
*(UINT32 *)&PccAcpi->Reserved[0] = EFI_ACPI_RESERVED_DWORD; | |
*(UINT16 *)&PccAcpi->Reserved[4] = EFI_ACPI_RESERVED_WORD; | |
PccAcpi->BaseAddress = PccCmObj->BaseAddress; | |
PccAcpi->AddressLength = PccCmObj->AddressLength; | |
CopyMem ( | |
&PccAcpi->DoorbellRegister, | |
&Doorbell->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; | |
PccAcpi->DoorbellWrite = Doorbell->WriteMask; | |
PccAcpi->NominalLatency = ChannelTiming->NominalLatency; | |
PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; | |
PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; | |
return EFI_SUCCESS; | |
} | |
/** Add one PCCT subspace structure of Type 1 (HW-Reduced). | |
@param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. | |
@param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. | |
@retval EFI_SUCCESS Table generated successfully. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
AddSubspaceStructType1 ( | |
IN CM_ARM_PCC_SUBSPACE_TYPE1_INFO *PccCmObj, | |
IN EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *PccAcpi | |
) | |
{ | |
CM_ARM_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; | |
PCC_MAILBOX_REGISTER_INFO *Doorbell; | |
PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; | |
GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; | |
if ((PccCmObj == NULL) || | |
(GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS) || | |
(PccAcpi == NULL)) | |
{ | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
Doorbell = &GenericPccCmObj->DoorbellReg; | |
ChannelTiming = &GenericPccCmObj->ChannelTiming; | |
PccAcpi->Type = GenericPccCmObj->Type; | |
PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); | |
PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; | |
PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; | |
PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; | |
PccAcpi->AddressLength = GenericPccCmObj->AddressLength; | |
CopyMem ( | |
&PccAcpi->DoorbellRegister, | |
&Doorbell->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; | |
PccAcpi->DoorbellWrite = Doorbell->WriteMask; | |
PccAcpi->NominalLatency = ChannelTiming->NominalLatency; | |
PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; | |
PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; | |
if ((PccCmObj->PlatIrq.Interrupt != 0)) { | |
mHasPlatformInterrupt = TRUE; | |
} | |
return EFI_SUCCESS; | |
} | |
/** Add one PCCT subspace structure of Type 2 (HW-Reduced). | |
@param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. | |
@param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. | |
@retval EFI_SUCCESS Table generated successfully. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
AddSubspaceStructType2 ( | |
IN CM_ARM_PCC_SUBSPACE_TYPE2_INFO *PccCmObj, | |
IN EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *PccAcpi | |
) | |
{ | |
CM_ARM_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; | |
PCC_MAILBOX_REGISTER_INFO *Doorbell; | |
PCC_MAILBOX_REGISTER_INFO *PlatIrqAck; | |
PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; | |
GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; | |
if ((PccCmObj == NULL) || | |
(GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS) || | |
(PccAcpi == NULL)) | |
{ | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
Doorbell = &GenericPccCmObj->DoorbellReg; | |
PlatIrqAck = &PccCmObj->PlatIrqAckReg; | |
ChannelTiming = &GenericPccCmObj->ChannelTiming; | |
PccAcpi->Type = GenericPccCmObj->Type; | |
PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); | |
PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; | |
PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; | |
PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; | |
PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; | |
PccAcpi->AddressLength = GenericPccCmObj->AddressLength; | |
CopyMem ( | |
&PccAcpi->DoorbellRegister, | |
&Doorbell->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; | |
PccAcpi->DoorbellWrite = Doorbell->WriteMask; | |
PccAcpi->NominalLatency = ChannelTiming->NominalLatency; | |
PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; | |
PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; | |
CopyMem ( | |
&PccAcpi->PlatformInterruptAckRegister, | |
&PlatIrqAck->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask; | |
PccAcpi->PlatformInterruptAckWrite = PlatIrqAck->WriteMask; | |
if ((PccCmObj->PlatIrq.Interrupt != 0)) { | |
mHasPlatformInterrupt = TRUE; | |
} | |
return EFI_SUCCESS; | |
} | |
/** Add one PCCT subspace structure of Type 3 or 4 (Extended). | |
@param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. | |
@param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. | |
@retval EFI_SUCCESS Table generated successfully. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
AddSubspaceStructType34 ( | |
IN CM_ARM_PCC_SUBSPACE_TYPE3_INFO *PccCmObj, | |
IN EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *PccAcpi | |
) | |
{ | |
CM_ARM_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; | |
PCC_MAILBOX_REGISTER_INFO *Doorbell; | |
PCC_MAILBOX_REGISTER_INFO *PlatIrqAck; | |
PCC_MAILBOX_REGISTER_INFO *CmdCompleteCheck; | |
PCC_MAILBOX_REGISTER_INFO *CmdCompleteUpdate; | |
PCC_MAILBOX_REGISTER_INFO *ErrorStatus; | |
PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; | |
GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; | |
if ((PccCmObj == NULL) || | |
((GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC) && | |
(GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC)) || | |
(PccAcpi == NULL)) | |
{ | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
Doorbell = &GenericPccCmObj->DoorbellReg; | |
PlatIrqAck = &PccCmObj->PlatIrqAckReg; | |
CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg; | |
CmdCompleteUpdate = &PccCmObj->CmdCompleteUpdateReg; | |
ErrorStatus = &PccCmObj->ErrorStatusReg; | |
ChannelTiming = &GenericPccCmObj->ChannelTiming; | |
PccAcpi->Type = GenericPccCmObj->Type; | |
PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); | |
PccAcpi->PlatformInterrupt = PccCmObj->PlatIrq.Interrupt; | |
PccAcpi->PlatformInterruptFlags = PccCmObj->PlatIrq.Flags; | |
PccAcpi->Reserved = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; | |
PccAcpi->AddressLength = GenericPccCmObj->AddressLength; | |
CopyMem ( | |
&PccAcpi->DoorbellRegister, | |
&Doorbell->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; | |
PccAcpi->DoorbellWrite = Doorbell->WriteMask; | |
PccAcpi->NominalLatency = ChannelTiming->NominalLatency; | |
PccAcpi->MaximumPeriodicAccessRate = ChannelTiming->MaxPeriodicAccessRate; | |
PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; | |
CopyMem ( | |
&PccAcpi->PlatformInterruptAckRegister, | |
&PlatIrqAck->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->PlatformInterruptAckPreserve = PlatIrqAck->PreserveMask; | |
PccAcpi->PlatformInterruptAckSet = PlatIrqAck->WriteMask; | |
PccAcpi->Reserved1[0] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[1] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[3] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[4] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[5] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[6] = EFI_ACPI_RESERVED_BYTE; | |
PccAcpi->Reserved1[7] = EFI_ACPI_RESERVED_BYTE; | |
CopyMem ( | |
&PccAcpi->CommandCompleteCheckRegister, | |
&CmdCompleteCheck->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask; | |
// No Write mask. | |
CopyMem ( | |
&PccAcpi->CommandCompleteUpdateRegister, | |
&CmdCompleteUpdate->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->CommandCompleteUpdatePreserve = CmdCompleteUpdate->PreserveMask; | |
PccAcpi->CommandCompleteUpdateSet = CmdCompleteUpdate->WriteMask; | |
CopyMem ( | |
&PccAcpi->ErrorStatusRegister, | |
&ErrorStatus->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask; | |
// No Write mask. | |
if (GenericPccCmObj->Type == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) { | |
mHasPlatformInterrupt = TRUE; | |
} else if ((PccCmObj->PlatIrq.Interrupt != 0)) { | |
mHasPlatformInterrupt = TRUE; | |
} | |
return EFI_SUCCESS; | |
} | |
/** Add one PCCT subspace structure of Type 5 (HW-Registers). | |
@param [in] PccCmObj Pointer to a CmObj PCCT Subspace info structure. | |
@param [in] PccAcpi Pointer to the ACPI PCCT Subspace structure to populate. | |
@retval EFI_SUCCESS Table generated successfully. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
AddSubspaceStructType5 ( | |
IN CM_ARM_PCC_SUBSPACE_TYPE5_INFO *PccCmObj, | |
IN EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *PccAcpi | |
) | |
{ | |
CM_ARM_PCC_SUBSPACE_TYPE0_INFO *GenericPccCmObj; | |
PCC_MAILBOX_REGISTER_INFO *Doorbell; | |
PCC_MAILBOX_REGISTER_INFO *CmdCompleteCheck; | |
PCC_MAILBOX_REGISTER_INFO *ErrorStatus; | |
PCC_SUBSPACE_CHANNEL_TIMING_INFO *ChannelTiming; | |
GenericPccCmObj = (CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)PccCmObj; | |
if ((PccCmObj == NULL) || | |
(GenericPccCmObj->Type != EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS) || | |
(PccAcpi == NULL)) | |
{ | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
Doorbell = &GenericPccCmObj->DoorbellReg; | |
CmdCompleteCheck = &PccCmObj->CmdCompleteCheckReg; | |
ErrorStatus = &PccCmObj->ErrorStatusReg; | |
ChannelTiming = &GenericPccCmObj->ChannelTiming; | |
PccAcpi->Type = GenericPccCmObj->Type; | |
PccAcpi->Length = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); | |
PccAcpi->Version = PccCmObj->Version; | |
PccAcpi->BaseAddress = GenericPccCmObj->BaseAddress; | |
PccAcpi->SharedMemoryRangeLength = GenericPccCmObj->AddressLength; | |
CopyMem ( | |
&PccAcpi->DoorbellRegister, | |
&Doorbell->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->DoorbellPreserve = Doorbell->PreserveMask; | |
PccAcpi->DoorbellWrite = Doorbell->WriteMask; | |
CopyMem ( | |
&PccAcpi->CommandCompleteCheckRegister, | |
&CmdCompleteCheck->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->CommandCompleteCheckMask = CmdCompleteCheck->PreserveMask; | |
// No Write mask. | |
CopyMem ( | |
&PccAcpi->ErrorStatusRegister, | |
&ErrorStatus->Register, | |
sizeof (EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE) | |
); | |
PccAcpi->ErrorStatusMask = ErrorStatus->PreserveMask; | |
// No Write mask. | |
PccAcpi->NominalLatency = ChannelTiming->NominalLatency; | |
// No MaximumPeriodicAccessRate. | |
PccAcpi->MinimumRequestTurnaroundTime = ChannelTiming->MinRequestTurnaroundTime; | |
return EFI_SUCCESS; | |
} | |
/** Populate the PCCT table using the MappingTable. | |
@param [in] MappingTable The mapping table structure. | |
@param [in] Pcc Pointer to an array of Pcc Subpace structures. | |
@param [in] Size Size of the Pcc array. | |
@retval EFI_SUCCESS Table generated successfully. | |
@retval EFI_BUFFER_TOO_SMALL Buffer too small. | |
@retval EFI_INVALID_PARAMETER A parameter is invalid. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
PopulatePcctTable ( | |
IN MAPPING_TABLE *MappingTable, | |
IN VOID *Pcc, | |
IN UINT32 Size | |
) | |
{ | |
EFI_STATUS Status; | |
UINT8 *PccBuffer; | |
UINT32 CmObjSize; | |
UINT32 Index; | |
UINT32 MaxIndex; | |
VOID **Table; | |
VOID *CurrentPccSubspace; | |
ASSERT (MappingTable != NULL); | |
ASSERT (MappingTable->Table != NULL); | |
PccBuffer = Pcc; | |
MaxIndex = MappingTable->MaxIndex; | |
Table = MappingTable->Table; | |
for (Index = 0; Index < MaxIndex; Index++) { | |
CurrentPccSubspace = Table[Index]; | |
if (CurrentPccSubspace == NULL) { | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
switch (((PCC_SUBSPACE_GENERIC_INFO *)CurrentPccSubspace)->Type) { | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC: | |
Status = AddSubspaceStructType0 ( | |
(CM_ARM_PCC_SUBSPACE_TYPE0_INFO *)CurrentPccSubspace, | |
(EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC *)PccBuffer | |
); | |
CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS: | |
Status = AddSubspaceStructType1 ( | |
(CM_ARM_PCC_SUBSPACE_TYPE1_INFO *)CurrentPccSubspace, | |
(EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS *)PccBuffer | |
); | |
CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS: | |
Status = AddSubspaceStructType2 ( | |
(CM_ARM_PCC_SUBSPACE_TYPE2_INFO *)CurrentPccSubspace, | |
(EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *)PccBuffer | |
); | |
CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC: | |
Status = AddSubspaceStructType34 ( | |
(CM_ARM_PCC_SUBSPACE_TYPE3_INFO *)CurrentPccSubspace, | |
(EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC *)PccBuffer | |
); | |
CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC: | |
Status = AddSubspaceStructType34 ( | |
(CM_ARM_PCC_SUBSPACE_TYPE4_INFO *)CurrentPccSubspace, | |
(EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC *)PccBuffer | |
); | |
CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC); | |
break; | |
case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS: | |
Status = AddSubspaceStructType5 ( | |
(CM_ARM_PCC_SUBSPACE_TYPE5_INFO *)CurrentPccSubspace, | |
(EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS *)PccBuffer | |
); | |
CmObjSize = sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); | |
break; | |
default: | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} // switch | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
return Status; | |
} | |
if (Size < CmObjSize) { | |
ASSERT_EFI_ERROR (EFI_BUFFER_TOO_SMALL); | |
return EFI_BUFFER_TOO_SMALL; | |
} | |
PccBuffer += CmObjSize; | |
Size -= CmObjSize; | |
} // for | |
return EFI_SUCCESS; | |
} | |
/** Construct the PCCT ACPI table. | |
Called by the Dynamic Table Manager, this function invokes the | |
Configuration Manager protocol interface to get the required hardware | |
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. | |
@retval EFI_BUFFER_TOO_SMALL Buffer too small. | |
@retval EFI_OUT_OF_RESOURCES Memory allocation failed. | |
**/ | |
STATIC | |
EFI_STATUS | |
EFIAPI | |
BuildPcctTable ( | |
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; | |
ACPI_PCCT_GENERATOR *Generator; | |
UINT32 TableSize; | |
EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *Pcct; | |
UINT8 *Buffer; | |
MAPPING_TABLE *MappingTable; | |
UINT32 MappingTableCount; | |
CM_ARM_PCC_SUBSPACE_TYPE0_INFO *PccType0; | |
UINT32 PccType0Count; | |
CM_ARM_PCC_SUBSPACE_TYPE1_INFO *PccType1; | |
UINT32 PccType1Count; | |
CM_ARM_PCC_SUBSPACE_TYPE2_INFO *PccType2; | |
UINT32 PccType2Count; | |
CM_ARM_PCC_SUBSPACE_TYPE3_INFO *PccType3; | |
UINT32 PccType3Count; | |
CM_ARM_PCC_SUBSPACE_TYPE4_INFO *PccType4; | |
UINT32 PccType4Count; | |
CM_ARM_PCC_SUBSPACE_TYPE5_INFO *PccType5; | |
UINT32 PccType5Count; | |
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: PCCT: Requested table revision = %d, is not supported." | |
"Supported table revision: Minimum = %d, Maximum = %d\n", | |
AcpiTableInfo->AcpiTableRevision, | |
This->MinAcpiTableRevision, | |
This->AcpiTableRevision | |
)); | |
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); | |
return EFI_INVALID_PARAMETER; | |
} | |
Generator = (ACPI_PCCT_GENERATOR *)This; | |
MappingTable = &Generator->MappingTable; | |
*Table = NULL; | |
// First get all the Pcc Subpace CmObj of type X. | |
Status = GetEArmObjPccSubspaceType0Info ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&PccType0, | |
&PccType0Count | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = GetEArmObjPccSubspaceType1Info ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&PccType1, | |
&PccType1Count | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = GetEArmObjPccSubspaceType2Info ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&PccType2, | |
&PccType2Count | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = GetEArmObjPccSubspaceType3Info ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&PccType3, | |
&PccType3Count | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = GetEArmObjPccSubspaceType4Info ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&PccType4, | |
&PccType4Count | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = GetEArmObjPccSubspaceType5Info ( | |
CfgMgrProtocol, | |
CM_NULL_TOKEN, | |
&PccType5, | |
&PccType5Count | |
); | |
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
// Count the number of Pcc Subspaces. | |
MappingTableCount = PccType0Count; | |
MappingTableCount += PccType1Count; | |
MappingTableCount += PccType2Count; | |
MappingTableCount += PccType3Count; | |
MappingTableCount += PccType4Count; | |
MappingTableCount += PccType5Count; | |
Status = MappingTableInitialize (MappingTable, MappingTableCount); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
// Map the Subspace Ids for all types. | |
Status = MapPccSubspaceId (MappingTable, PccType0, PccType0Count); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = MapPccSubspaceId (MappingTable, PccType1, PccType1Count); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = MapPccSubspaceId (MappingTable, PccType2, PccType2Count); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = MapPccSubspaceId (MappingTable, PccType3, PccType3Count); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = MapPccSubspaceId (MappingTable, PccType4, PccType4Count); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Status = MapPccSubspaceId (MappingTable, PccType5, PccType5Count); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
// Compute the size of the PCCT table. | |
TableSize = sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); | |
TableSize += PccType0Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_GENERIC); | |
TableSize += PccType1Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_1_HW_REDUCED_COMMUNICATIONS); | |
TableSize += PccType2Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); | |
TableSize += PccType3Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_3_EXTENDED_PCC); | |
TableSize += PccType4Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_4_EXTENDED_PCC); | |
TableSize += PccType5Count * sizeof (EFI_ACPI_6_4_PCCT_SUBSPACE_5_HW_REGISTERS_COMMUNICATIONS); | |
// Allocate a Buffer for the PCCT table. | |
*Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); | |
if (*Table == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Pcct = (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)*Table; | |
Status = AddAcpiHeader ( | |
CfgMgrProtocol, | |
This, | |
&Pcct->Header, | |
AcpiTableInfo, | |
TableSize | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: PCCT: Failed to add ACPI header. Status = %r\n", | |
Status | |
)); | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
Buffer = (UINT8 *)Pcct; | |
Buffer += sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); | |
TableSize -= sizeof (EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER); | |
// Populate the PCCT table by following the Subspace Id mapping. | |
Status = PopulatePcctTable (MappingTable, Buffer, TableSize); | |
if (EFI_ERROR (Status)) { | |
ASSERT_EFI_ERROR (Status); | |
goto error_handler; | |
} | |
// Setup the Reserved fields once mHasPlatformInterrupt hase been populated. | |
Pcct->Flags = mHasPlatformInterrupt; | |
Pcct->Reserved = EFI_ACPI_RESERVED_QWORD; | |
MappingTableFree (MappingTable); | |
return Status; | |
error_handler: | |
DEBUG (( | |
DEBUG_ERROR, | |
"ERROR: PCCT: Failed to install table. Status = %r\n", | |
Status | |
)); | |
if (*Table != NULL) { | |
FreePool (*Table); | |
*Table = NULL; | |
} | |
MappingTableFree (MappingTable); | |
return Status; | |
} | |
/** Free any resources allocated for constructing the PCCT. | |
@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 | |
FreePcctTableResources ( | |
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: PCCT: Invalid Table Pointer\n")); | |
ASSERT ((Table != NULL) && (*Table != NULL)); | |
return EFI_INVALID_PARAMETER; | |
} | |
FreePool (*Table); | |
*Table = NULL; | |
return EFI_SUCCESS; | |
} | |
/** This macro defines the PCCT Table Generator revision. | |
*/ | |
#define PCCT_GENERATOR_REVISION CREATE_REVISION (1, 0) | |
/** The interface for the PCCT Table Generator. | |
*/ | |
STATIC | |
ACPI_PCCT_GENERATOR PcctGenerator = { | |
// ACPI table generator header | |
{ | |
// Generator ID | |
CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdPcct), | |
// Generator Description | |
L"ACPI.STD.PCCT.GENERATOR", | |
// ACPI Table Signature | |
EFI_ACPI_6_4_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE, | |
// ACPI Table Revision supported by this Generator | |
EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, | |
// Minimum ACPI Table Revision supported by this Generator | |
EFI_ACPI_6_4_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, | |
// Creator ID | |
TABLE_GENERATOR_CREATOR_ID_ARM, | |
// Creator Revision | |
PCCT_GENERATOR_REVISION, | |
// Build Table function | |
BuildPcctTable, | |
// Free Resource function | |
FreePcctTableResources, | |
// Extended build function not needed | |
NULL, | |
// Extended build function not implemented by the generator. | |
// Hence extended free resource function is not required. | |
NULL | |
}, | |
// Private fields are defined from here. | |
// Mapping Table | |
{ | |
// Table | |
NULL, | |
// MaxIndex | |
0, | |
}, | |
}; | |
/** 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 | |
AcpiPcctLibConstructor ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
Status = RegisterAcpiTableGenerator (&PcctGenerator.Header); | |
DEBUG ((DEBUG_INFO, "PCCT: 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 | |
AcpiPcctLibDestructor ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
Status = DeregisterAcpiTableGenerator (&PcctGenerator.Header); | |
DEBUG ((DEBUG_INFO, "PCCT: Deregister Generator. Status = %r\n", Status)); | |
ASSERT_EFI_ERROR (Status); | |
return Status; | |
} |