summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarshitPandya <varshit.pandya@arm.com>2026-06-24 15:56:28 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2026-06-30 20:31:10 +0000
commit5628eaaf38ea25d7cf0726a132ddfa200ad46f4c (patch)
tree3188a4d9b81c295f3d93dc5fa5cf14c0ac38423c
parent0c2e3373512dfd6ac02215126e032ec41602af24 (diff)
downloadedk2-5628eaaf38ea25d7cf0726a132ddfa200ad46f4c.tar.gz
edk2-5628eaaf38ea25d7cf0726a132ddfa200ad46f4c.zip
DynamicTablesPkg: Add SMBIOS Temperature Probe (Type 28) generator
Introduce a CM_ARCH_COMMON_TEMPERATURE_PROBE_INFO object to describe temperature probes provided by the platform. The generator creates one SMBIOS Type 28 record for each temperature probe object and populates the description, location/status, probe limits, resolution, tolerance, accuracy, OEM-defined data, and nominal value. Add the CM object parser entry and wire the generator into the DynamicTablesPkg build. Signed-off-by: Varshit Pandya <varshit.pandya@arm.com>
-rw-r--r--DynamicTablesPkg/DynamicTables.dsc.inc2
-rw-r--r--DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h45
-rw-r--r--DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c16
-rw-r--r--DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Generator.c465
-rw-r--r--DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Lib.inf29
5 files changed, 557 insertions, 0 deletions
diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index 3de761edcf..e3e29a7d6c 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -116,6 +116,7 @@
DynamicTablesPkg/Library/Smbios/SmbiosType17Lib/SmbiosType17Lib.inf
DynamicTablesPkg/Library/Smbios/SmbiosType19Lib/SmbiosType19Lib.inf
DynamicTablesPkg/Library/Smbios/SmbiosType27Lib/SmbiosType27Lib.inf
+ DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Lib.inf
# AML Fixup (Arm specific)
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
@@ -167,6 +168,7 @@
NULL|DynamicTablesPkg/Library/Smbios/SmbiosType17Lib/SmbiosType17Lib.inf
NULL|DynamicTablesPkg/Library/Smbios/SmbiosType19Lib/SmbiosType19Lib.inf
NULL|DynamicTablesPkg/Library/Smbios/SmbiosType27Lib/SmbiosType27Lib.inf
+ NULL|DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Lib.inf
}
[Components.RISCV64]
diff --git a/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h b/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
index 49898c5283..9ccbd43e7b 100644
--- a/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
+++ b/DynamicTablesPkg/Include/ArchCommonNameSpaceObjects.h
@@ -84,6 +84,7 @@ typedef enum ArchCommonObjectID {
EArchCommonObjMemoryDeviceInfo, ///< 56 - Memory Device Info
EArchCommonObjMemoryArrayMappedAddress, ///< 57 - Memory Array Mapped Address Info
EArchCommonObjCoolingDeviceInfo, ///< 58 - Cooling Device Info
+ EArchCommonObjTemperatureProbeInfo, ///< 59 - Temperature Probe Info
EArchCommonObjMax
} EARCH_COMMON_OBJECT_ID;
@@ -1489,4 +1490,48 @@ typedef struct CmArchCommonCoolingDeviceInfo {
CHAR8 Description[SMBIOS_MAX_STRING_SIZE];
} CM_ARCH_COMMON_COOLING_DEVICE_INFO;
+/** A structure that describes a temperature probe.
+
+ SMBIOS Specification v3.9.0 Type 28
+
+ ID: EArchCommonObjTemperatureProbeInfo
+**/
+typedef struct CmArchCommonTemperatureProbeInfo {
+ /// CM Object Token uniquely identifying this temperature probe.
+ CM_OBJECT_TOKEN TemperatureProbeToken;
+
+ /// Description of the temperature probe or its location.
+ CHAR8 Description[SMBIOS_MAX_STRING_SIZE];
+
+ /// Location and status of the temperature probe.
+ MISC_TEMPERATURE_PROBE_LOCATION LocationAndStatus;
+
+ /// Maximum value readable by the probe, in 1/10 degrees C.
+ /// A value of 0x8000 indicates unknown.
+ UINT16 MaximumValue;
+
+ /// Minimum value readable by the probe, in 1/10 degrees C.
+ /// A value of 0x8000 indicates unknown.
+ UINT16 MinimumValue;
+
+ /// Resolution for the probe reading, in 1/1000 degrees C.
+ /// A value of 0x8000 indicates unknown.
+ UINT16 Resolution;
+
+ /// Tolerance for the probe reading, plus/minus 1/10 degrees C.
+ /// A value of 0x8000 indicates unknown.
+ UINT16 Tolerance;
+
+ /// Accuracy for the probe reading, in plus/minus 1/100 percent.
+ /// A value of 0x8000 indicates unknown.
+ UINT16 Accuracy;
+
+ /// OEM- or firmware vendor-specific information.
+ UINT32 OemDefined;
+
+ /// Nominal temperature value, in 1/10 degrees C.
+ /// A value of 0x8000 indicates unknown.
+ UINT16 NominalValue;
+} CM_ARCH_COMMON_TEMPERATURE_PROBE_INFO;
+
#pragma pack()
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index 9443059559..da28b64d20 100644
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -1235,6 +1235,21 @@ STATIC CONST CM_OBJ_PARSER CmArchCommonCoolingDeviceInfoParser[] = {
{ "Description", SMBIOS_MAX_STRING_SIZE, NULL, PrintString },
};
+/** A parser for EArchCommonObjTemperatureProbeInfo.
+*/
+STATIC CONST CM_OBJ_PARSER CmArchCommonTemperatureProbeInfoParser[] = {
+ { "TemperatureProbeToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL },
+ { "Description", SMBIOS_MAX_STRING_SIZE, NULL, PrintString },
+ { "LocationAndStatus", sizeof (MISC_TEMPERATURE_PROBE_LOCATION), "0x%x", NULL },
+ { "MaximumValue", sizeof (UINT16), "0x%x", NULL },
+ { "MinimumValue", sizeof (UINT16), "0x%x", NULL },
+ { "Resolution", sizeof (UINT16), "0x%x", NULL },
+ { "Tolerance", sizeof (UINT16), "0x%x", NULL },
+ { "Accuracy", sizeof (UINT16), "0x%x", NULL },
+ { "OEMDefined", sizeof (UINT32), "0x%x", NULL },
+ { "NominalValue", sizeof (UINT16), "0x%x", NULL },
+};
+
/** A parser for Arch Common namespace objects.
*/
STATIC CONST CM_OBJ_PARSER_ARRAY ArchCommonNamespaceObjectParser[] = {
@@ -1298,6 +1313,7 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArchCommonNamespaceObjectParser[] = {
CM_PARSER_ADD_OBJECT (EArchCommonObjMemoryDeviceInfo, CmArchCommonMemoryDeviceInfoParser),
CM_PARSER_ADD_OBJECT (EArchCommonObjMemoryArrayMappedAddress, CmArchCommonMemoryArrayMappedAddressParser),
CM_PARSER_ADD_OBJECT (EArchCommonObjCoolingDeviceInfo, CmArchCommonCoolingDeviceInfoParser),
+ CM_PARSER_ADD_OBJECT (EArchCommonObjTemperatureProbeInfo, CmArchCommonTemperatureProbeInfoParser),
CM_PARSER_ADD_OBJECT_RESERVED (EArchCommonObjMax)
};
diff --git a/DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Generator.c b/DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Generator.c
new file mode 100644
index 0000000000..db664c5afc
--- /dev/null
+++ b/DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Generator.c
@@ -0,0 +1,465 @@
+/** @file
+ SMBIOS Type28 Table Generator.
+
+ @par Reference(s):
+ - SMBIOS Specification 3.9.0, Type 28 Temperature Probe
+
+ Copyright (c) 2026, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SmbiosStringTableLib.h>
+
+// Module specific include files.
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include <Protocol/DynamicTableFactoryProtocol.h>
+#include <IndustryStandard/SmBios.h>
+
+/** SMBIOS Type 28 Temperature Probe Generator
+
+Requirements:
+ The following Configuration Manager Object(s) are required by
+ this Generator:
+ - EArchCommonObjTemperatureProbeInfo
+*/
+
+/**
+ This macro expands to a function that retrieves the Temperature Probe
+ information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArchCommon,
+ EArchCommonObjTemperatureProbeInfo,
+ CM_ARCH_COMMON_TEMPERATURE_PROBE_INFO
+ );
+
+/**
+ Type 28 records currently expose one string field: Description.
+*/
+#define SMBIOS_TYPE28_MAX_STRINGS (1)
+
+/**
+ Valid SMBIOS Type 28 Status values are 0x01-0x06.
+ Valid Location values are 0x01-0x0F.
+*/
+#define SMBIOS_TYPE28_PROBE_STATUS_MIN 1
+#define SMBIOS_TYPE28_PROBE_STATUS_MAX 6
+#define SMBIOS_TYPE28_PROBE_LOCATION_MIN 1
+#define SMBIOS_TYPE28_PROBE_LOCATION_MAX 15
+
+/** Check whether a Type 28 temperature probe status value is valid.
+
+ @param [in] Status Temperature probe status value.
+
+ @retval TRUE The status value is valid.
+ @retval FALSE The status value is invalid.
+**/
+STATIC
+BOOLEAN
+IsValidTemperatureProbeStatus (
+ IN UINT8 Status
+ )
+{
+ return (Status >= SMBIOS_TYPE28_PROBE_STATUS_MIN) &&
+ (Status <= SMBIOS_TYPE28_PROBE_STATUS_MAX);
+}
+
+/** Check whether a Type 28 temperature probe location value is valid.
+
+ @param [in] Location Temperature probe location value.
+
+ @retval TRUE The location value is valid.
+ @retval FALSE The location value is invalid.
+**/
+STATIC
+BOOLEAN
+IsValidTemperatureProbeLocation (
+ IN UINT8 Location
+ )
+{
+ return (Location >= SMBIOS_TYPE28_PROBE_LOCATION_MIN) &&
+ (Location <= SMBIOS_TYPE28_PROBE_LOCATION_MAX);
+}
+
+/**
+ Free any resources allocated when installing SMBIOS Type 28 table.
+
+ @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 table.
+ @param [in] CmObjectToken Pointer to the CM ObjectToken Array.
+ @param [in] TableCount Number of SMBIOS tables.
+
+ @retval EFI_SUCCESS Resources were freed 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
+FreeSmbiosType28TableEx (
+ 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;
+ SMBIOS_STRUCTURE **TableList;
+
+ TableList = *Table;
+ for (Index = 0; Index < TableCount; Index++) {
+ if (TableList[Index] != NULL) {
+ FreePool (TableList[Index]);
+ }
+ }
+
+ if (*CmObjectToken != NULL) {
+ FreePool (*CmObjectToken);
+ }
+
+ if (TableList != NULL) {
+ FreePool (TableList);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Construct SMBIOS Type 28 Table describing temperature probes.
+
+ 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] 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 [out] Table Pointer to the SMBIOS table.
+ @param [out] CmObjectToken Pointer to the CM Object Token Array.
+ @param [out] TableCount Number of tables installed.
+
+ @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
+BuildSmbiosType28TableEx (
+ 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;
+ UINTN Index;
+ UINTN SmbiosRecordSize;
+ UINT32 TempProbeCount;
+ UINT8 Description;
+ STRING_TABLE StrTable;
+ SMBIOS_STRUCTURE **TableList;
+ SMBIOS_TABLE_TYPE28 *SmbiosRecord;
+ CM_OBJECT_TOKEN *CmObjectList;
+ CM_ARCH_COMMON_TEMPERATURE_PROBE_INFO *TempProbeInfo;
+
+ ASSERT (This != NULL);
+ ASSERT (SmbiosTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (CmObjectToken != NULL);
+ ASSERT (Table != NULL);
+ ASSERT (TableCount != NULL);
+ ASSERT (SmbiosTableInfo->TableGeneratorId == This->GeneratorID);
+
+ if ((This == 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;
+ SmbiosRecord = NULL;
+ CmObjectList = NULL;
+
+ Status = GetEArchCommonObjTemperatureProbeInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &TempProbeInfo,
+ &TempProbeCount
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get temperature probe info. Status = %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ if (TempProbeCount == 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: No Temperature Probe CM Objects found\n",
+ __func__
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ TableList = (SMBIOS_STRUCTURE **)AllocateZeroPool (sizeof (SMBIOS_STRUCTURE *) * TempProbeCount);
+ if (TableList == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to alloc memory for %u temperature probe table\n",
+ __func__,
+ TempProbeCount
+ ));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ CmObjectList = AllocateZeroPool (
+ sizeof (CM_OBJECT_TOKEN) * TempProbeCount
+ );
+ if (CmObjectList == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to alloc memory for %u temperature probe table\n",
+ __func__,
+ TempProbeCount
+ ));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ Index = 0;
+ for (Index = 0; Index < TempProbeCount; Index++) {
+ Status = StringTableInitialize (&StrTable, SMBIOS_TYPE28_MAX_STRINGS);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to initialize string table for TempProbeInfo[%u]. Status = %r\n",
+ __func__,
+ Index,
+ Status
+ ));
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ Description = 0;
+ if (TempProbeInfo[Index].Description[0]) {
+ Status = StringTableAddString (&StrTable, TempProbeInfo[Index].Description, &Description);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to add Description String %r\n", Status));
+ ASSERT (!EFI_ERROR (Status));
+ StringTableFree (&StrTable);
+ goto exitErrorBuildSmbiosType28Table;
+ }
+ }
+
+ SmbiosRecordSize = sizeof (SMBIOS_TABLE_TYPE28) + StringTableGetStringSetSize (&StrTable);
+ SmbiosRecord = (SMBIOS_TABLE_TYPE28 *)AllocateZeroPool (SmbiosRecordSize);
+ if (SmbiosRecord == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ StringTableFree (&StrTable);
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ // Set up the header
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_TEMPERATURE_PROBE;
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE28);
+
+ if (!IsValidTemperatureProbeStatus (
+ TempProbeInfo[Index].LocationAndStatus.TemperatureProbeStatus
+ ))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Invalid Temperature Probe Status 0x%x for TempProbeInfo[%u]\n",
+ __func__,
+ TempProbeInfo[Index].LocationAndStatus.TemperatureProbeStatus,
+ Index
+ ));
+ Status = EFI_INVALID_PARAMETER;
+ StringTableFree (&StrTable);
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ if (!IsValidTemperatureProbeLocation (
+ TempProbeInfo[Index].LocationAndStatus.TemperatureProbeSite
+ ))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Invalid Temperature Probe Location 0x%x for TempProbeInfo[%u]\n",
+ __func__,
+ TempProbeInfo[Index].LocationAndStatus.TemperatureProbeSite,
+ Index
+ ));
+ Status = EFI_INVALID_PARAMETER;
+ StringTableFree (&StrTable);
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ SmbiosRecord->Description = Description;
+ SmbiosRecord->LocationAndStatus = TempProbeInfo[Index].LocationAndStatus;
+ SmbiosRecord->MaximumValue = TempProbeInfo[Index].MaximumValue;
+ SmbiosRecord->MinimumValue = TempProbeInfo[Index].MinimumValue;
+ SmbiosRecord->Resolution = TempProbeInfo[Index].Resolution;
+ SmbiosRecord->Tolerance = TempProbeInfo[Index].Tolerance;
+ SmbiosRecord->Accuracy = TempProbeInfo[Index].Accuracy;
+ SmbiosRecord->OEMDefined = TempProbeInfo[Index].OemDefined;
+ SmbiosRecord->NominalValue = TempProbeInfo[Index].NominalValue;
+
+ Status = StringTablePublishStringSet (
+ &StrTable,
+ (CHAR8 *)(SmbiosRecord + 1),
+ SmbiosRecordSize - sizeof (SMBIOS_TABLE_TYPE28)
+ );
+ if (EFI_ERROR (Status)) {
+ StringTableFree (&StrTable);
+ goto exitErrorBuildSmbiosType28Table;
+ }
+
+ StringTableFree (&StrTable);
+
+ TableList[Index] = (SMBIOS_STRUCTURE *)SmbiosRecord;
+ CmObjectList[Index] = TempProbeInfo[Index].TemperatureProbeToken;
+ SmbiosRecord = NULL;
+ }
+
+ *Table = TableList;
+ *CmObjectToken = CmObjectList;
+ *TableCount = TempProbeCount;
+
+ return EFI_SUCCESS;
+exitErrorBuildSmbiosType28Table:
+ if (TableList != NULL) {
+ for (Index = 0; Index < TempProbeCount; Index++) {
+ if (TableList[Index] != NULL) {
+ FreePool (TableList[Index]);
+ }
+ }
+
+ FreePool (TableList);
+ }
+
+ if (CmObjectList != NULL) {
+ FreePool (CmObjectList);
+ }
+
+ if (SmbiosRecord != NULL) {
+ FreePool (SmbiosRecord);
+ }
+
+ return Status;
+}
+
+/** The interface for the SMBIOS Type28 Table Generator.
+*/
+STATIC
+CONST
+SMBIOS_TABLE_GENERATOR SmbiosType28Generator = {
+ // Generator ID
+ CREATE_STD_SMBIOS_TABLE_GEN_ID (EStdSmbiosTableIdType28),
+ // Generator Description
+ L"SMBIOS.TYPE28.GENERATOR",
+ // SMBIOS Table Type
+ EFI_SMBIOS_TYPE_TEMPERATURE_PROBE,
+ NULL,
+ NULL,
+ // Build table function.
+ BuildSmbiosType28TableEx,
+ // Free function.
+ FreeSmbiosType28TableEx,
+};
+
+/** 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
+SmbiosType28LibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RegisterSmbiosTableGenerator (&SmbiosType28Generator);
+ DEBUG ((
+ DEBUG_INFO,
+ "SMBIOS Type 28: 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
+SmbiosType28LibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DeregisterSmbiosTableGenerator (&SmbiosType28Generator);
+ DEBUG ((
+ DEBUG_INFO,
+ "SMBIOS Type 28: Deregister Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Lib.inf b/DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Lib.inf
new file mode 100644
index 0000000000..52a72aa939
--- /dev/null
+++ b/DynamicTablesPkg/Library/Smbios/SmbiosType28Lib/SmbiosType28Lib.inf
@@ -0,0 +1,29 @@
+## @file
+# SMBIOS Type28 Table Generator
+#
+# Copyright (c) 2026, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SmbiosType28LibArm
+ FILE_GUID = aeb393de-ec41-48af-8d92-d537fe5239e4
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = NULL|DXE_DRIVER
+ CONSTRUCTOR = SmbiosType28LibConstructor
+ DESTRUCTOR = SmbiosType28LibDestructor
+
+[Sources]
+ SmbiosType28Generator.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ MemoryAllocationLib
+ SmbiosStringTableLib