summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c835
1 files changed, 835 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
new file mode 100644
index 00000000..1d723939
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
@@ -0,0 +1,835 @@
+/** @file
+ SRAT Table Generator
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification, January 2019
+
+ @par Glossary:
+ - Cm or CM - Configuration Manager
+ - Obj or OBJ - Object
+**/
+
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.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>
+
+/**
+ ARM standard SRAT Generator
+
+ Requirements:
+ The following Configuration Manager Object(s) are used by this Generator:
+ - EArmObjGicCInfo (REQUIRED)
+ - EArmObjGicItsInfo (OPTIONAL)
+ - EArmObjMemoryAffinityInfo (OPTIONAL)
+ - EArmObjGenericInitiatorAffinityInfo (OPTIONAL)
+ - EArmObjDeviceHandleAcpi (OPTIONAL)
+ - EArmObjDeviceHandlePci (OPTIONAL)
+*/
+
+/** This macro expands to a function that retrieves the GIC
+ CPU interface Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjGicCInfo,
+ CM_ARM_GICC_INFO
+ );
+
+/** This macro expands to a function that retrieves the GIC
+ Interrupt Translation Service Information from the
+ Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjGicItsInfo,
+ CM_ARM_GIC_ITS_INFO
+ );
+
+/**
+ This macro expands to a function that retrieves the Memory Affinity
+ information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjMemoryAffinityInfo,
+ CM_ARM_MEMORY_AFFINITY_INFO
+ );
+
+/**
+ This macro expands to a function that retrieves the Generic Initiator Affinity
+ information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjGenericInitiatorAffinityInfo,
+ CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO
+ );
+
+/**
+ This macro expands to a function that retrieves the ACPI Device Handle
+ information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjDeviceHandleAcpi,
+ CM_ARM_DEVICE_HANDLE_ACPI
+ );
+
+/**
+ This macro expands to a function that retrieves the PCI Device Handle
+ information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjDeviceHandlePci,
+ CM_ARM_DEVICE_HANDLE_PCI
+ );
+
+
+/** Return the PCI Device information in BDF format
+
+ PCI Bus Number - Max 256 busses (Bits 15:8 of BDF)
+ PCI Device Number - Max 32 devices (Bits 7:3 of BDF)
+ PCI Function Number - Max 8 functions (Bits 2:0 of BDF)
+
+ @param [in] DeviceHandlePci Pointer to the PCI Device Handle.
+
+ @retval BDF value corresponding to the PCI Device Handle.
+**/
+STATIC
+UINT16
+GetBdf (
+ IN CONST CM_ARM_DEVICE_HANDLE_PCI * DeviceHandlePci
+ )
+{
+ UINT16 Bdf;
+ Bdf = (UINT16)DeviceHandlePci->BusNumber << 8;
+ Bdf |= (DeviceHandlePci->DeviceNumber & 0x1F) << 3;
+ Bdf |= DeviceHandlePci->FunctionNumber & 0x7;
+ return Bdf;
+}
+
+/** Add the GICC Affinity Structures in the SRAT Table.
+
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in] Srat Pointer to the SRAT Table.
+ @param [in] GicCAffOffset Offset of the GICC Affinity
+ information in the SRAT Table.
+ @param [in] GicCInfo Pointer to the GIC CPU Information list.
+ @param [in] GicCCount Count of GIC CPU Interfaces.
+
+ @retval EFI_SUCCESS Table generated successfully.
+**/
+STATIC
+EFI_STATUS
+AddGICCAffinity (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,
+ IN CONST UINT32 GicCAffOffset,
+ IN CONST CM_ARM_GICC_INFO * GicCInfo,
+ IN UINT32 GicCCount
+ )
+{
+ EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE * GicCAff;
+
+ ASSERT (Srat != NULL);
+ ASSERT (GicCInfo != NULL);
+
+ GicCAff = (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *)((UINT8*)Srat +
+ GicCAffOffset);
+
+ while (GicCCount-- != 0) {
+ DEBUG ((DEBUG_INFO, "SRAT: GicCAff = 0x%p\n", GicCAff));
+
+ GicCAff->Type = EFI_ACPI_6_3_GICC_AFFINITY;
+ GicCAff->Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE);
+ GicCAff->ProximityDomain = GicCInfo->ProximityDomain;
+ GicCAff->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;
+ GicCAff->Flags = GicCInfo->AffinityFlags;
+ GicCAff->ClockDomain = GicCInfo->ClockDomain;
+
+ // Next
+ GicCAff++;
+ GicCInfo++;
+ }// while
+ return EFI_SUCCESS;
+}
+
+/** Add the GIC ITS Affinity Structures in the SRAT Table.
+
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in] Srat Pointer to the SRAT Table.
+ @param [in] GicItsAffOffset Offset of the GIC ITS Affinity
+ information in the SRAT Table.
+ @param [in] GicItsInfo Pointer to the GIC ITS Information list.
+ @param [in] GicItsCount Count of GIC ITS.
+
+ @retval EFI_SUCCESS Table generated successfully.
+**/
+STATIC
+EFI_STATUS
+AddGICItsAffinity (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,
+ IN CONST UINT32 GicItsAffOffset,
+ IN CONST CM_ARM_GIC_ITS_INFO * GicItsInfo,
+ IN UINT32 GicItsCount
+ )
+{
+ EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE * GicItsAff;
+
+ ASSERT (Srat != NULL);
+ ASSERT (GicItsInfo != NULL);
+
+ GicItsAff = (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *)((UINT8*)Srat +
+ GicItsAffOffset);
+
+ while (GicItsCount-- != 0) {
+ DEBUG ((DEBUG_INFO, "SRAT: GicItsAff = 0x%p\n", GicItsAff));
+
+ GicItsAff->Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY;
+ GicItsAff->Length = sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE);
+ GicItsAff->ProximityDomain = GicItsInfo->ProximityDomain;
+ GicItsAff->Reserved[0] = EFI_ACPI_RESERVED_BYTE;
+ GicItsAff->Reserved[1] = EFI_ACPI_RESERVED_BYTE;
+ GicItsAff->ItsId = GicItsInfo->GicItsId;
+
+ // Next
+ GicItsAff++;
+ GicItsInfo++;
+ }// while
+ return EFI_SUCCESS;
+}
+
+/** Add the Memory Affinity Structures in the SRAT Table.
+
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in] Srat Pointer to the SRAT Table.
+ @param [in] MemAffOffset Offset of the Memory Affinity
+ information in the SRAT Table.
+ @param [in] MemAffInfo Pointer to the Memory Affinity Information list.
+ @param [in] MemAffCount Count of Memory Affinity objects.
+
+ @retval EFI_SUCCESS Table generated successfully.
+**/
+STATIC
+EFI_STATUS
+AddMemoryAffinity (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,
+ IN CONST UINT32 MemAffOffset,
+ IN CONST CM_ARM_MEMORY_AFFINITY_INFO * MemAffInfo,
+ IN UINT32 MemAffCount
+ )
+{
+ EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE * MemAff;
+
+ ASSERT (Srat != NULL);
+ ASSERT (MemAffInfo != NULL);
+
+ MemAff = (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *)((UINT8*)Srat +
+ MemAffOffset);
+
+ while (MemAffCount-- != 0) {
+ DEBUG ((DEBUG_INFO, "SRAT: MemAff = 0x%p\n", MemAff));
+
+ MemAff->Type = EFI_ACPI_6_3_MEMORY_AFFINITY;
+ MemAff->Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE);
+ MemAff->ProximityDomain = MemAffInfo->ProximityDomain;
+ MemAff->Reserved1 = EFI_ACPI_RESERVED_WORD;
+ MemAff->AddressBaseLow = (UINT32)(MemAffInfo->BaseAddress & MAX_UINT32);
+ MemAff->AddressBaseHigh = (UINT32)(MemAffInfo->BaseAddress >> 32);
+ MemAff->LengthLow = (UINT32)(MemAffInfo->Length & MAX_UINT32);
+ MemAff->LengthHigh = (UINT32)(MemAffInfo->Length >> 32);
+ MemAff->Reserved2 = EFI_ACPI_RESERVED_DWORD;
+ MemAff->Flags = MemAffInfo->Flags;
+ MemAff->Reserved3 = EFI_ACPI_RESERVED_QWORD;
+
+ // Next
+ MemAff++;
+ MemAffInfo++;
+ }// while
+ return EFI_SUCCESS;
+}
+
+
+/** Add the Generic Initiator Affinity Structures in the SRAT Table.
+
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in] Srat Pointer to the SRAT Table.
+ @param [in] GenInitAffOff Offset of the Generic Initiator Affinity
+ information in the SRAT Table.
+ @param [in] GenInitAffInfo Pointer to the Generic Initiator Affinity
+ Information list.
+ @param [in] GenInitAffCount Count of Generic Initiator Affinity
+ objects.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The required object information is 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
+AddGenericInitiatorAffinity (
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,
+ IN CONST UINT32 GenInitAffOff,
+ IN CONST CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO * GenInitAffInfo,
+ IN UINT32 GenInitAffCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE * GenInitAff;
+ CM_ARM_DEVICE_HANDLE_ACPI * DeviceHandleAcpi;
+ CM_ARM_DEVICE_HANDLE_PCI * DeviceHandlePci;
+ UINT32 DeviceHandleCount;
+
+ ASSERT (Srat != NULL);
+ ASSERT (GenInitAffInfo != NULL);
+
+ GenInitAff = (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *)(
+ (UINT8*)Srat + GenInitAffOff);
+
+ while (GenInitAffCount-- != 0) {
+ DEBUG ((DEBUG_INFO, "SRAT: GenInitAff = 0x%p\n", GenInitAff));
+
+ GenInitAff->Type = EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY;
+ GenInitAff->Length =
+ sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE);
+ GenInitAff->Reserved1 = EFI_ACPI_RESERVED_WORD;
+ GenInitAff->DeviceHandleType = GenInitAffInfo->DeviceHandleType;
+ GenInitAff->ProximityDomain = GenInitAffInfo->ProximityDomain;
+
+ if (GenInitAffInfo->DeviceHandleToken == CM_NULL_TOKEN) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Invalid Device Handle Token.\n"
+ ));
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (GenInitAffInfo->DeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) {
+ Status = GetEArmObjDeviceHandleAcpi (
+ CfgMgrProtocol,
+ GenInitAffInfo->DeviceHandleToken,
+ &DeviceHandleAcpi,
+ &DeviceHandleCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to get ACPI Device Handle Inf."
+ " DeviceHandleToken = %p."
+ " Status = %r\n",
+ GenInitAffInfo->DeviceHandleToken,
+ Status
+ ));
+ return Status;
+ }
+
+ // We are expecting only one device handle.
+ ASSERT (DeviceHandleCount == 1);
+
+ // Populate the ACPI device handle information.
+ GenInitAff->DeviceHandle.Acpi.AcpiHid = DeviceHandleAcpi->Hid;
+ GenInitAff->DeviceHandle.Acpi.AcpiUid = DeviceHandleAcpi->Uid;
+ GenInitAff->DeviceHandle.Acpi.Reserved[0] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Acpi.Reserved[1] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Acpi.Reserved[2] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Acpi.Reserved[3] = EFI_ACPI_RESERVED_BYTE;
+ } else if (GenInitAffInfo->DeviceHandleType ==
+ EFI_ACPI_6_3_PCI_DEVICE_HANDLE) {
+ Status = GetEArmObjDeviceHandlePci (
+ CfgMgrProtocol,
+ GenInitAffInfo->DeviceHandleToken,
+ &DeviceHandlePci,
+ &DeviceHandleCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to get ACPI Device Handle Inf."
+ " DeviceHandleToken = %p."
+ " Status = %r\n",
+ GenInitAffInfo->DeviceHandleToken,
+ Status
+ ));
+ return Status;
+ }
+
+ // We are expecting only one device handle
+ ASSERT (DeviceHandleCount == 1);
+
+ // Populate the ACPI device handle information.
+ GenInitAff->DeviceHandle.Pci.PciSegment = DeviceHandlePci->SegmentNumber;
+ GenInitAff->DeviceHandle.Pci.PciBdfNumber = GetBdf (DeviceHandlePci);
+
+ GenInitAff->DeviceHandle.Pci.Reserved[0] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[1] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[2] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[3] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[4] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[5] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[6] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[7] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[8] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[9] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[10] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->DeviceHandle.Pci.Reserved[11] = EFI_ACPI_RESERVED_BYTE;
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Invalid Device Handle Type.\n"
+ ));
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ GenInitAff->Flags = GenInitAffInfo->Flags;
+ GenInitAff->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;
+ GenInitAff->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;
+
+ // Next
+ GenInitAff++;
+ GenInitAffInfo++;
+ }// while
+ return EFI_SUCCESS;
+}
+
+/** Construct the SRAT 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_OUT_OF_RESOURCES Memory allocation failed.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSratTable (
+ 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;
+ UINT32 TableSize;
+ UINT32 GicCCount;
+ UINT32 GicItsCount;
+ UINT32 MemAffCount;
+ UINT32 GenInitiatorAffCount;
+
+ UINT32 GicCAffOffset;
+ UINT32 GicItsAffOffset;
+ UINT32 MemAffOffset;
+ UINT32 GenInitiatorAffOffset;
+
+ CM_ARM_GICC_INFO * GicCInfo;
+ CM_ARM_GIC_ITS_INFO * GicItsInfo;
+ CM_ARM_MEMORY_AFFINITY_INFO * MemAffInfo;
+ CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO * GenInitiatorAffInfo;
+
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * Srat;
+
+ ASSERT (
+ (This != NULL) &&
+ (AcpiTableInfo != NULL) &&
+ (CfgMgrProtocol != NULL) &&
+ (Table != NULL) &&
+ (AcpiTableInfo->TableGeneratorId == This->GeneratorID) &&
+ (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)
+ );
+
+ if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
+ (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Requested table revision = %d is not supported. "
+ "Supported table revisions: Minimum = %d. Maximum = %d\n",
+ AcpiTableInfo->AcpiTableRevision,
+ This->MinAcpiTableRevision,
+ This->AcpiTableRevision
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Table = NULL;
+
+ Status = GetEArmObjGicCInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &GicCInfo,
+ &GicCCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to get GICC Info. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ if (GicCCount == 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: GIC CPU Interface information not provided.\n"
+ ));
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ Status = GetEArmObjGicItsInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &GicItsInfo,
+ &GicItsCount
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to get GIC ITS Info. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ Status = GetEArmObjMemoryAffinityInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &MemAffInfo,
+ &MemAffCount
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to get Memory Affinity Info. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ Status = GetEArmObjGenericInitiatorAffinityInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &GenInitiatorAffInfo,
+ &GenInitiatorAffCount
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to get Generic Initiator Affinity Info."
+ " Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ // Calculate the size of the SRAT table
+ TableSize = sizeof (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER);
+
+ GicCAffOffset = TableSize;
+ TableSize += (sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) * GicCCount);
+
+ if (GicItsCount != 0) {
+ GicItsAffOffset = TableSize;
+ TableSize += (sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE) *
+ GicItsCount);
+ }
+
+ if (MemAffCount != 0) {
+ MemAffOffset = TableSize;
+ TableSize += (sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) *
+ MemAffCount);
+ }
+
+ if (GenInitiatorAffCount != 0) {
+ GenInitiatorAffOffset = TableSize;
+ TableSize += (sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE) *
+ GenInitiatorAffCount);
+ }
+
+ // Allocate the Buffer for SRAT table
+ *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);
+ if (*Table == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to allocate memory for SRAT Table, Size = %d," \
+ " Status = %r\n",
+ TableSize,
+ Status
+ ));
+ goto error_handler;
+ }
+
+ Srat = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER*)*Table;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "SRAT: Srat = 0x%p TableSize = 0x%x\n",
+ Srat,
+ TableSize
+ ));
+
+ Status = AddAcpiHeader (
+ CfgMgrProtocol,
+ This,
+ &Srat->Header,
+ AcpiTableInfo,
+ TableSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to add ACPI header. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ // Setup the Reserved fields
+ // Reserved1 must be set to 1 for backward compatibility
+ Srat->Reserved1 = 1;
+ Srat->Reserved2 = EFI_ACPI_RESERVED_QWORD;
+
+ Status = AddGICCAffinity (
+ CfgMgrProtocol,
+ Srat,
+ GicCAffOffset,
+ GicCInfo,
+ GicCCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to add GICC Affinity structures. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ if (GicItsCount != 0) {
+ Status = AddGICItsAffinity (
+ CfgMgrProtocol,
+ Srat,
+ GicItsAffOffset,
+ GicItsInfo,
+ GicItsCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to add GIC ITS Affinity structures. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+ }
+
+ if (MemAffCount != 0) {
+ Status = AddMemoryAffinity (
+ CfgMgrProtocol,
+ Srat,
+ MemAffOffset,
+ MemAffInfo,
+ MemAffCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to add Memory Affinity structures. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+ }
+
+ if (GenInitiatorAffCount != 0) {
+ Status = AddGenericInitiatorAffinity (
+ CfgMgrProtocol,
+ Srat,
+ GenInitiatorAffOffset,
+ GenInitiatorAffInfo,
+ GenInitiatorAffCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SRAT: Failed to add Generic Initiator Affinity structures."
+ " Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+ }
+
+ return Status;
+
+error_handler:
+
+ if (*Table != NULL) {
+ FreePool (*Table);
+ *Table = NULL;
+ }
+
+ return Status;
+}
+
+/** Free any resources allocated for constructing the SRAT.
+
+ @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
+FreeSratTableResources (
+ 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) &&
+ (AcpiTableInfo != NULL) &&
+ (CfgMgrProtocol != NULL) &&
+ (AcpiTableInfo->TableGeneratorId == This->GeneratorID) &&
+ (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)
+ );
+
+ if ((Table == NULL) || (*Table == NULL)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SRAT: Invalid Table Pointer\n"));
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (*Table);
+ *Table = NULL;
+ return EFI_SUCCESS;
+}
+
+/** The SRAT Table Generator revision.
+*/
+#define SRAT_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the SRAT Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR SratGenerator = {
+ // Generator ID
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSrat),
+ // Generator Description
+ L"ACPI.STD.SRAT.GENERATOR",
+ // ACPI Table Signature
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE,
+ // ACPI Table Revision supported by this Generator
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION,
+ // Minimum supported ACPI Table Revision
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION,
+ // Creator ID
+ TABLE_GENERATOR_CREATOR_ID_ARM,
+ // Creator Revision
+ SRAT_GENERATOR_REVISION,
+ // Build Table function
+ BuildSratTable,
+ // Free Resource function
+ FreeSratTableResources,
+ // 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
+AcpiSratLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+ Status = RegisterAcpiTableGenerator (&SratGenerator);
+ DEBUG ((DEBUG_INFO, "SRAT: 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
+AcpiSratLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+ Status = DeregisterAcpiTableGenerator (&SratGenerator);
+ DEBUG ((DEBUG_INFO, "SRAT: Deregister Generator. Status = %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}