Skip to content

Commit 777b9c1

Browse files
committed
DynamicTablesPkg: Smbios Memory Array Mapped Address (Type 19)
Add the Generator library for SMBIOS Table Type 19 - Memory Array Mapped Address. Signed-off-by: Girish Mahadevan <[email protected]> Reviewed-by: Jeff Brasen <[email protected]>
1 parent 562686e commit 777b9c1

File tree

3 files changed

+414
-0
lines changed

3 files changed

+414
-0
lines changed

DynamicTablesPkg/Include/SmbiosNameSpaceObjects.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,20 @@ typedef struct CmSmbiosPhysicalMemoryArray {
151151
CM_OBJECT_TOKEN PhysMemArrayToken;
152152
} CM_SMBIOS_PHYSICAL_MEMORY_ARRAY;
153153

154+
/** A structure that describes the Memory Array Mapped Address.
155+
156+
SMBIOS Specification v3.6.0 Type 19
157+
158+
ID: ESmbiosObjPhysicalMemoryArray
159+
**/
160+
typedef struct CmSmbiosMemArrayMappedAddress {
161+
EFI_PHYSICAL_ADDRESS StartingAddress;
162+
EFI_PHYSICAL_ADDRESS EndingAddress;
163+
CM_OBJECT_TOKEN MemoryArrayMappedAddressToken;
164+
UINT8 NumMemDevices;
165+
CM_OBJECT_TOKEN PhysMemArrayToken;
166+
} CM_SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS;
167+
154168
#pragma pack()
155169

156170
#endif // SMBIOS_NAMESPACE_OBJECTS_H_
Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
/** @file
2+
SMBIOS Type19 Table Generator.
3+
4+
Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5+
Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
6+
7+
SPDX-License-Identifier: BSD-2-Clause-Patent
8+
**/
9+
10+
#include <Library/BaseLib.h>
11+
#include <Library/BaseMemoryLib.h>
12+
#include <Library/DebugLib.h>
13+
#include <Library/PrintLib.h>
14+
#include <Library/MemoryAllocationLib.h>
15+
#include <Library/UefiBootServicesTableLib.h>
16+
#include <Library/SmbiosStringTableLib.h>
17+
18+
// Module specific include files.
19+
#include <ConfigurationManagerObject.h>
20+
#include <ConfigurationManagerHelper.h>
21+
#include <Protocol/ConfigurationManagerProtocol.h>
22+
#include <Protocol/DynamicTableFactoryProtocol.h>
23+
#include <Protocol/Smbios.h>
24+
#include <IndustryStandard/SmBios.h>
25+
26+
/** This macro expands to a function that retrieves the Memory Device
27+
information from the Configuration Manager.
28+
*/
29+
GET_OBJECT_LIST (
30+
EObjNameSpaceSmbios,
31+
ESmbiosObjMemoryArrayMappedAddress,
32+
CM_SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS
33+
)
34+
35+
#define EXTENDED_ADDRESS_THRESHOLD (0xFFFFFFFFL)
36+
37+
/**
38+
* Free any resources allocated when installing SMBIOS Type19 table.
39+
*
40+
* @param [in] This Pointer to the SMBIOS table generator.
41+
* @param [in] TableFactoryProtocol Pointer to the SMBIOS Table Factory
42+
Protocol interface.
43+
44+
* @param [in] SmbiosTableInfo Pointer to the SMBIOS table information.
45+
* @param [in] CfgMgrProtocol Pointer to the Configuration Manager
46+
Protocol interface.
47+
* @param [in] Table Pointer to the SMBIOS table.
48+
* @param [in] CmObjectToken Pointer to the CM ObjectToken Array.
49+
* @param [in] TableCount Number of SMBIOS tables.
50+
51+
* @retval EFI_SUCCESS Table generated successfully.
52+
* @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
53+
Manager is less than the Object size for
54+
the requested object.
55+
* @retval EFI_INVALID_PARAMETER A parameter is invalid.
56+
* @retval EFI_NOT_FOUND Could not find information.
57+
* @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
58+
* @retval EFI_UNSUPPORTED Unsupported configuration.
59+
**/
60+
STATIC
61+
EFI_STATUS
62+
FreeSmbiosType19TableEx (
63+
IN CONST SMBIOS_TABLE_GENERATOR *CONST This,
64+
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,
65+
IN CONST CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo,
66+
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
67+
IN SMBIOS_STRUCTURE ***CONST Table,
68+
IN CM_OBJECT_TOKEN **CmObjectToken,
69+
IN CONST UINTN TableCount
70+
)
71+
{
72+
UINTN Index;
73+
SMBIOS_STRUCTURE **TableList;
74+
75+
TableList = *Table;
76+
for (Index = 0; Index < TableCount; Index++) {
77+
if (TableList[Index] != NULL) {
78+
FreePool (TableList[Index]);
79+
}
80+
}
81+
82+
if (*CmObjectToken != NULL) {
83+
FreePool (*CmObjectToken);
84+
}
85+
86+
if (TableList != NULL) {
87+
FreePool (TableList);
88+
}
89+
90+
return EFI_SUCCESS;
91+
}
92+
93+
/**
94+
* Add the SMBIOS table handle reference to the Physical Array Table.
95+
*
96+
* @param [in] TableFactoryProtocol Pointer to the SMBIOS Table Factory.
97+
* @param [in] CmObjToken CM Token to lookup..
98+
* @param [out] SmbiosRecord SMBIOS record to update.
99+
**/
100+
STATIC
101+
VOID
102+
AddPhysArrHandle (
103+
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,
104+
IN CM_OBJECT_TOKEN CmObjToken,
105+
OUT SMBIOS_TABLE_TYPE19 *SmbiosRecord
106+
)
107+
{
108+
EFI_SMBIOS_HANDLE PhysMemArrHandle;
109+
SMBIOS_HANDLE_MAP *HandleMap;
110+
111+
HandleMap = TableFactoryProtocol->GetSmbiosHandle (CmObjToken);
112+
if (HandleMap == NULL) {
113+
DEBUG ((DEBUG_ERROR, "%a:Failed to get SMBIOS Handle\n", __FUNCTION__));
114+
PhysMemArrHandle = 0;
115+
} else {
116+
PhysMemArrHandle = HandleMap->SmbiosTblHandle;
117+
}
118+
119+
SmbiosRecord->MemoryArrayHandle = PhysMemArrHandle;
120+
}
121+
122+
/**
123+
* Update the Address encoding for Type 19.
124+
*
125+
* @param [in] StartAddress Starting memory address covered by the device.
126+
* @param [in] EndAddress Ending memory address covered by the device.
127+
* @param [out] SmbiosRecord SMBIOS record to update.
128+
**/
129+
STATIC
130+
VOID
131+
UpdateSmbiosType19Address (
132+
IN UINT64 StartAddress,
133+
IN UINT64 EndAddress,
134+
OUT SMBIOS_TABLE_TYPE19 *SmbiosRecord
135+
)
136+
{
137+
UINT64 StartingAddressKb = StartAddress / SIZE_1KB;
138+
UINT64 EndingAddressKb = EndAddress / SIZE_1KB;
139+
140+
if (StartingAddressKb >= EXTENDED_ADDRESS_THRESHOLD) {
141+
SmbiosRecord->StartingAddress = EXTENDED_ADDRESS_THRESHOLD;
142+
SmbiosRecord->EndingAddress = EXTENDED_ADDRESS_THRESHOLD;
143+
SmbiosRecord->ExtendedStartingAddress = StartAddress;
144+
SmbiosRecord->ExtendedEndingAddress = EndAddress;
145+
} else {
146+
SmbiosRecord->StartingAddress = StartingAddressKb;
147+
SmbiosRecord->EndingAddress = EndingAddressKb;
148+
}
149+
}
150+
151+
/** Construct SMBIOS Type19 Table describing memory devices.
152+
153+
If this function allocates any resources then they must be freed
154+
in the FreeXXXXTableResources function.
155+
156+
@param [in] This Pointer to the SMBIOS table generator.
157+
@param [in] SmbiosTableInfo Pointer to the SMBIOS table information.
158+
@param [in] CfgMgrProtocol Pointer to the Configuration Manager
159+
Protocol interface.
160+
@param [out] Table Pointer to the SMBIOS table.
161+
@param [out] CmObjectToken Pointer to the CM Object Token Array.
162+
@param [out] TableCount Number of tables installed.
163+
164+
@retval EFI_SUCCESS Table generated successfully.
165+
@retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
166+
Manager is less than the Object size for
167+
the requested object.
168+
@retval EFI_INVALID_PARAMETER A parameter is invalid.
169+
@retval EFI_NOT_FOUND Could not find information.
170+
@retval EFI_OUT_OF_RESOURCES Could not allocate memory.
171+
@retval EFI_UNSUPPORTED Unsupported configuration.
172+
**/
173+
STATIC
174+
EFI_STATUS
175+
BuildSmbiosType19TableEx (
176+
IN CONST SMBIOS_TABLE_GENERATOR *This,
177+
IN CONST EDKII_DYNAMIC_TABLE_FACTORY_PROTOCOL *CONST TableFactoryProtocol,
178+
IN CM_STD_OBJ_SMBIOS_TABLE_INFO *CONST SmbiosTableInfo,
179+
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
180+
OUT SMBIOS_STRUCTURE ***Table,
181+
OUT CM_OBJECT_TOKEN **CmObjectToken,
182+
OUT UINTN *CONST TableCount
183+
)
184+
{
185+
EFI_STATUS Status;
186+
UINT32 NumMemMap;
187+
SMBIOS_STRUCTURE **TableList;
188+
CM_OBJECT_TOKEN *CmObjectList;
189+
CM_SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS *MemoryMapInfo;
190+
SMBIOS_TABLE_TYPE19 *SmbiosRecord;
191+
UINTN Index;
192+
193+
ASSERT (This != NULL);
194+
ASSERT (SmbiosTableInfo != NULL);
195+
ASSERT (CfgMgrProtocol != NULL);
196+
ASSERT (Table != NULL);
197+
ASSERT (TableCount != NULL);
198+
ASSERT (SmbiosTableInfo->TableGeneratorId == This->GeneratorID);
199+
200+
if ((This == NULL) || (SmbiosTableInfo == NULL) || (CfgMgrProtocol == NULL) ||
201+
(Table == NULL) || (TableCount == NULL) ||
202+
(SmbiosTableInfo->TableGeneratorId != This->GeneratorID))
203+
{
204+
DEBUG ((DEBUG_ERROR, "%a:Invalid Paramater\n ", __FUNCTION__));
205+
return EFI_INVALID_PARAMETER;
206+
}
207+
208+
*Table = NULL;
209+
Status = GetESmbiosObjMemoryArrayMappedAddress (
210+
CfgMgrProtocol,
211+
CM_NULL_TOKEN,
212+
&MemoryMapInfo,
213+
&NumMemMap
214+
);
215+
if (EFI_ERROR (Status)) {
216+
DEBUG ((
217+
DEBUG_ERROR,
218+
"Failed to get Memory Devices CM Object %r\n",
219+
Status
220+
));
221+
return Status;
222+
}
223+
224+
TableList = (SMBIOS_STRUCTURE **)AllocateZeroPool (sizeof (SMBIOS_STRUCTURE *) * NumMemMap);
225+
if (TableList == NULL) {
226+
DEBUG ((
227+
DEBUG_ERROR,
228+
"%a: Failed to alloc memory for %u devices table\n",
229+
__FUNCTION__,
230+
NumMemMap
231+
));
232+
Status = EFI_OUT_OF_RESOURCES;
233+
goto exitBuildSmbiosType19TableEx;
234+
}
235+
236+
CmObjectList = (CM_OBJECT_TOKEN *)AllocateZeroPool (sizeof (CM_OBJECT_TOKEN *) * NumMemMap);
237+
if (CmObjectList == NULL) {
238+
DEBUG ((
239+
DEBUG_ERROR,
240+
"%a: Failed to alloc memory for %u CMObjects\n",
241+
__FUNCTION__,
242+
NumMemMap
243+
));
244+
Status = EFI_OUT_OF_RESOURCES;
245+
goto exitBuildSmbiosType19TableEx;
246+
}
247+
248+
for (Index = 0; Index < NumMemMap; Index++) {
249+
/**
250+
* Per Spec each structure is terminated by a double-NULL if there are no
251+
* strings.
252+
*/
253+
SmbiosRecord = (SMBIOS_TABLE_TYPE19 *)AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE19) + 1 + 1);
254+
if (SmbiosRecord == NULL) {
255+
Status = EFI_OUT_OF_RESOURCES;
256+
goto exitBuildSmbiosType19TableEx;
257+
}
258+
259+
UpdateSmbiosType19Address (
260+
MemoryMapInfo[Index].StartingAddress,
261+
MemoryMapInfo[Index].EndingAddress,
262+
SmbiosRecord
263+
);
264+
SmbiosRecord->PartitionWidth = MemoryMapInfo[Index].NumMemDevices;
265+
// Is there a reference to a Physical Array Device.
266+
if (MemoryMapInfo[Index].PhysMemArrayToken != CM_NULL_TOKEN) {
267+
AddPhysArrHandle (
268+
TableFactoryProtocol,
269+
MemoryMapInfo[Index].PhysMemArrayToken,
270+
SmbiosRecord
271+
);
272+
}
273+
274+
// setup the header
275+
SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
276+
SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE19);
277+
TableList[Index] = (SMBIOS_STRUCTURE *)SmbiosRecord;
278+
CmObjectList[Index] = MemoryMapInfo[Index].MemoryArrayMappedAddressToken;
279+
}
280+
281+
*Table = TableList;
282+
*CmObjectToken = CmObjectList;
283+
*TableCount = NumMemMap;
284+
285+
exitBuildSmbiosType19TableEx:
286+
return Status;
287+
}
288+
289+
/** The interface for the SMBIOS Type17 Table Generator.
290+
*/
291+
STATIC
292+
CONST
293+
SMBIOS_TABLE_GENERATOR SmbiosType19Generator = {
294+
// Generator ID
295+
CREATE_STD_SMBIOS_TABLE_GEN_ID (EStdSmbiosTableIdType19),
296+
// Generator Description
297+
L"SMBIOS.TYPE19.GENERATOR",
298+
// SMBIOS Table Type
299+
EFI_SMBIOS_TYPE_MEMORY_DEVICE,
300+
NULL,
301+
NULL,
302+
// Build table function Extended.
303+
BuildSmbiosType19TableEx,
304+
// Free function Extended.
305+
FreeSmbiosType19TableEx
306+
};
307+
308+
/** Register the Generator with the SMBIOS Table Factory.
309+
310+
@param [in] ImageHandle The handle to the image.
311+
@param [in] SystemTable Pointer to the System Table.
312+
313+
@retval EFI_SUCCESS The Generator is registered.
314+
@retval EFI_INVALID_PARAMETER A parameter is invalid.
315+
@retval EFI_ALREADY_STARTED The Generator for the Table ID
316+
is already registered.
317+
**/
318+
EFI_STATUS
319+
EFIAPI
320+
SmbiosType19LibConstructor (
321+
IN EFI_HANDLE ImageHandle,
322+
IN EFI_SYSTEM_TABLE *SystemTable
323+
)
324+
{
325+
EFI_STATUS Status;
326+
327+
Status = RegisterSmbiosTableGenerator (&SmbiosType19Generator);
328+
DEBUG ((
329+
DEBUG_INFO,
330+
"SMBIOS Type 19: Register Generator. Status = %r\n",
331+
Status
332+
));
333+
ASSERT_EFI_ERROR (Status);
334+
335+
return Status;
336+
}
337+
338+
/** Deregister the Generator from the SMBIOS Table Factory.
339+
340+
@param [in] ImageHandle The handle to the image.
341+
@param [in] SystemTable Pointer to the System Table.
342+
343+
@retval EFI_SUCCESS The Generator is deregistered.
344+
@retval EFI_INVALID_PARAMETER A parameter is invalid.
345+
@retval EFI_NOT_FOUND The Generator is not registered.
346+
**/
347+
EFI_STATUS
348+
EFIAPI
349+
SmbiosType19LibDestructor (
350+
IN EFI_HANDLE ImageHandle,
351+
IN EFI_SYSTEM_TABLE *SystemTable
352+
)
353+
{
354+
EFI_STATUS Status;
355+
356+
Status = DeregisterSmbiosTableGenerator (&SmbiosType19Generator);
357+
DEBUG ((
358+
DEBUG_INFO,
359+
"SMBIOS Type19: Deregister Generator. Status = %r\n",
360+
Status
361+
));
362+
ASSERT_EFI_ERROR (Status);
363+
return Status;
364+
}

0 commit comments

Comments
 (0)