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/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/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/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