diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 2ea65fdabe..c71abe57a6 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -54,6 +54,7 @@ # SMBIOS Generators (Common) DynamicTablesPkg/Library/Smbios/SmbiosType0Lib/SmbiosType0Lib.inf DynamicTablesPkg/Library/Smbios/SmbiosType1Lib/SmbiosType1Lib.inf + DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Lib.inf DynamicTablesPkg/Library/Smbios/SmbiosType4Lib/SmbiosType4Lib.inf DynamicTablesPkg/Library/Smbios/SmbiosType7Lib/SmbiosType7Lib.inf DynamicTablesPkg/Library/Smbios/SmbiosType16Lib/SmbiosType16Lib.inf @@ -174,6 +175,7 @@ NULL|DynamicTablesPkg/Library/Smbios/SmbiosType0Lib/SmbiosType0Lib.inf NULL|DynamicTablesPkg/Library/Smbios/SmbiosType1Lib/SmbiosType1Lib.inf + NULL|DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Lib.inf NULL|DynamicTablesPkg/Library/Smbios/SmbiosType4Lib/SmbiosType4Lib.inf NULL|DynamicTablesPkg/Library/Smbios/SmbiosType7Lib/SmbiosType7Lib.inf NULL|DynamicTablesPkg/Library/Smbios/SmbiosType16Lib/SmbiosType16Lib.inf diff --git a/DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Generator.c b/DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Generator.c new file mode 100644 index 0000000000..47b1910c11 --- /dev/null +++ b/DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Generator.c @@ -0,0 +1,601 @@ +/** @file + SMBIOS Type 3 System Enclosure Table Generator. + + Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define SMBIOS_TYPE3_MAX_STRINGS 5 +#define SMBIOS_TYPE3_CHASSIS_TYPE_MASK 0x7F +#define SMBIOS_TYPE3_CONTAINED_ELEMENT_TYPE_SELECT BIT7 +#define SMBIOS_TYPE3_CONTAINED_ELEMENT_TYPE_MASK 0x7F +#define SMBIOS_TYPE3_CONTAINED_ELEMENT_RECORD_LENGTH 3 +#define SMBIOS_TYPE3_TRAILING_FIELD_LENGTH 3 +#define SMBIOS_TYPE3_BASE_LENGTH \ + (OFFSET_OF (SMBIOS_TABLE_TYPE3, ContainedElements) + SMBIOS_TYPE3_TRAILING_FIELD_LENGTH) + +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjSystemEnclosureInfo, + CM_ARCH_COMMON_SYSTEM_ENCLOSURE_INFO + ); + +GET_OBJECT_LIST ( + EObjNameSpaceArchCommon, + EArchCommonObjEnclosureElement, + CM_ARCH_COMMON_ENCLOSURE_ELEMENT + ); + +/** Validate System Enclosure Contained Element CM objects. + + @param [in] ContainedElement Contained Element objects to validate. + @param [in] ContainedElementCount Number of Contained Element objects. + + @retval EFI_SUCCESS The Contained Element objects are valid. + @retval EFI_INVALID_PARAMETER A Contained Element object is invalid. +**/ +STATIC +EFI_STATUS +ValidateSystemEnclosureContainedElements ( + IN CONST CM_ARCH_COMMON_ENCLOSURE_ELEMENT *ContainedElement, + IN UINT32 ContainedElementCount + ) +{ + UINT32 Index; + UINT8 ElementType; + + for (Index = 0; Index < ContainedElementCount; Index++) { + ElementType = ContainedElement[Index].ContainedElementType & + SMBIOS_TYPE3_CONTAINED_ELEMENT_TYPE_MASK; + + if (((ContainedElement[Index].ContainedElementType & + SMBIOS_TYPE3_CONTAINED_ELEMENT_TYPE_SELECT) == 0) && + ((ElementType < BaseBoardTypeUnknown) || + (ElementType > BaseBoardTypeInterconnectBoard))) + { + DEBUG (( + DEBUG_ERROR, + "%a: Invalid Baseboard Type 0x%x for Contained Element %u\n", + __func__, + ElementType, + Index + )); + return EFI_INVALID_PARAMETER; + } + + // When bit 7 is set, bits 6:0 identify an SMBIOS structure type. + // Type 127 is the end-of-table marker and cannot represent a device. + if (((ContainedElement[Index].ContainedElementType & + SMBIOS_TYPE3_CONTAINED_ELEMENT_TYPE_SELECT) != 0) && + (ElementType > EFI_SMBIOS_TYPE_INACTIVE)) + { + DEBUG (( + DEBUG_ERROR, + "%a: Invalid SMBIOS Type 0x%x for Contained Element %u\n", + __func__, + ElementType, + Index + )); + return EFI_INVALID_PARAMETER; + } + + if ((ContainedElement[Index].ContainedElementMinimum == MAX_UINT8) || + (ContainedElement[Index].ContainedElementMaximum == 0) || + (ContainedElement[Index].ContainedElementMinimum > + ContainedElement[Index].ContainedElementMaximum)) + { + DEBUG (( + DEBUG_ERROR, + "%a: Invalid quantity range %u-%u for Contained Element %u\n", + __func__, + ContainedElement[Index].ContainedElementMinimum, + ContainedElement[Index].ContainedElementMaximum, + Index + )); + return EFI_INVALID_PARAMETER; + } + } + + return EFI_SUCCESS; +} + +/** Validate a System Enclosure CM object. + + @param [in] EnclosureInfo System Enclosure information to validate. + + @retval EFI_SUCCESS The System Enclosure information is valid. + @retval EFI_INVALID_PARAMETER The System Enclosure information is invalid. +**/ +STATIC +EFI_STATUS +ValidateSystemEnclosureInfo ( + IN CONST CM_ARCH_COMMON_SYSTEM_ENCLOSURE_INFO *EnclosureInfo + ) +{ + UINT8 ChassisType; + + if (EnclosureInfo->Manufacturer[0] == '\0') { + DEBUG ((DEBUG_ERROR, "%a: Manufacturer must be non-empty\n", __func__)); + return EFI_INVALID_PARAMETER; + } + + ChassisType = EnclosureInfo->Type & SMBIOS_TYPE3_CHASSIS_TYPE_MASK; + if ((ChassisType < MiscChassisTypeOther) || + (ChassisType == MiscChassisTypeUnknown) || + (ChassisType > MiscChassisStickPc)) + { + DEBUG ((DEBUG_ERROR, "%a: Invalid chassis Type 0x%x\n", __func__, EnclosureInfo->Type)); + return EFI_INVALID_PARAMETER; + } + + if ((EnclosureInfo->BootUpState < ChassisStateOther) || + (EnclosureInfo->BootUpState > ChassisStateNonRecoverable) || + (EnclosureInfo->PowerSupplyState < ChassisStateOther) || + (EnclosureInfo->PowerSupplyState > ChassisStateNonRecoverable) || + (EnclosureInfo->ThermalState < ChassisStateOther) || + (EnclosureInfo->ThermalState > ChassisStateNonRecoverable)) + { + DEBUG ((DEBUG_ERROR, "%a: Invalid chassis state\n", __func__)); + return EFI_INVALID_PARAMETER; + } + + if ((EnclosureInfo->SecurityStatus < ChassisSecurityStatusOther) || + (EnclosureInfo->SecurityStatus > ChassisSecurityStatusExternalInterfaceLockedEnabled)) + { + DEBUG ((DEBUG_ERROR, "%a: Invalid SecurityStatus 0x%x\n", __func__, EnclosureInfo->SecurityStatus)); + return EFI_INVALID_PARAMETER; + } + + if (EnclosureInfo->RackType > ChassisRackTypeOU) { + DEBUG ((DEBUG_ERROR, "%a: Invalid RackType 0x%x\n", __func__, EnclosureInfo->RackType)); + return EFI_INVALID_PARAMETER; + } + + if ((EnclosureInfo->Height == ChassisHeightUseRackHeight) && + (EnclosureInfo->RackHeight == 0)) + { + DEBUG ((DEBUG_ERROR, "%a: RackHeight must be non-zero when Height is 0xFF\n", __func__)); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +/** Construct SMBIOS Type 3 tables describing system enclosures. + + @param [in] This Pointer to the SMBIOS table generator. + @param [in] TableFactoryProtocol Pointer to the SMBIOS table factory. + @param [in] SmbiosTableInfo Pointer to the SMBIOS table information. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager. + @param [out] Table Pointer to the generated SMBIOS tables. + @param [out] CmObjectToken Pointer to the CM object tokens. + @param [out] TableCount Number of generated SMBIOS tables. + + @retval EFI_SUCCESS Tables generated successfully. + @retval EFI_INVALID_PARAMETER A parameter or CM object is invalid. + @retval EFI_NOT_FOUND No System Enclosure objects were found. + @retval EFI_OUT_OF_RESOURCES Could not allocate memory. +**/ +STATIC +EFI_STATUS +EFIAPI +BuildSmbiosType3TableEx ( + IN CONST SMBIOS_TABLE_GENERATOR *This, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + OUT SMBIOS_STRUCTURE ***Table, + OUT CM_OBJECT_TOKEN **CmObjectToken, + OUT UINTN *CONST TableCount + ) +{ + EFI_STATUS Status; + CM_ARCH_COMMON_SYSTEM_ENCLOSURE_INFO *EnclosureInfo; + CM_ARCH_COMMON_ENCLOSURE_ELEMENT *ContainedElement; + UINT32 EnclosureCount; + UINT32 ContainedElementCount; + SMBIOS_STRUCTURE **TableList; + CM_OBJECT_TOKEN *CmObjectList; + SMBIOS_TABLE_TYPE3 *SmbiosRecord; + CONTAINED_ELEMENT *ContainedElementField; + STRING_TABLE StrTable; + SMBIOS_TABLE_STRING ManufacturerRef; + SMBIOS_TABLE_STRING VersionRef; + SMBIOS_TABLE_STRING SerialNumRef; + SMBIOS_TABLE_STRING AssetTagRef; + SMBIOS_TABLE_STRING SkuNumRef; + SMBIOS_TABLE_STRING *SkuNumField; + UINT8 *RackTypeField; + UINT8 *RackHeightField; + UINTN FormattedLength; + UINTN RecordSize; + UINTN Index; + UINTN ContainedElementIndex; + + ASSERT (This != NULL); + ASSERT (TableFactoryProtocol != NULL); + ASSERT (SmbiosTableInfo != NULL); + ASSERT (CfgMgrProtocol != NULL); + ASSERT (Table != NULL); + ASSERT (CmObjectToken != NULL); + ASSERT (TableCount != NULL); + ASSERT (SmbiosTableInfo->TableGeneratorId == This->GeneratorID); + + if ((This == NULL) || (TableFactoryProtocol == NULL) || + (SmbiosTableInfo == NULL) || (CfgMgrProtocol == NULL) || + (Table == NULL) || (CmObjectToken == NULL) || (TableCount == NULL) || + (SmbiosTableInfo->TableGeneratorId != This->GeneratorID)) + { + DEBUG ((DEBUG_ERROR, "%a: Invalid Parameter\n", __func__)); + return EFI_INVALID_PARAMETER; + } + + *Table = NULL; + *CmObjectToken = NULL; + *TableCount = 0; + TableList = NULL; + CmObjectList = NULL; + SmbiosRecord = NULL; + + Status = GetEArchCommonObjSystemEnclosureInfo ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &EnclosureInfo, + &EnclosureCount + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get System Enclosure objects: %r\n", __func__, Status)); + return Status; + } + + if (EnclosureCount == 0) { + return EFI_NOT_FOUND; + } + + TableList = AllocateZeroPool (sizeof (*TableList) * EnclosureCount); + if (TableList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CmObjectList = AllocateZeroPool (sizeof (*CmObjectList) * EnclosureCount); + if (CmObjectList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + for (Index = 0; Index < EnclosureCount; Index++) { + Status = ValidateSystemEnclosureInfo (&EnclosureInfo[Index]); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + ContainedElement = NULL; + ContainedElementCount = 0; + if (EnclosureInfo[Index].ContainedElementListToken != CM_NULL_TOKEN) { + Status = GetEArchCommonObjEnclosureElement ( + CfgMgrProtocol, + EnclosureInfo[Index].ContainedElementListToken, + &ContainedElement, + &ContainedElementCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "%a: Failed to get Contained Elements for enclosure %u: %r\n", + __func__, + Index, + Status + )); + goto ErrorExit; + } + + if ((ContainedElementCount != 0) && (ContainedElement == NULL)) { + DEBUG (( + DEBUG_ERROR, + "%a: Contained Element list is NULL for enclosure %u\n", + __func__, + Index + )); + Status = EFI_INVALID_PARAMETER; + goto ErrorExit; + } + + if (ContainedElementCount > MAX_UINT8) { + DEBUG (( + DEBUG_ERROR, + "%a: Too many Contained Elements for enclosure %u: %u\n", + __func__, + Index, + ContainedElementCount + )); + Status = EFI_INVALID_PARAMETER; + goto ErrorExit; + } + + Status = ValidateSystemEnclosureContainedElements ( + ContainedElement, + ContainedElementCount + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + } + + FormattedLength = SMBIOS_TYPE3_BASE_LENGTH + + (ContainedElementCount * SMBIOS_TYPE3_CONTAINED_ELEMENT_RECORD_LENGTH); + if (FormattedLength > MAX_UINT8) { + DEBUG (( + DEBUG_ERROR, + "%a: Formatted length %Lu exceeds Hdr.Length for enclosure %u\n", + __func__, + (UINT64)FormattedLength, + Index + )); + Status = EFI_INVALID_PARAMETER; + goto ErrorExit; + } + + Status = StringTableInitialize (&StrTable, SMBIOS_TYPE3_MAX_STRINGS); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + ManufacturerRef = 0; + VersionRef = 0; + SerialNumRef = 0; + AssetTagRef = 0; + SkuNumRef = 0; + + Status = StringTableAddString (&StrTable, EnclosureInfo[Index].Manufacturer, &ManufacturerRef); + if (EFI_ERROR (Status)) { + StringTableFree (&StrTable); + goto ErrorExit; + } + + if (EnclosureInfo[Index].Version[0] != '\0') { + Status = StringTableAddString (&StrTable, EnclosureInfo[Index].Version, &VersionRef); + } + + if (!EFI_ERROR (Status) && (EnclosureInfo[Index].SerialNum[0] != '\0')) { + Status = StringTableAddString (&StrTable, EnclosureInfo[Index].SerialNum, &SerialNumRef); + } + + if (!EFI_ERROR (Status) && (EnclosureInfo[Index].AssetTag[0] != '\0')) { + Status = StringTableAddString (&StrTable, EnclosureInfo[Index].AssetTag, &AssetTagRef); + } + + if (!EFI_ERROR (Status) && (EnclosureInfo[Index].SkuNum[0] != '\0')) { + Status = StringTableAddString (&StrTable, EnclosureInfo[Index].SkuNum, &SkuNumRef); + } + + if (EFI_ERROR (Status)) { + StringTableFree (&StrTable); + goto ErrorExit; + } + + RecordSize = FormattedLength + StringTableGetStringSetSize (&StrTable); + SmbiosRecord = AllocateZeroPool (RecordSize); + if (SmbiosRecord == NULL) { + Status = EFI_OUT_OF_RESOURCES; + StringTableFree (&StrTable); + goto ErrorExit; + } + + SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE; + SmbiosRecord->Hdr.Length = (UINT8)FormattedLength; + SmbiosRecord->Manufacturer = ManufacturerRef; + SmbiosRecord->Type = EnclosureInfo[Index].Type; + SmbiosRecord->Version = VersionRef; + SmbiosRecord->SerialNumber = SerialNumRef; + SmbiosRecord->AssetTag = AssetTagRef; + SmbiosRecord->BootupState = EnclosureInfo[Index].BootUpState; + SmbiosRecord->PowerSupplyState = EnclosureInfo[Index].PowerSupplyState; + SmbiosRecord->ThermalState = EnclosureInfo[Index].ThermalState; + SmbiosRecord->SecurityStatus = EnclosureInfo[Index].SecurityStatus; + SmbiosRecord->Height = EnclosureInfo[Index].Height; + SmbiosRecord->NumberofPowerCords = EnclosureInfo[Index].NumberOfPowerCords; + SmbiosRecord->ContainedElementCount = (UINT8)ContainedElementCount; + SmbiosRecord->ContainedElementRecordLength = + (ContainedElementCount == 0) ? 0 : SMBIOS_TYPE3_CONTAINED_ELEMENT_RECORD_LENGTH; + WriteUnaligned32 ((UINT32 *)SmbiosRecord->OemDefined, EnclosureInfo[Index].OemDefined); + + ContainedElementField = (CONTAINED_ELEMENT *)((UINT8 *)SmbiosRecord + + OFFSET_OF (SMBIOS_TABLE_TYPE3, ContainedElements)); + if (ContainedElement != NULL) { + for (ContainedElementIndex = 0; + ContainedElementIndex < ContainedElementCount; + ContainedElementIndex++) + { + ContainedElementField[ContainedElementIndex].ContainedElementType = + ContainedElement[ContainedElementIndex].ContainedElementType; + ContainedElementField[ContainedElementIndex].ContainedElementMinimum = + ContainedElement[ContainedElementIndex].ContainedElementMinimum; + ContainedElementField[ContainedElementIndex].ContainedElementMaximum = + ContainedElement[ContainedElementIndex].ContainedElementMaximum; + } + } + + SkuNumField = (SMBIOS_TABLE_STRING *)((UINT8 *)ContainedElementField + + (ContainedElementCount * + SMBIOS_TYPE3_CONTAINED_ELEMENT_RECORD_LENGTH)); + RackTypeField = (UINT8 *)(SkuNumField + 1); + RackHeightField = RackTypeField + 1; + *SkuNumField = SkuNumRef; + *RackTypeField = EnclosureInfo[Index].RackType; + *RackHeightField = EnclosureInfo[Index].RackHeight; + + Status = StringTablePublishStringSet ( + &StrTable, + (CHAR8 *)SmbiosRecord + FormattedLength, + RecordSize - FormattedLength + ); + StringTableFree (&StrTable); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + TableList[Index] = (SMBIOS_STRUCTURE *)SmbiosRecord; + CmObjectList[Index] = EnclosureInfo[Index].SystemEnclosureToken; + SmbiosRecord = NULL; + } + + *Table = TableList; + *CmObjectToken = CmObjectList; + *TableCount = EnclosureCount; + return EFI_SUCCESS; + +ErrorExit: + if (SmbiosRecord != NULL) { + FreePool (SmbiosRecord); + } + + if (TableList != NULL) { + for (Index = 0; Index < EnclosureCount; Index++) { + if (TableList[Index] != NULL) { + FreePool (TableList[Index]); + } + } + + FreePool (TableList); + } + + if (CmObjectList != NULL) { + FreePool (CmObjectList); + } + + return Status; +} + +/** + Free any resources allocated when installing SMBIOS Type 3 tables. + + @param [in] This Pointer to the SMBIOS table generator. + @param [in] TableFactoryProtocol Pointer to the SMBIOS Table Factory + Protocol interface. + @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 SMBIOS tables. + @param [in] CmObjectToken Pointer to the CM ObjectToken array. + @param [in] TableCount Number of SMBIOS tables. + + @retval EFI_SUCCESS Resources freed successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. +**/ +STATIC +EFI_STATUS +EFIAPI +FreeSmbiosType3TableEx ( + IN CONST SMBIOS_TABLE_GENERATOR *CONST This, + IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol, + IN CONST CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN SMBIOS_STRUCTURE ***CONST Table, + IN CM_OBJECT_TOKEN **CmObjectToken, + IN CONST UINTN TableCount + ) +{ + UINTN Index; + + if ((This == NULL) || (TableFactoryProtocol == NULL) || + (SmbiosTableInfo == NULL) || (CfgMgrProtocol == NULL) || + (Table == NULL) || (CmObjectToken == NULL)) + { + DEBUG ((DEBUG_ERROR, "%a: Invalid Parameter\n", __func__)); + return EFI_INVALID_PARAMETER; + } + + if (*Table != NULL) { + for (Index = 0; Index < TableCount; Index++) { + if ((*Table)[Index] != NULL) { + FreePool ((*Table)[Index]); + } + } + + FreePool (*Table); + *Table = NULL; + } + + if (*CmObjectToken != NULL) { + FreePool (*CmObjectToken); + *CmObjectToken = NULL; + } + + return EFI_SUCCESS; +} + +STATIC CONST SMBIOS_TABLE_GENERATOR SmbiosType3Generator = { + // Generator ID + CREATE_STD_SMBIOS_TABLE_GEN_ID (EStdSmbiosTableIdType03), + // Generator Description + L"SMBIOS.TYPE3.GENERATOR", + // SMBIOS Table Type + EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, + NULL, + NULL, + // Build table function Extended. + BuildSmbiosType3TableEx, + // Free function Extended. + FreeSmbiosType3TableEx +}; + +/** 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 +SmbiosType3LibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = RegisterSmbiosTableGenerator (&SmbiosType3Generator); + DEBUG ((DEBUG_INFO, "SMBIOS Type 3: 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 +SmbiosType3LibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = DeregisterSmbiosTableGenerator (&SmbiosType3Generator); + DEBUG ((DEBUG_INFO, "SMBIOS Type 3: Deregister Generator. Status = %r\n", Status)); + ASSERT_EFI_ERROR (Status); + return Status; +} diff --git a/DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Lib.inf b/DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Lib.inf new file mode 100644 index 0000000000..c1e24aa518 --- /dev/null +++ b/DynamicTablesPkg/Library/Smbios/SmbiosType3Lib/SmbiosType3Lib.inf @@ -0,0 +1,30 @@ +## @file +# SMBIOS Type 3 Table Generator +# +# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SmbiosType3Lib + FILE_GUID = 82f255ee-f7c3-49b8-bd45-dc637a9817cf + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = NULL|DXE_DRIVER + CONSTRUCTOR = SmbiosType3LibConstructor + DESTRUCTOR = SmbiosType3LibDestructor + +[Sources] + SmbiosType3Generator.c + +[Packages] + MdePkg/MdePkg.dec + DynamicTablesPkg/DynamicTablesPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + MemoryAllocationLib + SmbiosStringTableLib