in the ARM Namespace\r
*/\r
typedef enum ArmObjectID {\r
- EArmObjReserved, ///< 0 - Reserved\r
- EArmObjBootArchInfo, ///< 1 - Boot Architecture Info\r
- EArmObjCpuInfo, ///< 2 - CPU Info\r
- EArmObjPowerManagementProfileInfo, ///< 3 - Power Management Profile Info\r
- EArmObjGicCInfo, ///< 4 - GIC CPU Interface Info\r
- EArmObjGicDInfo, ///< 5 - GIC Distributor Info\r
- EArmObjGicMsiFrameInfo, ///< 6 - GIC MSI Frame Info\r
- EArmObjGicRedistributorInfo, ///< 7 - GIC Redistributor Info\r
- EArmObjGicItsInfo, ///< 8 - GIC ITS Info\r
- EArmObjSerialConsolePortInfo, ///< 9 - Serial Console Port Info\r
- EArmObjSerialDebugPortInfo, ///< 10 - Serial Debug Port Info\r
- EArmObjGenericTimerInfo, ///< 11 - Generic Timer Info\r
- EArmObjPlatformGTBlockInfo, ///< 12 - Platform GT Block Info\r
- EArmObjGTBlockTimerFrameInfo, ///< 13 - Generic Timer Block Frame Info\r
- EArmObjPlatformGenericWatchdogInfo, ///< 14 - Platform Generic Watchdog\r
- EArmObjPciConfigSpaceInfo, ///< 15 - PCI Configuration Space Info\r
- EArmObjHypervisorVendorIdentity, ///< 16 - Hypervisor Vendor Id\r
- EArmObjFixedFeatureFlags, ///< 17 - Fixed feature flags for FADT\r
- EArmObjItsGroup, ///< 18 - ITS Group\r
- EArmObjNamedComponent, ///< 19 - Named Component\r
- EArmObjRootComplex, ///< 20 - Root Complex\r
- EArmObjSmmuV1SmmuV2, ///< 21 - SMMUv1 or SMMUv2\r
- EArmObjSmmuV3, ///< 22 - SMMUv3\r
- EArmObjPmcg, ///< 23 - PMCG\r
- EArmObjGicItsIdentifierArray, ///< 24 - GIC ITS Identifier Array\r
- EArmObjIdMappingArray, ///< 25 - ID Mapping Array\r
- EArmObjSmmuInterruptArray, ///< 26 - SMMU Interrupt Array\r
- EArmObjProcHierarchyInfo, ///< 27 - Processor Hierarchy Info\r
- EArmObjCacheInfo, ///< 28 - Cache Info\r
- EArmObjProcNodeIdInfo, ///< 29 - Processor Hierarchy Node ID Info\r
- EArmObjCmRef, ///< 30 - CM Object Reference\r
+ EArmObjReserved, ///< 0 - Reserved\r
+ EArmObjBootArchInfo, ///< 1 - Boot Architecture Info\r
+ EArmObjCpuInfo, ///< 2 - CPU Info\r
+ EArmObjPowerManagementProfileInfo, ///< 3 - Power Management Profile Info\r
+ EArmObjGicCInfo, ///< 4 - GIC CPU Interface Info\r
+ EArmObjGicDInfo, ///< 5 - GIC Distributor Info\r
+ EArmObjGicMsiFrameInfo, ///< 6 - GIC MSI Frame Info\r
+ EArmObjGicRedistributorInfo, ///< 7 - GIC Redistributor Info\r
+ EArmObjGicItsInfo, ///< 8 - GIC ITS Info\r
+ EArmObjSerialConsolePortInfo, ///< 9 - Serial Console Port Info\r
+ EArmObjSerialDebugPortInfo, ///< 10 - Serial Debug Port Info\r
+ EArmObjGenericTimerInfo, ///< 11 - Generic Timer Info\r
+ EArmObjPlatformGTBlockInfo, ///< 12 - Platform GT Block Info\r
+ EArmObjGTBlockTimerFrameInfo, ///< 13 - Generic Timer Block Frame Info\r
+ EArmObjPlatformGenericWatchdogInfo, ///< 14 - Platform Generic Watchdog\r
+ EArmObjPciConfigSpaceInfo, ///< 15 - PCI Configuration Space Info\r
+ EArmObjHypervisorVendorIdentity, ///< 16 - Hypervisor Vendor Id\r
+ EArmObjFixedFeatureFlags, ///< 17 - Fixed feature flags for FADT\r
+ EArmObjItsGroup, ///< 18 - ITS Group\r
+ EArmObjNamedComponent, ///< 19 - Named Component\r
+ EArmObjRootComplex, ///< 20 - Root Complex\r
+ EArmObjSmmuV1SmmuV2, ///< 21 - SMMUv1 or SMMUv2\r
+ EArmObjSmmuV3, ///< 22 - SMMUv3\r
+ EArmObjPmcg, ///< 23 - PMCG\r
+ EArmObjGicItsIdentifierArray, ///< 24 - GIC ITS Identifier Array\r
+ EArmObjIdMappingArray, ///< 25 - ID Mapping Array\r
+ EArmObjSmmuInterruptArray, ///< 26 - SMMU Interrupt Array\r
+ EArmObjProcHierarchyInfo, ///< 27 - Processor Hierarchy Info\r
+ EArmObjCacheInfo, ///< 28 - Cache Info\r
+ EArmObjProcNodeIdInfo, ///< 29 - Processor Node ID Info\r
+ EArmObjCmRef, ///< 30 - CM Object Reference\r
+ EArmObjMemoryAffinityInfo, ///< 31 - Memory Affinity Info\r
+ EArmObjDeviceHandleAcpi, ///< 32 - Device Handle Acpi\r
+ EArmObjDeviceHandlePci, ///< 33 - Device Handle Pci\r
+ EArmObjGenericInitiatorAffinityInfo, ///< 34 - Generic Initiator Affinity\r
EArmObjMax\r
} EARM_OBJECT_ID;\r
\r
generating MADT revision 4 or lower.\r
*/\r
UINT16 SpeOverflowInterrupt;\r
+\r
+ /** The proximity domain to which the logical processor belongs.\r
+ This field is used to populate the GICC affinity structure\r
+ in the SRAT table.\r
+ */\r
+ UINT32 ProximityDomain;\r
+\r
+ /** The clock domain to which the logical processor belongs.\r
+ This field is used to populate the GICC affinity structure\r
+ in the SRAT table.\r
+ */\r
+ UINT32 ClockDomain;\r
+\r
+ /** The GICC Affinity flags field as described by the GICC Affinity structure\r
+ in the SRAT table.\r
+ */\r
+ UINT32 AffinityFlags;\r
} CM_ARM_GICC_INFO;\r
\r
/** A structure that describes the\r
\r
/// The physical address for the Interrupt Translation Service\r
UINT64 PhysicalBaseAddress;\r
+\r
+ /** The proximity domain to which the logical processor belongs.\r
+ This field is used to populate the GIC ITS affinity structure\r
+ in the SRAT table.\r
+ */\r
+ UINT32 ProximityDomain;\r
} CM_ARM_GIC_ITS_INFO;\r
\r
/** A structure that describes the\r
CM_OBJECT_TOKEN ReferenceToken;\r
} CM_ARM_OBJ_REF;\r
\r
+/** A structure that describes the Memory Affinity Structure (Type 1) in SRAT\r
+\r
+ ID: EArmObjMemoryAffinityInfo\r
+*/\r
+typedef struct CmArmMemoryAffinityInfo {\r
+ /// The proximity domain to which the "range of memory" belongs.\r
+ UINT32 ProximityDomain;\r
+\r
+ /// Base Address\r
+ UINT64 BaseAddress;\r
+\r
+ /// Length\r
+ UINT64 Length;\r
+\r
+ /// Flags\r
+ UINT32 Flags;\r
+} CM_ARM_MEMORY_AFFINITY_INFO;\r
+\r
+/** A structure that describes the ACPI Device Handle (Type 0) in the\r
+ Generic Initiator Affinity structure in SRAT\r
+\r
+ ID: EArmObjDeviceHandleAcpi\r
+*/\r
+typedef struct CmArmDeviceHandleAcpi {\r
+ /// Hardware ID\r
+ UINT64 Hid;\r
+\r
+ /// Unique Id\r
+ UINT32 Uid;\r
+} CM_ARM_DEVICE_HANDLE_ACPI;\r
+\r
+/** A structure that describes the PCI Device Handle (Type 1) in the\r
+ Generic Initiator Affinity structure in SRAT\r
+\r
+ ID: EArmObjDeviceHandlePci\r
+*/\r
+typedef struct CmArmDeviceHandlePci {\r
+ /// PCI Segment Number\r
+ UINT16 SegmentNumber;\r
+\r
+ /// PCI Bus Number - Max 256 busses (Bits 15:8 of BDF)\r
+ UINT8 BusNumber;\r
+\r
+ /// PCI Device Mumber - Max 32 devices (Bits 7:3 of BDF)\r
+ UINT8 DeviceNumber;\r
+\r
+ /// PCI Function Number - Max 8 functions (Bits 2:0 of BDF)\r
+ UINT8 FunctionNumber;\r
+} CM_ARM_DEVICE_HANDLE_PCI;\r
+\r
+/** A structure that describes the Generic Initiator Affinity structure in SRAT\r
+\r
+ ID: EArmObjGenericInitiatorAffinityInfo\r
+*/\r
+typedef struct CmArmGenericInitiatorAffinityInfo {\r
+ /// The proximity domain to which the generic initiator belongs.\r
+ UINT32 ProximityDomain;\r
+\r
+ /// Flags\r
+ UINT32 Flags;\r
+\r
+ /// Device Handle Type\r
+ UINT8 DeviceHandleType;\r
+\r
+ /// Reference Token for the Device Handle\r
+ CM_OBJECT_TOKEN DeviceHandleToken;\r
+} CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO;\r
+\r
#pragma pack()\r
\r
#endif // ARM_NAMESPACE_OBJECTS_H_\r
--- /dev/null
+/** @file\r
+ SRAT Table Generator\r
+\r
+ Copyright (c) 2019, ARM Limited. All rights reserved.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+ @par Reference(s):\r
+ - ACPI 6.3 Specification, January 2019\r
+\r
+ @par Glossary:\r
+ - Cm or CM - Configuration Manager\r
+ - Obj or OBJ - Object\r
+**/\r
+\r
+#include <Library/AcpiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Protocol/AcpiTable.h>\r
+\r
+// Module specific include files.\r
+#include <AcpiTableGenerator.h>\r
+#include <ConfigurationManagerObject.h>\r
+#include <ConfigurationManagerHelper.h>\r
+#include <Library/TableHelperLib.h>\r
+#include <Protocol/ConfigurationManagerProtocol.h>\r
+\r
+/**\r
+ ARM standard SRAT Generator\r
+\r
+ Requirements:\r
+ The following Configuration Manager Object(s) are used by this Generator:\r
+ - EArmObjGicCInfo (REQUIRED)\r
+ - EArmObjGicItsInfo (OPTIONAL)\r
+ - EArmObjMemoryAffinityInfo (OPTIONAL)\r
+ - EArmObjGenericInitiatorAffinityInfo (OPTIONAL)\r
+ - EArmObjDeviceHandleAcpi (OPTIONAL)\r
+ - EArmObjDeviceHandlePci (OPTIONAL)\r
+*/\r
+\r
+/** This macro expands to a function that retrieves the GIC\r
+ CPU interface Information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjGicCInfo,\r
+ CM_ARM_GICC_INFO\r
+ );\r
+\r
+/** This macro expands to a function that retrieves the GIC\r
+ Interrupt Translation Service Information from the\r
+ Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjGicItsInfo,\r
+ CM_ARM_GIC_ITS_INFO\r
+ );\r
+\r
+/**\r
+ This macro expands to a function that retrieves the Memory Affinity\r
+ information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjMemoryAffinityInfo,\r
+ CM_ARM_MEMORY_AFFINITY_INFO\r
+ );\r
+\r
+/**\r
+ This macro expands to a function that retrieves the Generic Initiator Affinity\r
+ information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjGenericInitiatorAffinityInfo,\r
+ CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO\r
+ );\r
+\r
+/**\r
+ This macro expands to a function that retrieves the ACPI Device Handle\r
+ information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjDeviceHandleAcpi,\r
+ CM_ARM_DEVICE_HANDLE_ACPI\r
+ );\r
+\r
+/**\r
+ This macro expands to a function that retrieves the PCI Device Handle\r
+ information from the Configuration Manager.\r
+*/\r
+GET_OBJECT_LIST (\r
+ EObjNameSpaceArm,\r
+ EArmObjDeviceHandlePci,\r
+ CM_ARM_DEVICE_HANDLE_PCI\r
+ );\r
+\r
+\r
+/** Return the PCI Device information in BDF format\r
+\r
+ PCI Bus Number - Max 256 busses (Bits 15:8 of BDF)\r
+ PCI Device Mumber - Max 32 devices (Bits 7:3 of BDF)\r
+ PCI Function Number - Max 8 functions (Bits 2:0 of BDF)\r
+\r
+ @param [in] DeviceHandlePci Pointer to the PCI Device Handle.\r
+\r
+ @retval BDF value corresponding to the PCI Device Handle.\r
+*/\r
+STATIC\r
+UINT16\r
+GetBdf (\r
+ IN CONST CM_ARM_DEVICE_HANDLE_PCI * DeviceHandlePci\r
+ )\r
+{\r
+ UINT16 Bdf;\r
+ Bdf = (UINT16)DeviceHandlePci->BusNumber << 8;\r
+ Bdf |= (DeviceHandlePci->DeviceNumber & 0x1F) << 3;\r
+ Bdf |= DeviceHandlePci->FunctionNumber & 0x7;\r
+ return Bdf;\r
+}\r
+\r
+/** Add the GICC Affinity Structures in the SRAT Table.\r
+\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] Srat Pointer to the SRAT Table.\r
+ @param [in] GicCAffOffset Offset of the GICC Affinity\r
+ information in the SRAT Table.\r
+ @param [in] GicCInfo Pointer to the GIC CPU Information list.\r
+ @param [in] GicCCount Count of GIC CPU Interfaces.\r
+\r
+ @retval EFI_SUCCESS Table generated successfully.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddGICCAffinity (\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,\r
+ IN CONST UINT32 GicCAffOffset,\r
+ IN CONST CM_ARM_GICC_INFO * GicCInfo,\r
+ IN UINT32 GicCCount\r
+ )\r
+{\r
+ EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE * GicCAff;\r
+\r
+ ASSERT (Srat != NULL);\r
+ ASSERT (GicCInfo != NULL);\r
+\r
+ GicCAff = (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *)((UINT8*)Srat +\r
+ GicCAffOffset);\r
+\r
+ while (GicCCount-- != 0) {\r
+ DEBUG ((DEBUG_INFO, "SRAT: GicCAff = 0x%p\n", GicCAff));\r
+\r
+ GicCAff->Type = EFI_ACPI_6_3_GICC_AFFINITY;\r
+ GicCAff->Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE);\r
+ GicCAff->ProximityDomain = GicCInfo->ProximityDomain;\r
+ GicCAff->AcpiProcessorUid = GicCInfo->AcpiProcessorUid;\r
+ GicCAff->Flags = GicCInfo->AffinityFlags;\r
+ GicCAff->ClockDomain = GicCInfo->ClockDomain;\r
+\r
+ // Next\r
+ GicCAff++;\r
+ GicCInfo++;\r
+ }// while\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** Add the GIC ITS Affinity Structures in the SRAT Table.\r
+\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] Srat Pointer to the SRAT Table.\r
+ @param [in] GicItsAffOffset Offset of the GIC ITS Affinity\r
+ information in the SRAT Table.\r
+ @param [in] GicItsInfo Pointer to the GIC ITS Information list.\r
+ @param [in] GicItsCount Count of GIC ITS.\r
+\r
+ @retval EFI_SUCCESS Table generated successfully.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddGICItsAffinity (\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,\r
+ IN CONST UINT32 GicItsAffOffset,\r
+ IN CONST CM_ARM_GIC_ITS_INFO * GicItsInfo,\r
+ IN UINT32 GicItsCount\r
+ )\r
+{\r
+ EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE * GicItsAff;\r
+\r
+ ASSERT (Srat != NULL);\r
+ ASSERT (GicItsInfo != NULL);\r
+\r
+ GicItsAff = (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *)((UINT8*)Srat +\r
+ GicItsAffOffset);\r
+\r
+ while (GicItsCount-- != 0) {\r
+ DEBUG ((DEBUG_INFO, "SRAT: GicItsAff = 0x%p\n", GicItsAff));\r
+\r
+ GicItsAff->Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY;\r
+ GicItsAff->Length = sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE);\r
+ GicItsAff->ProximityDomain = GicItsInfo->ProximityDomain;\r
+ GicItsAff->Reserved[0] = EFI_ACPI_RESERVED_BYTE;\r
+ GicItsAff->Reserved[1] = EFI_ACPI_RESERVED_BYTE;\r
+ GicItsAff->ItsId = GicItsInfo->GicItsId;\r
+\r
+ // Next\r
+ GicItsAff++;\r
+ GicItsInfo++;\r
+ }// while\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** Add the Memory Affinity Structures in the SRAT Table.\r
+\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] Srat Pointer to the SRAT Table.\r
+ @param [in] MemAffOffset Offset of the Memory Affinity\r
+ information in the SRAT Table.\r
+ @param [in] MemAffInfo Pointer to the Memory Affinity Information list.\r
+ @param [in] MemAffCount Count of Memory Affinity objects.\r
+\r
+ @retval EFI_SUCCESS Table generated successfully.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddMemoryAffinity (\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,\r
+ IN CONST UINT32 MemAffOffset,\r
+ IN CONST CM_ARM_MEMORY_AFFINITY_INFO * MemAffInfo,\r
+ IN UINT32 MemAffCount\r
+ )\r
+{\r
+ EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE * MemAff;\r
+\r
+ ASSERT (Srat != NULL);\r
+ ASSERT (MemAffInfo != NULL);\r
+\r
+ MemAff = (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *)((UINT8*)Srat +\r
+ MemAffOffset);\r
+\r
+ while (MemAffCount-- != 0) {\r
+ DEBUG ((DEBUG_INFO, "SRAT: MemAff = 0x%p\n", MemAff));\r
+\r
+ MemAff->Type = EFI_ACPI_6_3_MEMORY_AFFINITY;\r
+ MemAff->Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE);\r
+ MemAff->ProximityDomain = MemAffInfo->ProximityDomain;\r
+ MemAff->Reserved1 = EFI_ACPI_RESERVED_WORD;\r
+ MemAff->AddressBaseLow = (UINT32)(MemAffInfo->BaseAddress & MAX_UINT32);\r
+ MemAff->AddressBaseHigh = (UINT32)(MemAffInfo->BaseAddress >> 32);\r
+ MemAff->LengthLow = (UINT32)(MemAffInfo->Length & MAX_UINT32);\r
+ MemAff->LengthHigh = (UINT32)(MemAffInfo->Length >> 32);\r
+ MemAff->Reserved2 = EFI_ACPI_RESERVED_DWORD;\r
+ MemAff->Flags = MemAffInfo->Flags;\r
+ MemAff->Reserved3 = EFI_ACPI_RESERVED_QWORD;\r
+\r
+ // Next\r
+ MemAff++;\r
+ MemAffInfo++;\r
+ }// while\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/** Add the Generic Initiator Affinity Structures in the SRAT Table.\r
+\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in] Srat Pointer to the SRAT Table.\r
+ @param [in] GenInitAffOff Offset of the Generic Initiator Affinity\r
+ information in the SRAT Table.\r
+ @param [in] GenInitAffInfo Pointer to the Generic Initiator Affinity\r
+ Information list.\r
+ @param [in] GenInitAffCount Count of Generic Initiator Affinity\r
+ objects.\r
+\r
+ @retval EFI_SUCCESS Table generated successfully.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND The required object information is not found.\r
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
+ Manager is less than the Object size for the\r
+ requested object.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+AddGenericInitiatorAffinity (\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * CONST Srat,\r
+ IN CONST UINT32 GenInitAffOff,\r
+ IN CONST CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO * GenInitAffInfo,\r
+ IN UINT32 GenInitAffCount\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE * GenInitAff;\r
+ CM_ARM_DEVICE_HANDLE_ACPI * DeviceHandleAcpi;\r
+ CM_ARM_DEVICE_HANDLE_PCI * DeviceHandlePci;\r
+ UINT32 DeviceHandleCount;\r
+\r
+ ASSERT (Srat != NULL);\r
+ ASSERT (GenInitAffInfo != NULL);\r
+\r
+ GenInitAff = (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE *)(\r
+ (UINT8*)Srat + GenInitAffOff);\r
+\r
+ while (GenInitAffCount-- != 0) {\r
+ DEBUG ((DEBUG_INFO, "SRAT: GenInitAff = 0x%p\n", GenInitAff));\r
+\r
+ GenInitAff->Type = EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY;\r
+ GenInitAff->Length =\r
+ sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE);\r
+ GenInitAff->Reserved1 = EFI_ACPI_RESERVED_WORD;\r
+ GenInitAff->DeviceHandleType = GenInitAffInfo->DeviceHandleType;\r
+ GenInitAff->ProximityDomain = GenInitAffInfo->ProximityDomain;\r
+\r
+ if (GenInitAffInfo->DeviceHandleToken == CM_NULL_TOKEN) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Invalid Device Handle Token.\n"\r
+ ));\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (GenInitAffInfo->DeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) {\r
+ Status = GetEArmObjDeviceHandleAcpi (\r
+ CfgMgrProtocol,\r
+ GenInitAffInfo->DeviceHandleToken,\r
+ &DeviceHandleAcpi,\r
+ &DeviceHandleCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to get ACPI Device Handle Inf."\r
+ " DeviceHandleToken = %p."\r
+ " Status = %r\n",\r
+ GenInitAffInfo->DeviceHandleToken,\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ // We are expecting only one device handle.\r
+ ASSERT (DeviceHandleCount == 1);\r
+\r
+ // Populate the ACPI device handle information.\r
+ GenInitAff->DeviceHandle.Acpi.AcpiHid = DeviceHandleAcpi->Hid;\r
+ GenInitAff->DeviceHandle.Acpi.AcpiUid = DeviceHandleAcpi->Uid;\r
+ GenInitAff->DeviceHandle.Acpi.Reserved[0] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Acpi.Reserved[1] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Acpi.Reserved[2] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Acpi.Reserved[3] = EFI_ACPI_RESERVED_BYTE;\r
+ } else if (GenInitAffInfo->DeviceHandleType ==\r
+ EFI_ACPI_6_3_PCI_DEVICE_HANDLE) {\r
+ Status = GetEArmObjDeviceHandlePci (\r
+ CfgMgrProtocol,\r
+ GenInitAffInfo->DeviceHandleToken,\r
+ &DeviceHandlePci,\r
+ &DeviceHandleCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to get ACPI Device Handle Inf."\r
+ " DeviceHandleToken = %p."\r
+ " Status = %r\n",\r
+ GenInitAffInfo->DeviceHandleToken,\r
+ Status\r
+ ));\r
+ return Status;\r
+ }\r
+\r
+ // We are expecting only one device handle\r
+ ASSERT (DeviceHandleCount == 1);\r
+\r
+ // Populate the ACPI device handle information.\r
+ GenInitAff->DeviceHandle.Pci.PciSegment = DeviceHandlePci->SegmentNumber;\r
+ GenInitAff->DeviceHandle.Pci.PciBdfNumber = GetBdf (DeviceHandlePci);\r
+\r
+ GenInitAff->DeviceHandle.Pci.Reserved[0] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[1] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[2] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[3] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[4] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[5] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[6] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[7] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[8] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[9] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[10] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->DeviceHandle.Pci.Reserved[11] = EFI_ACPI_RESERVED_BYTE;\r
+ } else {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Invalid Device Handle Type.\n"\r
+ ));\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ GenInitAff->Flags = GenInitAffInfo->Flags;\r
+ GenInitAff->Reserved2[0] = EFI_ACPI_RESERVED_BYTE;\r
+ GenInitAff->Reserved2[1] = EFI_ACPI_RESERVED_BYTE;\r
+\r
+ // Next\r
+ GenInitAff++;\r
+ GenInitAffInfo++;\r
+ }// while\r
+ return Status;\r
+}\r
+\r
+/** Construct the SRAT ACPI table.\r
+\r
+ Called by the Dynamic Table Manager, this function invokes the\r
+ Configuration Manager protocol interface to get the required hardware\r
+ information for generating the ACPI table.\r
+\r
+ If this function allocates any resources then they must be freed\r
+ in the FreeXXXXTableResources function.\r
+\r
+ @param [in] This Pointer to the table generator.\r
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [out] Table Pointer to the constructed ACPI Table.\r
+\r
+ @retval EFI_SUCCESS Table generated successfully.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND The required object was not found.\r
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
+ Manager is less than the Object size for the\r
+ requested object.\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+BuildSratTable (\r
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 TableSize;\r
+ UINT32 GicCCount;\r
+ UINT32 GicItsCount;\r
+ UINT32 MemAffCount;\r
+ UINT32 GenInitiatorAffCount;\r
+\r
+ UINT32 GicCAffOffset;\r
+ UINT32 GicItsAffOffset;\r
+ UINT32 MemAffOffset;\r
+ UINT32 GenInitiatorAffOffset;\r
+\r
+ CM_ARM_GICC_INFO * GicCInfo;\r
+ CM_ARM_GIC_ITS_INFO * GicItsInfo;\r
+ CM_ARM_MEMORY_AFFINITY_INFO * MemAffInfo;\r
+ CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO * GenInitiatorAffInfo;\r
+\r
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER * Srat;\r
+\r
+ ASSERT (\r
+ (This != NULL) &&\r
+ (AcpiTableInfo != NULL) &&\r
+ (CfgMgrProtocol != NULL) &&\r
+ (Table != NULL) &&\r
+ (AcpiTableInfo->TableGeneratorId == This->GeneratorID) &&\r
+ (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)\r
+ );\r
+\r
+ if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
+ (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Requested table revision = %d is not supported. "\r
+ "Supported table revisions: Minimum = %d. Maximum = %d\n",\r
+ AcpiTableInfo->AcpiTableRevision,\r
+ This->MinAcpiTableRevision,\r
+ This->AcpiTableRevision\r
+ ));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Table = NULL;\r
+\r
+ Status = GetEArmObjGicCInfo (\r
+ CfgMgrProtocol,\r
+ CM_NULL_TOKEN,\r
+ &GicCInfo,\r
+ &GicCCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to get GICC Info. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ if (GicCCount == 0) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: GIC CPU Interface information not provided.\n"\r
+ ));\r
+ ASSERT (0);\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto error_handler;\r
+ }\r
+\r
+ Status = GetEArmObjGicItsInfo (\r
+ CfgMgrProtocol,\r
+ CM_NULL_TOKEN,\r
+ &GicItsInfo,\r
+ &GicItsCount\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to get GIC ITS Info. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ Status = GetEArmObjMemoryAffinityInfo (\r
+ CfgMgrProtocol,\r
+ CM_NULL_TOKEN,\r
+ &MemAffInfo,\r
+ &MemAffCount\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to get Memory Affinity Info. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ Status = GetEArmObjGenericInitiatorAffinityInfo (\r
+ CfgMgrProtocol,\r
+ CM_NULL_TOKEN,\r
+ &GenInitiatorAffInfo,\r
+ &GenInitiatorAffCount\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to get Generic Initiator Affinity Info."\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ // Calculate the size of the SRAT table\r
+ TableSize = sizeof (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER);\r
+\r
+ GicCAffOffset = TableSize;\r
+ TableSize += (sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) * GicCCount);\r
+\r
+ if (GicItsCount != 0) {\r
+ GicItsAffOffset = TableSize;\r
+ TableSize += (sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE) *\r
+ GicItsCount);\r
+ }\r
+\r
+ if (MemAffCount != 0) {\r
+ MemAffOffset = TableSize;\r
+ TableSize += (sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) *\r
+ MemAffCount);\r
+ }\r
+\r
+ if (GenInitiatorAffCount != 0) {\r
+ GenInitiatorAffOffset = TableSize;\r
+ TableSize += (sizeof (EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY_STRUCTURE) *\r
+ GenInitiatorAffCount);\r
+ }\r
+\r
+ // Allocate the Buffer for SRAT table\r
+ *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);\r
+ if (*Table == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to allocate memory for SRAT Table, Size = %d," \\r
+ " Status = %r\n",\r
+ TableSize,\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ Srat = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER*)*Table;\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "SRAT: Srat = 0x%p TableSize = 0x%x\n",\r
+ Srat,\r
+ TableSize\r
+ ));\r
+\r
+ Status = AddAcpiHeader (\r
+ CfgMgrProtocol,\r
+ This,\r
+ &Srat->Header,\r
+ AcpiTableInfo,\r
+ TableSize\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to add ACPI header. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ // Setup the Reserved fields\r
+ // Reserved1 must be set to 1 for backward compatibility\r
+ Srat->Reserved1 = 1;\r
+ Srat->Reserved2 = EFI_ACPI_RESERVED_QWORD;\r
+\r
+ Status = AddGICCAffinity (\r
+ CfgMgrProtocol,\r
+ Srat,\r
+ GicCAffOffset,\r
+ GicCInfo,\r
+ GicCCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to add GICC Affinity structures. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+\r
+ if (GicItsCount != 0) {\r
+ Status = AddGICItsAffinity (\r
+ CfgMgrProtocol,\r
+ Srat,\r
+ GicItsAffOffset,\r
+ GicItsInfo,\r
+ GicItsCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to add GIC ITS Affinity structures. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+ }\r
+\r
+ if (MemAffCount != 0) {\r
+ Status = AddMemoryAffinity (\r
+ CfgMgrProtocol,\r
+ Srat,\r
+ MemAffOffset,\r
+ MemAffInfo,\r
+ MemAffCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to add Memory Affinity structures. Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+ }\r
+\r
+ if (GenInitiatorAffCount != 0) {\r
+ Status = AddGenericInitiatorAffinity (\r
+ CfgMgrProtocol,\r
+ Srat,\r
+ GenInitiatorAffOffset,\r
+ GenInitiatorAffInfo,\r
+ GenInitiatorAffCount\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((\r
+ DEBUG_ERROR,\r
+ "ERROR: SRAT: Failed to add Generic Initiator Affinity structures."\r
+ " Status = %r\n",\r
+ Status\r
+ ));\r
+ goto error_handler;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+\r
+error_handler:\r
+\r
+ if (*Table != NULL) {\r
+ FreePool (*Table);\r
+ *Table = NULL;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** Free any resources allocated for constructing the SRAT.\r
+\r
+ @param [in] This Pointer to the table generator.\r
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
+ Protocol Interface.\r
+ @param [in, out] Table Pointer to the ACPI Table.\r
+\r
+ @retval EFI_SUCCESS The resources were freed successfully.\r
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+FreeSratTableResources (\r
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
+ )\r
+{\r
+ ASSERT (\r
+ (This != NULL) &&\r
+ (AcpiTableInfo != NULL) &&\r
+ (CfgMgrProtocol != NULL) &&\r
+ (AcpiTableInfo->TableGeneratorId == This->GeneratorID) &&\r
+ (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature)\r
+ );\r
+\r
+ if ((Table == NULL) || (*Table == NULL)) {\r
+ DEBUG ((DEBUG_ERROR, "ERROR: SRAT: Invalid Table Pointer\n"));\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ FreePool (*Table);\r
+ *Table = NULL;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** The SRAT Table Generator revision.\r
+*/\r
+#define SRAT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
+\r
+/** The interface for the SRAT Table Generator.\r
+*/\r
+STATIC\r
+CONST\r
+ACPI_TABLE_GENERATOR SratGenerator = {\r
+ // Generator ID\r
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSrat),\r
+ // Generator Description\r
+ L"ACPI.STD.SRAT.GENERATOR",\r
+ // ACPI Table Signature\r
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE,\r
+ // ACPI Table Revision supported by this Generator\r
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION,\r
+ // Minimum supported ACPI Table Revision\r
+ EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION,\r
+ // Creator ID\r
+ TABLE_GENERATOR_CREATOR_ID_ARM,\r
+ // Creator Revision\r
+ SRAT_GENERATOR_REVISION,\r
+ // Build Table function\r
+ BuildSratTable,\r
+ // Free Resource function\r
+ FreeSratTableResources,\r
+ // Extended build function not needed\r
+ NULL,\r
+ // Extended build function not implemented by the generator.\r
+ // Hence extended free resource function is not required.\r
+ NULL\r
+};\r
+\r
+/** Register the Generator with the ACPI Table Factory.\r
+\r
+ @param [in] ImageHandle The handle to the image.\r
+ @param [in] SystemTable Pointer to the System Table.\r
+\r
+ @retval EFI_SUCCESS The Generator is registered.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
+ is already registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiSratLibConstructor (\r
+ IN CONST EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE * CONST SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ Status = RegisterAcpiTableGenerator (&SratGenerator);\r
+ DEBUG ((DEBUG_INFO, "SRAT: Register Generator. Status = %r\n", Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+}\r
+\r
+/** Deregister the Generator from the ACPI Table Factory.\r
+\r
+ @param [in] ImageHandle The handle to the image.\r
+ @param [in] SystemTable Pointer to the System Table.\r
+\r
+ @retval EFI_SUCCESS The Generator is deregistered.\r
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
+ @retval EFI_NOT_FOUND The Generator is not registered.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiSratLibDestructor (\r
+ IN CONST EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE * CONST SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ Status = DeregisterAcpiTableGenerator (&SratGenerator);\r
+ DEBUG ((DEBUG_INFO, "SRAT: Deregister Generator. Status = %r\n", Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+}\r