diff --git a/BaseTools/.gitignore b/BaseTools/.gitignore index a45689bc89..ec9c69f8b2 100644 --- a/BaseTools/.gitignore +++ b/BaseTools/.gitignore @@ -17,4 +17,5 @@ Source/C/VfrCompile/VfrTokens.h Source/C/bin/ Source/C/libs/ Bin/Win32 -Lib \ No newline at end of file +Lib +BaseToolsBuild/ \ No newline at end of file diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c index ed62299f9b..1642d6c387 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c @@ -8,9 +8,11 @@ **/ #include +#include #include #include #include +#include // Module specific include files. #include @@ -31,6 +33,18 @@ GET_OBJECT_LIST ( CM_STD_OBJ_ACPI_TABLE_INFO ) +/** This macro expands to a function that retrieves the SMBIOS Table + List from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceStandard, + EStdObjSmbiosTableList, + CM_STD_OBJ_SMBIOS_TABLE_INFO + ) + +STATIC VOID *AcpiTableProtocolRegistration; +STATIC VOID *SmbiosProtocolRegistration; + /** A helper function to build and install a single ACPI table. This is a helper function that invokes the Table generator interface @@ -478,6 +492,449 @@ VerifyMandatoryTablesArePresent ( return Status; } +/** A helper function to build and install an SMBIOS table. + + This is a helper function that invokes the Table generator interface + for building an SMBIOS table. It uses the SmbiosProtocol to install the + table, then frees the resources allocated for generating it. + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Required object is not found. + @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager + is less than the Object size for the + requested object. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildAndInstallSingleSmbiosTable ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST SMBIOS_TABLE_GENERATOR *CONST Generator, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + SMBIOS_STRUCTURE *SmbiosTable; + EFI_SMBIOS_HANDLE TableHandle; + + SmbiosTable = NULL; + Status = Generator->BuildSmbiosTable ( + Generator, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Build Table." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + if (SmbiosTable == NULL) { + Status = EFI_NOT_FOUND; + goto exit_handler; + } + + TableHandle = SMBIOS_HANDLE_PI_RESERVED; + // Install SMBIOS table + Status = SmbiosProtocol->Add ( + SmbiosProtocol, + NULL, + &TableHandle, + SmbiosTable + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Install SMBIOS Table. Status = %r\n", + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + DEBUG (( + DEBUG_INFO, + "INFO: SMBIOS Table installed. Status = %r\n", + Status + )); + +exit_handler: + // Free any resources allocated for generating the tables. + if (Generator->FreeTableResources != NULL) { + Status1 = Generator->FreeTableResources ( + Generator, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable + ); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Free Table Resources." \ + "TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status1 + )); + } + + // Return the first error status in case of failure + if (!EFI_ERROR (Status)) { + Status = Status1; + } + } + + return Status; +} + +/** A helper function to build and install multiple SMBIOS tables. + + This is a helper function that invokes the Table generator interface + for building SMBIOS tables. It uses the SmbiosProtocol to install the + tables, then frees the resources allocated for generating it. + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] Generator Pointer to the SmbiosTable generator. + @param [in] SmbiosProtocol Pointer to the Smbios protocol. + @param [in] AcpiTableInfo Pointer to the SMBIOS table Info. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Required object is not found. + @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager + is less than the Object size for the + requested object. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildAndInstallMultipleSmbiosTables ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST SMBIOS_TABLE_GENERATOR *CONST Generator, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + SMBIOS_STRUCTURE **SmbiosTable; + EFI_SMBIOS_HANDLE TableHandle; + UINTN TableCount; + UINTN Index; + + TableCount = 0; + Status = Generator->BuildSmbiosTableEx ( + Generator, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable, + &TableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Build Table." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + if ((SmbiosTable == NULL) || (TableCount == 0)) { + Status = EFI_NOT_FOUND; + DEBUG (( + DEBUG_ERROR, + "%a: TableCount %u SmbiosTable %p \n", + __FUNCTION__, + TableCount, + SmbiosTable + )); + goto exit_handler; + } + + for (Index = 0; Index < TableCount; Index++) { + TableHandle = SMBIOS_HANDLE_PI_RESERVED; + // Install SMBIOS table + Status = SmbiosProtocol->Add ( + SmbiosProtocol, + NULL, + &TableHandle, + SmbiosTable[Index] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Install SMBIOS Table. Status = %r\n", + Status + )); + // Free any allocated resources. + goto exit_handler; + } + + DEBUG (( + DEBUG_INFO, + "INFO: SMBIOS Table installed. Status = %r\n", + Status + )); + } + +exit_handler: + // Free any resources allocated for generating the tables. + if (Generator->FreeTableResourcesEx != NULL) { + Status1 = Generator->FreeTableResourcesEx ( + Generator, + SmbiosTableInfo, + CfgMgrProtocol, + &SmbiosTable, + TableCount + ); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to Free Table Resources." \ + "TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status1 + )); + } + + // Return the first error status in case of failure + if (!EFI_ERROR (Status)) { + Status = Status1; + } + } + + return Status; +} + +/** A helper function to invoke a Table generator + + This is a helper function that invokes the Table generator interface + for building an SMBIOS table. It uses the SmbiosProtocol to install the + table, then frees the resources allocated for generating it. + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] SmbiosProtocol Pointer to the SMBIOS protocol. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table Info. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Required object is not found. + @retval EFI_BAD_BUFFER_SIZE Size returned by the Configuration Manager + is less than the Object size for the + requested object. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildAndInstallSmbiosTable ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_SMBIOS_PROTOCOL *SmbiosProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo + ) +{ + EFI_STATUS Status; + CONST SMBIOS_TABLE_GENERATOR *Generator; + + ASSERT (TableFactoryProtocol != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (SmbiosProtocol != NULL); + ASSERT (SmbiosTableInfo != NULL); + + DEBUG (( + DEBUG_INFO, + "INFO: EStdObjSmbiosTableList: Address = 0x%p," \ + " TableGeneratorId = 0x%x\n", + SmbiosTableInfo, + SmbiosTableInfo->TableGeneratorId + )); + + Generator = NULL; + Status = TableFactoryProtocol->GetSmbiosTableGenerator ( + TableFactoryProtocol, + SmbiosTableInfo->TableGeneratorId, + &Generator + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Table Generator not found." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + return Status; + } + + if (Generator == NULL) { + return EFI_NOT_FOUND; + } + + DEBUG (( + DEBUG_INFO, + "INFO: Generator found : %s\n", + Generator->Description + )); + + if (Generator->BuildSmbiosTableEx != NULL) { + Status = BuildAndInstallMultipleSmbiosTables ( + TableFactoryProtocol, + CfgMgrProtocol, + Generator, + SmbiosProtocol, + SmbiosTableInfo + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to find build and install SMBIOS Tables." \ + " Status = %r\n", + Status + )); + } + } else if (Generator->BuildSmbiosTable != NULL) { + Status = BuildAndInstallSingleSmbiosTable ( + TableFactoryProtocol, + CfgMgrProtocol, + Generator, + SmbiosProtocol, + SmbiosTableInfo + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to find build and install SMBIOS Table." \ + " Status = %r\n", + Status + )); + } + } else { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: Table Generator does not implement the" \ + "SMBIOS_TABLE_GENERATOR_BUILD_TABLE interface." \ + " TableGeneratorId = 0x%x. Status = %r\n", + SmbiosTableInfo->TableGeneratorId, + Status + )); + } + + return Status; +} + +/** Generate and install SMBIOS tables. + + The function gathers the information necessary for installing the + SMBIOS tables from the Configuration Manager, invokes the generators + and installs them (via BuildAndInstallAcpiTable). + + @param [in] TableFactoryProtocol Pointer to the Table Factory Protocol + interface. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + + @retval EFI_SUCCESS Success. + @retval EFI_NOT_FOUND If a mandatory table or a generator is not found. +**/ +STATIC +EFI_STATUS +EFIAPI +ProcessSmbiosTables ( + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_PROTOCOL *SmbiosProtocol; + CM_STD_OBJ_SMBIOS_TABLE_INFO *SmbiosTableInfo; + UINT32 SmbiosTableCount; + UINT32 Idx; + + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&SmbiosProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status)); + return Status; + } + + Status = GetEStdObjSmbiosTableList ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &SmbiosTableInfo, + &SmbiosTableCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to get SMBIOS Table List. Status = %r\n", + Status + )); + return Status; + } + + if (SmbiosTableCount == 0) { + DEBUG (( + DEBUG_ERROR, + "ERROR: EStdObjSmbiosTableList: SmbiosTableCount = %d\n", + SmbiosTableCount + )); + return EFI_NOT_FOUND; + } + + DEBUG (( + DEBUG_INFO, + "INFO: EStdObjSmbiosTableList: SmbiosTableCount = %d\n", + SmbiosTableCount + )); + + for (Idx = 0; Idx < SmbiosTableCount; Idx++) { + Status = BuildAndInstallSmbiosTable ( + TableFactoryProtocol, + CfgMgrProtocol, + SmbiosProtocol, + &SmbiosTableInfo[Idx] + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to install SMBIOS Table." \ + " Id = %u Status = %r\n", + SmbiosTableInfo[Idx].TableGeneratorId, + Status + )); + } + } + + return Status; +} + /** Generate and install ACPI tables. The function gathers the information necessary for installing the @@ -664,11 +1121,11 @@ ProcessAcpiTables ( @retval EFI_NOT_FOUND Required interface/object was not found. @retval EFI_INVALID_PARAMETER Some parameter is incorrect/invalid. **/ -EFI_STATUS -EFIAPI -DynamicTableManagerDxeInitialize ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable +STATIC +VOID +AcpiTableProtocolReady ( + IN EFI_EVENT Event, + IN VOID *Context ) { EFI_STATUS Status; @@ -689,7 +1146,7 @@ DynamicTableManagerDxeInitialize ( " Status = %r\n", Status )); - return Status; + return; } // Locate the Configuration Manager for the Platform @@ -704,7 +1161,7 @@ DynamicTableManagerDxeInitialize ( "ERROR: Failed to find Configuration Manager protocol. Status = %r\n", Status )); - return Status; + return; } Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo); @@ -714,7 +1171,7 @@ DynamicTableManagerDxeInitialize ( "ERROR: Failed to get Configuration Manager info. Status = %r\n", Status )); - return Status; + return; } DEBUG (( @@ -737,6 +1194,118 @@ DynamicTableManagerDxeInitialize ( Status )); } +} + +STATIC +VOID +SmbiosProtocolReady ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EDKII_CONFIGURATION_MANAGER_PROTOCOL *CfgMgrProtocol; + CM_STD_OBJ_CONFIGURATION_MANAGER_INFO *CfgMfrInfo; + EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *TableFactoryProtocol; + + // Locate the Dynamic Table Factory + Status = gBS->LocateProtocol ( + &gEdkiiDynamicTableFactoryProtocolGuid, + NULL, + (VOID **)&TableFactoryProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to find Dynamic Table Factory protocol." \ + " Status = %r\n", + Status + )); + return; + } + + // Locate the Configuration Manager for the Platform + Status = gBS->LocateProtocol ( + &gEdkiiConfigurationManagerProtocolGuid, + NULL, + (VOID **)&CfgMgrProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to find Configuration Manager protocol. Status = %r\n", + Status + )); + return; + } + + Status = GetCgfMgrInfo (CfgMgrProtocol, &CfgMfrInfo); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: Failed to get Configuration Manager info. Status = %r\n", + Status + )); + return; + } + + DEBUG (( + DEBUG_INFO, + "INFO: Configuration Manager Version = 0x%x, OemID = %c%c%c%c%c%c\n", + CfgMfrInfo->Revision, + CfgMfrInfo->OemId[0], + CfgMfrInfo->OemId[1], + CfgMfrInfo->OemId[2], + CfgMfrInfo->OemId[3], + CfgMfrInfo->OemId[4], + CfgMfrInfo->OemId[5] + )); + + Status = ProcessSmbiosTables (TableFactoryProtocol, CfgMgrProtocol); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SMBIOS Table processing failure. Status = %r\n", + Status + )); + } +} + +EFI_STATUS +EFIAPI +DynamicTableManagerDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT AcpiEvent; + EFI_EVENT SmbiosEvent; + + AcpiEvent = EfiCreateProtocolNotifyEvent ( + &gEfiAcpiTableProtocolGuid, + TPL_CALLBACK, + AcpiTableProtocolReady, + NULL, + &AcpiTableProtocolRegistration + ); + if (AcpiEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Failed to ACPI create protocol event\r\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + SmbiosEvent = EfiCreateProtocolNotifyEvent ( + &gEfiSmbiosProtocolGuid, + TPL_CALLBACK, + SmbiosProtocolReady, + NULL, + &SmbiosProtocolRegistration + ); + if (SmbiosEvent == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Failed to SMBIOS create protocol event\r\n", __FUNCTION__)); + gBS->CloseEvent (AcpiEvent); + return EFI_OUT_OF_RESOURCES; + } return Status; } diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf index 028c3d413c..aa4050a3e9 100644 --- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf +++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf @@ -31,17 +31,18 @@ [LibraryClasses] PrintLib TableHelperLib + UefiLib UefiBootServicesTableLib UefiDriverEntryPoint [Protocols] gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEdkiiConfigurationManagerProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEdkiiDynamicTableFactoryProtocolGuid # PROTOCOL ALWAYS_CONSUMED [Depex] - gEfiAcpiTableProtocolGuid AND gEdkiiConfigurationManagerProtocolGuid AND gEdkiiDynamicTableFactoryProtocolGuid diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 60bcf4b199..3d4fa0c4c4 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -15,6 +15,7 @@ [LibraryClasses.common] AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + SsdtPcieSupportLib|DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec index 9b74c5a671..cc34c2bdd6 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -30,6 +30,9 @@ ## @libraryclass Defines a set of APIs to a hardware information parser. HwInfoParserLib|Include/Library/HwInfoParserLib.h + ## @libraryclass Defines functions for customizing the generation of _OSC and slot info. + SsdtPcieSupportLib|Include/Library/SsdtPcieSupportLib.h + ## @libraryclass Defines a set of methods for fixing up a SSDT Serial Port. SsdtSerialPortFixupLib|Include/Library/SsdtSerialPortFixupLib.h diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc index 068f0bc630..07cc837552 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -41,6 +41,7 @@ [Components.common] DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h index 91bef9bccd..2507203c22 100644 --- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h +++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h @@ -61,6 +61,7 @@ typedef enum ArmObjectID { EArmObjLpiInfo, ///< 37 - Lpi Info EArmObjPciAddressMapInfo, ///< 38 - Pci Address Map Info EArmObjPciInterruptMapInfo, ///< 39 - Pci Interrupt Map Info + EArmObjMemoryDeviceInfo, ///< 40 - Memory Device Information EArmObjMax } EARM_OBJECT_ID; @@ -1006,6 +1007,64 @@ typedef struct CmArmPciInterruptMapInfo { CM_ARM_GENERIC_INTERRUPT IntcInterrupt; } CM_ARM_PCI_INTERRUPT_MAP_INFO; +/** A structure that describes the physical memory device. + + The physical memory devices on the system are described by this object. + + SMBIOS Specification v3.5.0 Type17 + + ID: EArmObjMemoryDeviceInfo, +*/ +typedef struct CmArmMemoryDeviceInfo { + /** Size of the device. + Size of the device in bytes. + */ + UINT64 Size; + + /** Device Set */ + UINT8 DeviceSet; + + /** Speed of the device + Speed of the device in MegaTransfers/second. + */ + UINT32 Speed; + + /** Serial Number of device */ + CHAR8 *SerialNum; + + /** AssetTag identifying the device */ + CHAR8 *AssetTag; + + /** Device Locator String for the device. + String that describes the slot or position of the device on the board. + */ + CHAR8 *DeviceLocator; + + /** Bank locator string for the device. + String that describes the bank where the device is located. + */ + CHAR8 *BankLocator; + + /** Firmware version of the memory device */ + CHAR8 *FirmwareVersion; + + /** Manufacturer Id. + 2 byte Manufacturer Id as per JEDEC Standard JEP106AV + */ + UINT16 ModuleManufacturerId; + + /** Manufacturer Product Id + 2 byte Manufacturer Id as designated by Manufacturer. + */ + UINT16 ModuleProductId; + + /** Device Attributes */ + UINT8 Attributes; + + /** Device Configured Voltage in millivolts */ + UINT16 ConfiguredVoltage; +} CM_ARM_MEMORY_DEVICE_INFO; + #pragma pack() #endif // ARM_NAMESPACE_OBJECTS_H_ diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h index 6f214c0dfa..18013f3c0c 100644 --- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h +++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h @@ -1280,6 +1280,66 @@ AmlAddLpiState ( IN AML_OBJECT_NODE_HANDLE LpiNode ); +/** AML code generation for a _DSD device data object. + + AmlAddDeviceDataDescriptorPackage (Uuid, DsdNode, PackageNode) is + equivalent of the following ASL code: + ToUUID(Uuid), + Package () {} + + Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)". + + _DSD (Device Specific Data) Implementation Guide + https://github.com/UEFI/DSD-Guide + Per s3. "'Well-Known _DSD UUIDs and Data Structure Formats'" + If creating a Device Properties data then UUID daffd814-6eba-4d8c-8a91-bc9bbf4aa301 should be used. + + @ingroup CodeGenApis + + @param [in] Uuid The Uuid of the descriptor to be created + @param [in] DsdNode Node of the DSD Package. + @param [out] PackageNode If success, contains the created package node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlAddDeviceDataDescriptorPackage ( + IN CONST EFI_GUID *Uuid, + IN AML_OBJECT_NODE_HANDLE DsdNode, + OUT AML_OBJECT_NODE_HANDLE *PackageNode + ); + +/** AML code generation to add a package with a name and value, + to a parent package. + This is useful for build the _DSD package but can be used in other cases. + + AmlAddNameValuePackage ("Name", Value, PackageNode) is + equivalent of the following ASL code: + Package (2) {"Name", Value} + + Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)". + + @ingroup CodeGenApis + + @param [in] Name String to place in first entry of package + @param [in] Value Integer to place in second entry of package + @param [in] PackageNode Package to add new sub package to. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlAddNameIntegerPackage ( + IN CHAR8 *Name, + IN UINT64 Value, + IN AML_OBJECT_NODE_HANDLE PackageNode + ); + // DEPRECATED APIS #ifndef DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h b/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h new file mode 100644 index 0000000000..4171dabc33 --- /dev/null +++ b/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h @@ -0,0 +1,75 @@ +/** @file + Ssdt PCIe Support Library + + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef SSDT_PCIE_SUPPORT_LIB_H_ +#define SSDT_PCIE_SUPPORT_LIB_H_ + +#pragma pack(1) + +/** Structure used to map integer to an index. +*/ +typedef struct MappingTable { + /// Mapping table. + /// Contains the Index <-> integer mapping + UINT32 *Table; + + /// Last used index of the Table. + /// Bound by MaxIndex. + UINT32 LastIndex; + + /// Number of entries in the Table. + UINT32 MaxIndex; +} MAPPING_TABLE; + +#pragma pack() + +/** Add an _OSC template method to the PciNode. + + The _OSC method is provided as an AML blob. The blob is + parsed and attached at the end of the PciNode list of variable elements. + + @param [in] PciInfo Pci device information. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AddOscMethod ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ); + +/** Generate Pci slots devices. + + PCI Firmware Specification - Revision 3.3, + s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot + used. It should be possible to enumerate them, but this is additional + information. + + @param [in] PciInfo Pci device information. + @param [in] MappingTable The mapping table structure. + @param [in] Uid Unique Id of the Pci device. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +GeneratePciSlots ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN CONST MAPPING_TABLE *MappingTable, + IN UINT32 Uid, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ); + +#endif // SSDT_PCIE_SUPPORT_LIB_H_ diff --git a/DynamicTablesPkg/Include/SmbiosTableGenerator.h b/DynamicTablesPkg/Include/SmbiosTableGenerator.h index 934d56c90d..7bf6300d90 100644 --- a/DynamicTablesPkg/Include/SmbiosTableGenerator.h +++ b/DynamicTablesPkg/Include/SmbiosTableGenerator.h @@ -168,6 +168,48 @@ typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLE) ( IN SMBIOS_STRUCTURE **Table ); +/** This function pointer describes the interface to SMBIOS table build + functions provided by the SMBIOS table generator and called by the + Table Manager to build an SMBIOS table. + + @param [in] Generator Pointer to the SMBIOS table generator. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to the generated SMBIOS table. + + @return EFI_SUCCESS If the table is generated successfully or other + failure codes as returned by the generator. +**/ +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_BUILD_TABLEEX) ( + IN CONST SMBIOS_TABLE_GENERATOR *Generator, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT SMBIOS_STRUCTURE ***Table, + OUT UINTN *CONST TableCount + ); + +/** This function pointer describes the interface to used by the + Table Manager to give the generator an opportunity to free + any resources allocated for building the SMBIOS table. + + @param [in] Generator Pointer to the SMBIOS table generator. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [in] Table Pointer to the generated SMBIOS table. + + @return EFI_SUCCESS If freed successfully or other failure codes + as returned by the generator. +**/ +typedef EFI_STATUS (*SMBIOS_TABLE_GENERATOR_FREE_TABLEEX) ( + IN CONST SMBIOS_TABLE_GENERATOR *Generator, + IN CONST CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN SMBIOS_STRUCTURE ***Table, + IN CONST UINTN TableCount + ); + /** The SMBIOS_TABLE_GENERATOR structure provides an interface that the Table Manager can use to invoke the functions to build SMBIOS tables. */ @@ -189,6 +231,14 @@ typedef struct SmbiosTableGenerator { allocated for building the SMBIOS table. */ SMBIOS_TABLE_GENERATOR_FREE_TABLE FreeTableResources; + + /// SMBIOS table extended build function pointer. + SMBIOS_TABLE_GENERATOR_BUILD_TABLEEX BuildSmbiosTableEx; + + /** The function to free any resources + allocated for building the SMBIOS table. + */ + SMBIOS_TABLE_GENERATOR_FREE_TABLEEX FreeTableResourcesEx; } SMBIOS_TABLE_GENERATOR; /** Register SMBIOS table factory generator. diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c index 3266d8dd98..8561f48e1f 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyGenerator.c @@ -587,10 +587,10 @@ CreateAmlCpuFromProcHierarchy ( return Status; } -/** Create a Cluster in the AML namespace. +/** Create a Processor Container in the AML namespace. Any CM_ARM_PROC_HIERARCHY_INFO object with the following flags is - assumed to be a cluster: + assumed to be a processor container: - EFI_ACPI_6_3_PPTT_PACKAGE_NOT_PHYSICAL - EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID - EFI_ACPI_6_3_PPTT_NODE_IS_NOT_LEAF @@ -605,13 +605,13 @@ CreateAmlCpuFromProcHierarchy ( @param [in] Generator The SSDT Cpu Topology generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. - @param [in] ParentNode Parent node to attach the Cluster - node to. + @param [in] ParentNode Parent node to attach the processor + container node to. @param [in] ProcHierarchyNodeInfo CM_ARM_PROC_HIERARCHY_INFO object used to create the node. - @param [in] ClusterIndex Index used to generate the node name. - @param [out] ClusterNodePtr If success, contains the created Cluster - node. + @param [in] ProcContainerIndex Index used to generate the node name. + @param [out] ProcContainerNodePtr If success, contains the created processor + container node. @retval EFI_SUCCESS Success. @retval EFI_INVALID_PARAMETER Invalid parameter. @@ -620,43 +620,43 @@ CreateAmlCpuFromProcHierarchy ( STATIC EFI_STATUS EFIAPI -CreateAmlCluster ( +CreateAmlProcessorContainer ( IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN AML_NODE_HANDLE ParentNode, IN CM_ARM_PROC_HIERARCHY_INFO *ProcHierarchyNodeInfo, - IN UINT32 ClusterIndex, - OUT AML_OBJECT_NODE_HANDLE *ClusterNodePtr + IN UINT32 ProcContainerIndex, + OUT AML_OBJECT_NODE_HANDLE *ProcContainerNodePtr ) { EFI_STATUS Status; - AML_OBJECT_NODE_HANDLE ClusterNode; - CHAR8 AslNameCluster[AML_NAME_SEG_SIZE + 1]; + AML_OBJECT_NODE_HANDLE ProcContainerNode; + CHAR8 AslNameProcContainer[AML_NAME_SEG_SIZE + 1]; ASSERT (Generator != NULL); ASSERT (CfgMgrProtocol != NULL); ASSERT (ParentNode != NULL); ASSERT (ProcHierarchyNodeInfo != NULL); - ASSERT (ClusterNodePtr != NULL); + ASSERT (ProcContainerNodePtr != NULL); - Status = WriteAslName ('C', ClusterIndex, AslNameCluster); + Status = WriteAslName ('C', ProcContainerIndex, AslNameProcContainer); if (EFI_ERROR (Status)) { ASSERT (0); return Status; } - Status = AmlCodeGenDevice (AslNameCluster, ParentNode, &ClusterNode); + Status = AmlCodeGenDevice (AslNameProcContainer, ParentNode, &ProcContainerNode); if (EFI_ERROR (Status)) { ASSERT (0); return Status; } - // Use the ClusterIndex for the _UID value as there is no AcpiProcessorUid + // Use the ProcContainerIndex for the _UID value as there is no AcpiProcessorUid // and EFI_ACPI_6_3_PPTT_PROCESSOR_ID_INVALID is set for non-Cpus. Status = AmlCodeGenNameInteger ( "_UID", - ClusterIndex, - ClusterNode, + ProcContainerIndex, + ProcContainerNode, NULL ); if (EFI_ERROR (Status)) { @@ -667,7 +667,7 @@ CreateAmlCluster ( Status = AmlCodeGenNameString ( "_HID", ACPI_HID_PROCESSOR_CONTAINER_DEVICE, - ClusterNode, + ProcContainerNode, NULL ); if (EFI_ERROR (Status)) { @@ -681,7 +681,7 @@ CreateAmlCluster ( Status = CreateAmlLpiMethod ( Generator, ProcHierarchyNodeInfo, - ClusterNode + ProcContainerNode ); if (EFI_ERROR (Status)) { ASSERT (0); @@ -689,23 +689,25 @@ CreateAmlCluster ( } } - *ClusterNodePtr = ClusterNode; + *ProcContainerNodePtr = ProcContainerNode; return Status; } /** Create an AML representation of the Cpu topology. - A cluster is by extension any non-leave device in the cpu topology. + A processor container is by extension any non-leave device in the cpu topology. - @param [in] Generator The SSDT Cpu Topology generator. - @param [in] CfgMgrProtocol Pointer to the Configuration Manager - Protocol Interface. - @param [in] NodeToken Token of the CM_ARM_PROC_HIERARCHY_INFO - currently handled. - Cannot be CM_NULL_TOKEN. - @param [in] ParentNode Parent node to attach the created - node to. + @param [in] Generator The SSDT Cpu Topology generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] NodeToken Token of the CM_ARM_PROC_HIERARCHY_INFO + currently handled. + Cannot be CM_NULL_TOKEN. + @param [in] ParentNode Parent node to attach the created + node to. + @param [in,out] ProcContainerIndex Pointer to the current processor container + index to be used as UID. @retval EFI_SUCCESS Success. @retval EFI_INVALID_PARAMETER Invalid parameter. @@ -718,14 +720,14 @@ CreateAmlCpuTopologyTree ( IN ACPI_CPU_TOPOLOGY_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CM_OBJECT_TOKEN NodeToken, - IN AML_NODE_HANDLE ParentNode + IN AML_NODE_HANDLE ParentNode, + IN OUT UINT32 *ProcContainerIndex ) { EFI_STATUS Status; UINT32 Index; UINT32 CpuIndex; - UINT32 ClusterIndex; - AML_OBJECT_NODE_HANDLE ClusterNode; + AML_OBJECT_NODE_HANDLE ProcContainerNode; ASSERT (Generator != NULL); ASSERT (Generator->ProcNodeList != NULL); @@ -733,9 +735,9 @@ CreateAmlCpuTopologyTree ( ASSERT (CfgMgrProtocol != NULL); ASSERT (NodeToken != CM_NULL_TOKEN); ASSERT (ParentNode != NULL); + ASSERT (ProcContainerIndex != NULL); - CpuIndex = 0; - ClusterIndex = 0; + CpuIndex = 0; for (Index = 0; Index < Generator->ProcNodeCount; Index++) { // Find the children of the CM_ARM_PROC_HIERARCHY_INFO @@ -770,7 +772,7 @@ CreateAmlCpuTopologyTree ( CpuIndex++; } else { - // If this is not a Cpu, then this is a cluster. + // If this is not a Cpu, then this is a processor container. // Acpi processor Id for clusters is not handled. if ((Generator->ProcNodeList[Index].Flags & PPTT_PROCESSOR_MASK) != @@ -785,13 +787,13 @@ CreateAmlCpuTopologyTree ( return EFI_INVALID_PARAMETER; } - Status = CreateAmlCluster ( + Status = CreateAmlProcessorContainer ( Generator, CfgMgrProtocol, ParentNode, &Generator->ProcNodeList[Index], - ClusterIndex, - &ClusterNode + *ProcContainerIndex, + &ProcContainerNode ); if (EFI_ERROR (Status)) { ASSERT (0); @@ -799,8 +801,8 @@ CreateAmlCpuTopologyTree ( } // Nodes must have a unique name in the ASL namespace. - // Reset the Cpu index whenever we create a new Cluster. - ClusterIndex++; + // Reset the Cpu index whenever we create a new processor container. + (*ProcContainerIndex)++; CpuIndex = 0; // Recursively continue creating an AML tree. @@ -808,7 +810,8 @@ CreateAmlCpuTopologyTree ( Generator, CfgMgrProtocol, Generator->ProcNodeList[Index].Token, - ClusterNode + ProcContainerNode, + ProcContainerIndex ); if (EFI_ERROR (Status)) { ASSERT (0); @@ -845,6 +848,7 @@ CreateTopologyFromProcHierarchy ( EFI_STATUS Status; UINT32 Index; UINT32 TopLevelProcNodeIndex; + UINT32 ProcContainerIndex; ASSERT (Generator != NULL); ASSERT (Generator->ProcNodeCount != 0); @@ -853,6 +857,7 @@ CreateTopologyFromProcHierarchy ( ASSERT (ScopeNode != NULL); TopLevelProcNodeIndex = MAX_UINT32; + ProcContainerIndex = 0; Status = TokenTableInitialize (Generator, Generator->ProcNodeCount); if (EFI_ERROR (Status)) { @@ -887,7 +892,8 @@ CreateTopologyFromProcHierarchy ( Generator, CfgMgrProtocol, Generator->ProcNodeList[TopLevelProcNodeIndex].Token, - ScopeNode + ScopeNode, + &ProcContainerIndex ); if (EFI_ERROR (Status)) { ASSERT (0); @@ -908,7 +914,7 @@ CreateTopologyFromProcHierarchy ( /** Create the processor hierarchy AML tree from CM_ARM_GICC_INFO CM objects. - A cluster is by extension any non-leave device in the cpu topology. + A processor container is by extension any non-leave device in the cpu topology. @param [in] Generator The SSDT Cpu Topology generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c index a34018151f..032a368900 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "SsdtPcieGenerator.h" @@ -280,86 +281,6 @@ GeneratePciDeviceInfo ( return Status; } -/** Generate Pci slots devices. - - PCI Firmware Specification - Revision 3.3, - s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot - used. It should be possible to enumerate them, but this is additional - information. - - @param [in] MappingTable The mapping table structure. - @param [in, out] PciNode Pci node to amend. - - @retval EFI_SUCCESS Success. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -GeneratePciSlots ( - IN CONST MAPPING_TABLE *MappingTable, - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - UINT32 Index; - UINT32 LastIndex; - UINT32 DeviceId; - CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; - AML_OBJECT_NODE_HANDLE DeviceNode; - - ASSERT (MappingTable != NULL); - ASSERT (PciNode != NULL); - - // Generic device name is "Dxx". - CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1); - - LastIndex = MappingTable->LastIndex; - - // There are at most 32 devices on a Pci bus. - if (LastIndex >= 32) { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - for (Index = 0; Index < LastIndex; Index++) { - DeviceId = MappingTable->Table[Index]; - AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF); - AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF); - - // ASL: - // Device (Dxx) { - // Name (_ADR,
) - // } - Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings" - High word-Device #, Low word-Function #. (for example, device 3, - function 2 is 0x00030002). To refer to all the functions on a device #, - use a function number of FFFF). - */ - Status = AmlCodeGenNameInteger ( - "_ADR", - (DeviceId << 16) | 0xFFFF, - DeviceNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // _SUN object is not generated as we don't know which slot will be used. - } - - return Status; -} - /** Generate a _PRT object (Pci Routing Table) for the Pci device. Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)" @@ -374,6 +295,7 @@ GeneratePciSlots ( @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol interface. @param [in] PciInfo Pci device information. + @param [in] Uid Unique Id of the Pci device. @param [in, out] PciNode Pci node to amend. @retval EFI_SUCCESS The function completed successfully. @@ -387,6 +309,7 @@ GeneratePrt ( IN ACPI_PCI_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN UINT32 Uid, IN OUT AML_OBJECT_NODE_HANDLE PciNode ) { @@ -495,7 +418,7 @@ GeneratePrt ( PrtNode = NULL; // Generate the Pci slots once all the device have been added. - Status = GeneratePciSlots (&Generator->DeviceTable, PciNode); + Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, Uid, PciNode); if (EFI_ERROR (Status)) { ASSERT (0); goto exit_handler; @@ -540,6 +463,7 @@ GeneratePciCrs ( UINT32 RefCount; CM_ARM_PCI_ADDRESS_MAP_INFO *AddrMapInfo; AML_OBJECT_NODE_HANDLE CrsNode; + BOOLEAN IsPosDecode; ASSERT (Generator != NULL); ASSERT (CfgMgrProtocol != NULL); @@ -609,6 +533,11 @@ GeneratePciCrs ( } Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress); + if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) { + IsPosDecode = TRUE; + } else { + IsPosDecode = FALSE; + } switch (AddrMapInfo->SpaceCode) { case PCI_SS_IO: @@ -616,12 +545,12 @@ GeneratePciCrs ( FALSE, TRUE, TRUE, - TRUE, + IsPosDecode, 3, 0, AddrMapInfo->PciAddress, AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, - Translation ? AddrMapInfo->CpuAddress : 0, + Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, AddrMapInfo->AddressSize, 0, NULL, @@ -635,7 +564,7 @@ GeneratePciCrs ( case PCI_SS_M32: Status = AmlCodeGenRdDWordMemory ( FALSE, - TRUE, + IsPosDecode, TRUE, TRUE, TRUE, @@ -643,7 +572,7 @@ GeneratePciCrs ( 0, AddrMapInfo->PciAddress, AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, - Translation ? AddrMapInfo->CpuAddress : 0, + Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, AddrMapInfo->AddressSize, 0, NULL, @@ -657,7 +586,7 @@ GeneratePciCrs ( case PCI_SS_M64: Status = AmlCodeGenRdQWordMemory ( FALSE, - TRUE, + IsPosDecode, TRUE, TRUE, TRUE, @@ -665,7 +594,7 @@ GeneratePciCrs ( 0, AddrMapInfo->PciAddress, AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1, - Translation ? AddrMapInfo->CpuAddress : 0, + Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0, AddrMapInfo->AddressSize, 0, NULL, @@ -689,89 +618,6 @@ GeneratePciCrs ( return Status; } -/** Add an _OSC template method to the PciNode. - - The _OSC method is provided as an AML blob. The blob is - parsed and attached at the end of the PciNode list of variable elements. - - @param [in, out] PciNode Pci node to amend. - - @retval EFI_SUCCESS The function completed successfully. - @retval EFI_INVALID_PARAMETER Invalid parameter. - @retval EFI_OUT_OF_RESOURCES Could not allocate memory. -**/ -STATIC -EFI_STATUS -EFIAPI -AddOscMethod ( - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - EFI_STATUS Status1; - EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate; - AML_ROOT_NODE_HANDLE OscTemplateRoot; - AML_OBJECT_NODE_HANDLE OscNode; - - ASSERT (PciNode != NULL); - - // Parse the Ssdt Pci Osc Template. - SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *) - ssdtpcieosctemplate_aml_code; - - OscNode = NULL; - OscTemplateRoot = NULL; - Status = AmlParseDefinitionBlock ( - SsdtPcieOscTemplate, - &OscTemplateRoot - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template." - " Status = %r\n", - Status - )); - return Status; - } - - Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode); - if (EFI_ERROR (Status)) { - goto error_handler; - } - - Status = AmlDetachNode (OscNode); - if (EFI_ERROR (Status)) { - goto error_handler; - } - - Status = AmlAttachNode (PciNode, OscNode); - if (EFI_ERROR (Status)) { - // Free the detached node. - AmlDeleteTree (OscNode); - goto error_handler; - } - -error_handler: - // Cleanup - Status1 = AmlDeleteTree (OscTemplateRoot); - if (EFI_ERROR (Status1)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree." - " Status = %r\n", - Status1 - )); - // If Status was success but we failed to delete the AML Tree - // return Status1 else return the original error code, i.e. Status. - if (!EFI_ERROR (Status)) { - return Status1; - } - } - - return Status; -} - /** Generate a Pci device. @param [in] Generator The SSDT Pci generator. @@ -818,7 +664,10 @@ GeneratePciDevice ( // Write the name of the PCI device. CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1); - AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid); + AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF); + if (Uid > 0xF) { + AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF); + } // ASL: Device (PCIx) {} Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode); @@ -840,6 +689,7 @@ GeneratePciDevice ( Generator, CfgMgrProtocol, PciInfo, + Uid, PciNode ); if (EFI_ERROR (Status)) { @@ -856,7 +706,7 @@ GeneratePciDevice ( } // Add the template _OSC method. - Status = AddOscMethod (PciNode); + Status = AddOscMethod (PciInfo, PciNode); ASSERT_EFI_ERROR (Status); return Status; } diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h index 59a0d601a3..7410f9ffd4 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h @@ -31,34 +31,13 @@ Corresponding changes would be needed to support the Name and UID fields describing the Pci root complexes. */ -#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED 16 +#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED 256 // _SB scope of the AML namespace. #define SB_SCOPE "\\_SB_" -/** C array containing the compiled AML template. - This symbol is defined in the auto generated C file - containing the AML bytecode array. -*/ -extern CHAR8 ssdtpcieosctemplate_aml_code[]; - #pragma pack(1) -/** Structure used to map integer to an index. -*/ -typedef struct MappingTable { - /// Mapping table. - /// Contains the Index <-> integer mapping - UINT32 *Table; - - /// Last used index of the Table. - /// Bound by MaxIndex. - UINT32 LastIndex; - - /// Number of entries in the Table. - UINT32 MaxIndex; -} MAPPING_TABLE; - /** A structure holding the Pcie generator and additional private data. */ typedef struct AcpiPcieGenerator { diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf index 283b564801..b38a4e9d34 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf @@ -19,7 +19,6 @@ [Sources] SsdtPcieGenerator.c SsdtPcieGenerator.h - SsdtPcieOscTemplate.asl [Packages] DynamicTablesPkg/DynamicTablesPkg.dec @@ -30,3 +29,4 @@ AcpiHelperLib AmlLib BaseLib + SsdtPcieSupportLib diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c index e51d2dd7f0..cf92e7aee7 100644 --- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c +++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c @@ -2600,3 +2600,257 @@ AmlAddLpiState ( return Status; } + +/** AML code generation for a _DSD device data object. + + AmlAddDeviceDataDescriptorPackage (Uuid, DsdNode, PackageNode) is + equivalent of the following ASL code: + ToUUID(Uuid), + Package () {} + + Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)". + + _DSD (Device Specific Data) Implementation Guide + https://github.com/UEFI/DSD-Guide + Per s3. "'Well-Known _DSD UUIDs and Data Structure Formats'" + If creating a Device Properties data then UUID daffd814-6eba-4d8c-8a91-bc9bbf4aa301 should be used. + + @ingroup CodeGenApis + + @param [in] Uuid The Uuid of the descriptor to be created + @param [in] DsdNode Node of the DSD Package. + @param [out] PackageNode If success, contains the created package node. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlAddDeviceDataDescriptorPackage ( + IN CONST EFI_GUID *Uuid, + IN AML_OBJECT_NODE_HANDLE DsdNode, + OUT AML_OBJECT_NODE_HANDLE *PackageNode + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE *UuidNode; + AML_DATA_NODE *UuidDataNode; + AML_OBJECT_NODE_HANDLE DsdEntryList; + + if ((Uuid == NULL) || + (PackageNode == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)DsdNode) != EAmlNodeObject) || + (!AmlNodeHasOpCode (DsdNode, AML_NAME_OP, 0)) || + !AmlNameOpCompareName (DsdNode, "_DSD")) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + // Get the Package object node of the _DSD node, + // which is the 2nd fixed argument (i.e. index 1). + DsdEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument ( + DsdNode, + EAmlParseIndexTerm1 + ); + if ((DsdEntryList == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)DsdEntryList) != EAmlNodeObject) || + (!AmlNodeHasOpCode (DsdEntryList, AML_PACKAGE_OP, 0))) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + *PackageNode = NULL; + UuidDataNode = NULL; + + Status = AmlCodeGenBuffer (NULL, 0, &UuidNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Status = AmlCreateDataNode ( + EAmlNodeDataTypeRaw, + (CONST UINT8 *)Uuid, + sizeof (EFI_GUID), + &UuidDataNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HEADER *)UuidNode, + (AML_NODE_HEADER *)UuidDataNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + UuidDataNode = NULL; + + // Append to the list of _DSD entries. + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)DsdEntryList, + (AML_NODE_HANDLE)UuidNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlCodeGenPackage (PackageNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler_detach; + } + + // Append to the list of _DSD entries. + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)DsdEntryList, + (AML_NODE_HANDLE)*PackageNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler_detach; + } + + return Status; + +error_handler_detach: + if (UuidNode != NULL) { + AmlDetachNode ((AML_NODE_HANDLE)UuidNode); + } + +error_handler: + if (UuidNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)UuidNode); + } + + if (*PackageNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)*PackageNode); + *PackageNode = NULL; + } + + if (UuidDataNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)UuidDataNode); + } + + return Status; +} + +/** AML code generation to add a package with a name and value, + to a parent package. + This is useful for build the _DSD package but can be used in other cases. + + AmlAddNameValuePackage ("Name", Value, PackageNode) is + equivalent of the following ASL code: + Package (2) {"Name", Value} + + Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)". + + @ingroup CodeGenApis + + @param [in] Name String to place in first entry of package + @param [in] Value Integer to place in second entry of package + @param [in] PackageNode Package to add new sub package to. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +AmlAddNameIntegerPackage ( + IN CHAR8 *Name, + IN UINT64 Value, + IN AML_OBJECT_NODE_HANDLE PackageNode + ) +{ + EFI_STATUS Status; + AML_OBJECT_NODE *NameNode; + AML_OBJECT_NODE *ValueNode; + AML_OBJECT_NODE *NewPackageNode; + + if ((Name == NULL) || + (AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) || + (!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0))) + { + ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; + } + + NameNode = NULL; + ValueNode = NULL; + + // The new package entry. + Status = AmlCodeGenPackage (&NewPackageNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + Status = AmlCodeGenString (Name, &NameNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewPackageNode, + (AML_NODE_HANDLE)NameNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + NameNode = NULL; + + Status = AmlCodeGenInteger (Value, &ValueNode); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)NewPackageNode, + (AML_NODE_HANDLE)ValueNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + ValueNode = NULL; + + Status = AmlVarListAddTail ( + (AML_NODE_HANDLE)PackageNode, + (AML_NODE_HANDLE)NewPackageNode + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto error_handler; + } + + return Status; + +error_handler: + if (NewPackageNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)NewPackageNode); + } + + if (NameNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)NameNode); + } + + if (ValueNode != NULL) { + AmlDeleteTree ((AML_NODE_HANDLE)ValueNode); + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl similarity index 100% rename from DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl rename to DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c new file mode 100644 index 0000000000..b35fb6a7dd --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c @@ -0,0 +1,202 @@ +/** @file + SSDT PCIe Support Library. + + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - PCI Firmware Specification - Revision 3.0 + - ACPI 6.4 specification: + - s6.2.13 "_PRT (PCI Routing Table)" + - s6.1.1 "_ADR (Address)" + - linux kernel code + - Arm Base Boot Requirements v1.0 + - Arm Base System Architecture v1.0 +**/ + +#include +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SsdtPcieSupportLibPrivate.h" + +/** Generate Pci slots devices. + + PCI Firmware Specification - Revision 3.3, + s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot + used. It should be possible to enumerate them, but this is additional + information. + + @param [in] PciInfo Pci device information. + @param [in] MappingTable The mapping table structure. + @param [in] Uid Unique Id of the Pci device. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +GeneratePciSlots ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN CONST MAPPING_TABLE *MappingTable, + IN UINT32 Uid, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 LastIndex; + UINT32 DeviceId; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + AML_OBJECT_NODE_HANDLE DeviceNode; + + ASSERT (MappingTable != NULL); + ASSERT (PciNode != NULL); + + // Generic device name is "Dxx". + CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1); + + LastIndex = MappingTable->LastIndex; + + // There are at most 32 devices on a Pci bus. + if (LastIndex >= 32) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; Index < LastIndex; Index++) { + DeviceId = MappingTable->Table[Index]; + AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF); + AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF); + + // ASL: + // Device (Dxx) { + // Name (_ADR,
) + // } + Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings" + High word-Device #, Low word-Function #. (for example, device 3, + function 2 is 0x00030002). To refer to all the functions on a device #, + use a function number of FFFF). + */ + Status = AmlCodeGenNameInteger ( + "_ADR", + (DeviceId << 16) | 0xFFFF, + DeviceNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // _SUN object is not generated as we don't know which slot will be used. + } + + return Status; +} + +/** Add an _OSC template method to the PciNode. + + The _OSC method is provided as an AML blob. The blob is + parsed and attached at the end of the PciNode list of variable elements. + + @param [in] PciInfo Pci device information. + @param [in, out] PciNode Pci node to amend. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +EFI_STATUS +EFIAPI +AddOscMethod ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate; + AML_ROOT_NODE_HANDLE OscTemplateRoot; + AML_OBJECT_NODE_HANDLE OscNode; + + ASSERT (PciNode != NULL); + + // Parse the Ssdt Pci Osc Template. + SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *) + ssdtpcieosctemplate_aml_code; + + OscNode = NULL; + OscTemplateRoot = NULL; + Status = AmlParseDefinitionBlock ( + SsdtPcieOscTemplate, + &OscTemplateRoot + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template." + " Status = %r\n", + Status + )); + return Status; + } + + Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode); + if (EFI_ERROR (Status)) { + goto error_handler; + } + + Status = AmlDetachNode (OscNode); + if (EFI_ERROR (Status)) { + goto error_handler; + } + + Status = AmlAttachNode (PciNode, OscNode); + if (EFI_ERROR (Status)) { + // Free the detached node. + AmlDeleteTree (OscNode); + goto error_handler; + } + +error_handler: + // Cleanup + Status1 = AmlDeleteTree (OscTemplateRoot); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree." + " Status = %r\n", + Status1 + )); + // If Status was success but we failed to delete the AML Tree + // return Status1 else return the original error code, i.e. Status. + if (!EFI_ERROR (Status)) { + return Status1; + } + } + + return Status; +} diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf new file mode 100644 index 0000000000..57fe32369f --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf @@ -0,0 +1,30 @@ +## @file +# Ssdt PCIe Support Library. +# +# Copyright (c) 2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SsdtPcieSupportLib + FILE_GUID = 510451a0-60b2-446c-b6bf-59cbe4a41782 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = SsdtPcieSupportLib + +[Sources] + SsdtPcieSupportLib.c + SsdtPcieSupportLibPrivate.h + SsdtPcieOscTemplate.asl + +[Packages] + DynamicTablesPkg/DynamicTablesPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + AcpiHelperLib + AmlLib + BaseLib diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h new file mode 100644 index 0000000000..0c070b8c7b --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h @@ -0,0 +1,25 @@ +/** @file + SSDT PCIe Support Library private data. + + Copyright (c) 2021, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - PCI Firmware Specification - Revision 3.0 + - ACPI 6.4 specification: + - s6.2.13 "_PRT (PCI Routing Table)" + - s6.1.1 "_ADR (Address)" + - linux kernel code + - Arm Base Boot Requirements v1.0 +**/ + +#ifndef SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_ +#define SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_ + +/** C array containing the compiled AML template. + This symbol is defined in the auto generated C file + containing the AML bytecode array. +*/ +extern CHAR8 ssdtpcieosctemplate_aml_code[]; + +#endif // SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_ diff --git a/DynamicTablesPkg/Library/Smbios/Arm/SmbiosType17Lib/SmbiosType17Generator.c b/DynamicTablesPkg/Library/Smbios/Arm/SmbiosType17Lib/SmbiosType17Generator.c new file mode 100644 index 0000000000..f258824ba5 --- /dev/null +++ b/DynamicTablesPkg/Library/Smbios/Arm/SmbiosType17Lib/SmbiosType17Generator.c @@ -0,0 +1,337 @@ +/** @file + SMBIOS Type17 Table Generator. + + Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include + +/** This macro expands to a function that retrieves the Memory Device + information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjMemoryDeviceInfo, + CM_ARM_MEMORY_DEVICE_INFO + ) + +// Default Values for Memory Device +STATIC SMBIOS_TABLE_TYPE17 MemDeviceInfoTemplate = { + { // Hdr + EFI_SMBIOS_TYPE_MEMORY_DEVICE, // Type + sizeof (SMBIOS_TABLE_TYPE17), // Length + 0 // Handle + }, + 0, // MemoryArrayHandle + 0, // MemoryErrorInformationHandle + 0xFFFF, // TotalWidth + 0xFFFF, // DataWIdth + 0x7FFF, // Size (always use Extended Size) + MemoryTypeUnknown, // FormFactor + 0xFF, // DeviceSet + 1, // Device Locator + 2, // Bank Locator + MemoryTypeSdram, // MemoryType + { // TypeDetail + 0 + }, + 0xFFFF, // Speed (Use Extended Speed) + 0, // Manufacturer + // (Unused Use ModuleManufactuerId) + 3, // SerialNumber + 4, // AssetTag + 0, // PartNumber + // (Unused Use ModuleProductId) + 0, // Attributes + 0, // ExtendedSize + 2000, // ConfiguredMemoryClockSpeed + 0, // MinimumVoltage + 0, // MaximumVoltage + 0, // ConfiguredVoltage + MemoryTechnologyDram, // MemoryTechnology + { // MemoryOperatingModeCapability + .Uint16 = 0x000 + }, + 5, // FirmwareVersion + 0, // ModuleManufacturerId + 0, // ModuleProductId + 0, // MemorySubsystemContollerManufacturerId + 0, // MemorySybsystemControllerProductId + 0, // NonVolatileSize + 0, // VolatileSize + 0, // CacheSize + 0, // LogicalSize + 0, // ExtendedSpeed + 0, // ExtendedConfiguredMemorySpeed +}; + +STATIC CHAR8 UnknownStr[] = "Unknown\0"; + +STATIC +EFI_STATUS +EFIAPI +FreeSmbiosType17TableEx ( + IN CONST SMBIOS_TABLE_GENERATOR *CONST This, + IN CONST CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN OUT SMBIOS_STRUCTURE ***CONST Table, + IN CONST UINTN TableCount + ) +{ + return EFI_SUCCESS; +} + +/** Construct SMBIOS Type17 Table describing memory devices. + + If this function allocates any resources then they must be freed + in the FreeXXXXTableResources function. + + @param [in] This Pointer to the SMBIOS table generator. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol interface. + @param [out] Table Pointer to the SMBIOS table. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration + Manager is less than the Object size for + the requested object. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND Could not find information. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. + @retval EFI_UNSUPPORTED Unsupported configuration. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSmbiosType17TableEx ( + IN CONST SMBIOS_TABLE_GENERATOR *This, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT SMBIOS_STRUCTURE ***Table, + OUT UINTN *CONST TableCount + ) +{ + EFI_STATUS Status; + UINT32 NumMemDevices; + SMBIOS_STRUCTURE **TableList; + CM_ARM_MEMORY_DEVICE_INFO *MemoryDevicesInfo; + UINTN Index; + UINTN SerialNumLen; + CHAR8 *SerialNum; + UINTN AssetTagLen; + CHAR8 *AssetTag; + UINTN DeviceLocatorLen; + CHAR8 *DeviceLocator; + UINTN BankLocatorLen; + CHAR8 *BankLocator; + UINTN FirmwareVersionLen; + CHAR8 *FirmwareVersion; + CHAR8 *OptionalStrings; + SMBIOS_TABLE_TYPE17 *SmbiosRecord; + + ASSERT (This != NULL); + ASSERT (SmbiosTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (TableCount != NULL); + ASSERT (SmbiosTableInfo->TableGeneratorId == This->GeneratorID); + + DEBUG ((DEBUG_ERROR, "%a : Start \n", __FUNCTION__)); + *Table = NULL; + Status = GetEArmObjMemoryDeviceInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &MemoryDevicesInfo, + &NumMemDevices + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Failed to get Memory Devices CM Object %r\n", + Status + )); + return Status; + } + + TableList = (SMBIOS_STRUCTURE **)AllocateZeroPool (sizeof (SMBIOS_STRUCTURE *) * NumMemDevices); + if (TableList == NULL) { + DEBUG ((DEBUG_ERROR, "Failed to alloc memory for %u devices table\n")); + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + for (Index = 0; Index < NumMemDevices; Index++) { + if (MemoryDevicesInfo[Index].SerialNum != NULL) { + SerialNumLen = AsciiStrLen (MemoryDevicesInfo[Index].SerialNum); + SerialNum = MemoryDevicesInfo[Index].SerialNum; + } else { + SerialNumLen = AsciiStrLen (UnknownStr); + SerialNum = UnknownStr; + } + + if (MemoryDevicesInfo[Index].AssetTag != NULL) { + AssetTagLen = AsciiStrLen (MemoryDevicesInfo[Index].AssetTag); + AssetTag = MemoryDevicesInfo[Index].AssetTag; + } else { + AssetTagLen = AsciiStrLen (UnknownStr); + AssetTag = UnknownStr; + } + + if (MemoryDevicesInfo[Index].DeviceLocator != NULL) { + DeviceLocatorLen = AsciiStrLen (MemoryDevicesInfo[Index].DeviceLocator); + DeviceLocator = MemoryDevicesInfo[Index].DeviceLocator; + } else { + DeviceLocatorLen = AsciiStrLen (UnknownStr); + DeviceLocator = UnknownStr; + } + + if (MemoryDevicesInfo[Index].BankLocator != NULL) { + BankLocatorLen = AsciiStrLen (MemoryDevicesInfo[Index].BankLocator); + BankLocator = MemoryDevicesInfo[Index].BankLocator; + } else { + BankLocatorLen = AsciiStrLen (UnknownStr); + BankLocator = UnknownStr; + } + + if (MemoryDevicesInfo[Index].FirmwareVersion != NULL) { + FirmwareVersionLen = AsciiStrLen (MemoryDevicesInfo[Index].FirmwareVersion); + FirmwareVersion = MemoryDevicesInfo[Index].FirmwareVersion; + } else { + FirmwareVersionLen = AsciiStrLen (UnknownStr); + FirmwareVersion = UnknownStr; + } + + SmbiosRecord = (SMBIOS_TABLE_TYPE17 *)AllocateZeroPool ( + sizeof (SMBIOS_TABLE_TYPE17) + + SerialNumLen + 1 + + AssetTagLen + 1 + DeviceLocatorLen + 1 + + BankLocatorLen + 1 + FirmwareVersionLen + 1 + 1 + ); + if (SmbiosRecord == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + CopyMem (SmbiosRecord, &MemDeviceInfoTemplate, sizeof (SMBIOS_TABLE_TYPE17)); + SmbiosRecord->ExtendedSize = MemoryDevicesInfo[Index].Size; + SmbiosRecord->DeviceSet = MemoryDevicesInfo[Index].DeviceSet; + SmbiosRecord->ModuleManufacturerID = + MemoryDevicesInfo[Index].ModuleManufacturerId; + SmbiosRecord->ModuleProductID = + MemoryDevicesInfo[Index].ModuleProductId; + SmbiosRecord->Attributes = + MemoryDevicesInfo[Index].Attributes; + SmbiosRecord->ExtendedSpeed = MemoryDevicesInfo[Index].Speed; + OptionalStrings = (CHAR8 *)(SmbiosRecord + 1); + AsciiSPrint (OptionalStrings, DeviceLocatorLen + 1, DeviceLocator); + OptionalStrings = OptionalStrings + DeviceLocatorLen + 1; + AsciiSPrint (OptionalStrings, BankLocatorLen + 1, BankLocator); + OptionalStrings = OptionalStrings + BankLocatorLen + 1; + AsciiSPrint (OptionalStrings, SerialNumLen + 1, SerialNum); + OptionalStrings = OptionalStrings + SerialNumLen + 1; + AsciiSPrint (OptionalStrings, AssetTagLen + 1, AssetTag); + OptionalStrings = OptionalStrings + AssetTagLen + 1; + AsciiSPrint (OptionalStrings, FirmwareVersionLen + 1, FirmwareVersion); + OptionalStrings = OptionalStrings + FirmwareVersionLen + 1; + TableList[Index] = (SMBIOS_STRUCTURE *)SmbiosRecord; + } + + *Table = TableList; + *TableCount = NumMemDevices; + +exit: + DEBUG ((DEBUG_ERROR, "%a : Done \n", __FUNCTION__)); + return Status; +} + +/** The interface for the SMBIOS Type17 Table Generator. +*/ +STATIC +CONST +SMBIOS_TABLE_GENERATOR SmbiosType17Generator = { + // Generator ID + CREATE_STD_SMBIOS_TABLE_GEN_ID (EStdSmbiosTableIdType17), + // Generator Description + L"SMBIOS.TYPE17.GENERATOR", + // SMBIOS Table Type + EFI_SMBIOS_TYPE_MEMORY_DEVICE, + NULL, + NULL, + // Build table function Extended. + BuildSmbiosType17TableEx, + // Free function Extended. + FreeSmbiosType17TableEx +}; + +/** Register the Generator with the SMBIOS 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 +SmbiosType17LibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterSmbiosTableGenerator (&SmbiosType17Generator); + DEBUG (( + DEBUG_INFO, + "SMBIOS Type 17: Register Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** Deregister the Generator from the SMBIOS 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 +SmbiosType17LibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterSmbiosTableGenerator (&SmbiosType17Generator); + DEBUG (( + DEBUG_INFO, + "SMBIOS Type17: Deregister Generator. Status = %r\n", + Status + )); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Smbios/Arm/SmbiosType17Lib/SmbiosType17LibArm.inf b/DynamicTablesPkg/Library/Smbios/Arm/SmbiosType17Lib/SmbiosType17LibArm.inf new file mode 100644 index 0000000000..78a80b75f0 --- /dev/null +++ b/DynamicTablesPkg/Library/Smbios/Arm/SmbiosType17Lib/SmbiosType17LibArm.inf @@ -0,0 +1,32 @@ +## @file +# SMBIOS Type17 Table Generator +# +# Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SmbiosType17LibArm + FILE_GUID = 1f063bac-f8f1-4e08-8ffd-9aae52c75497 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = SmbiosType17LibConstructor + DESTRUCTOR = SmbiosType17LibDestructor + +[Sources] + SmbiosType17Generator.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + DebugLib