]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Platform/Dxe/MemorySubClass/MemorySubClass.c
QuarkPlatformPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Dxe / MemorySubClass / MemorySubClass.c
CommitLineData
b303605e
MK
1/** @file\r
2This is the driver that locates the MemoryConfigurationData Variable, if it\r
3exists, and reports the data to the DataHub.\r
4\r
5Copyright (c) 2013-2015 Intel Corporation.\r
6\r
0eb3de2e 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
b303605e
MK
8\r
9**/\r
10\r
11#include "MemorySubClass.h"\r
12\r
13extern UINT8 MemorySubClassStrings[];\r
14\r
15EFI_GUID gEfiMemorySubClassDriverGuid = EFI_MEMORY_SUBCLASS_DRIVER_GUID;\r
16\r
17EFI_STATUS\r
18MemorySubClassEntryPoint (\r
19 IN EFI_HANDLE ImageHandle,\r
20 IN EFI_SYSTEM_TABLE *SystemTable\r
21 )\r
22/*++\r
23\r
24 Routine Description:\r
25 This is the standard EFI driver point that detects whether there is a\r
26 MemoryConfigurationData Variable and, if so, reports memory configuration info\r
27 to the DataHub.\r
28\r
29 Arguments:\r
30 ImageHandle - Handle for the image of this driver\r
31 SystemTable - Pointer to the EFI System Table\r
32\r
33 Returns:\r
34 EFI_SUCCESS if the data is successfully reported\r
35 EFI_NOT_FOUND if the HOB list could not be located.\r
36\r
37--*/\r
38{\r
39// UINT8 Index;\r
40 UINTN DataSize;\r
41 UINT8 Dimm;\r
42 UINTN StringBufferSize;\r
43 UINT8 NumSlots;\r
44 UINTN DevLocStrLen;\r
45 UINTN BankLocStrLen;\r
46 UINTN ManuStrLen;\r
47 UINTN SerialNumStrLen;\r
48 UINTN AssertTagStrLen;\r
49 UINTN PartNumStrLen;\r
50 UINTN MemoryDeviceSize;\r
51 CHAR8* OptionalStrStart;\r
52 UINT16 ArrayInstance;\r
53 UINT64 DimmMemorySize;\r
54 UINT64 TotalMemorySize;\r
55 UINT32 Data;\r
56 UINT32 MemoryCapacity;\r
57 BOOLEAN MemoryDeviceSizeUnitMega;\r
58 EFI_STATUS Status;\r
59 EFI_STRING StringBuffer;\r
60 EFI_STRING DevLocStr;\r
61 EFI_STRING BankLocStr;\r
62 EFI_STRING ManuStr;\r
63 EFI_STRING SerialNumStr;\r
64 EFI_STRING AssertTagStr;\r
65 EFI_STRING PartNumStr;\r
66 EFI_HII_HANDLE HiiHandle;\r
67 EFI_SMBIOS_HANDLE MemArraySmbiosHandle;\r
68 EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;\r
69 EFI_SMBIOS_HANDLE MemDevSmbiosHandle;\r
70 EFI_SMBIOS_HANDLE MemDevMappedAddrSmbiosHandle;\r
71 EFI_SMBIOS_HANDLE MemModuleInfoSmbiosHandle;\r
72 SMBIOS_TABLE_TYPE6 *Type6Record;\r
73 SMBIOS_TABLE_TYPE16 *Type16Record;\r
74 SMBIOS_TABLE_TYPE17 *Type17Record;\r
75 SMBIOS_TABLE_TYPE19 *Type19Record;\r
76 SMBIOS_TABLE_TYPE20 *Type20Record;\r
77 EFI_SMBIOS_PROTOCOL *Smbios;\r
78 EFI_MEMORY_ARRAY_LINK_DATA ArrayLink;\r
79 EFI_MEMORY_ARRAY_LOCATION_DATA ArrayLocationData;\r
80 EFI_MEMORY_DEVICE_START_ADDRESS_DATA DeviceStartAddress;\r
81\r
82\r
83 DataSize = 0;\r
84 Dimm = 0;\r
85\r
86\r
87 //\r
88 // Allocate Buffers\r
89 //\r
90 StringBufferSize = (sizeof (CHAR16)) * 100;\r
91 StringBuffer = AllocateZeroPool (StringBufferSize);\r
92 ASSERT (StringBuffer != NULL);\r
93\r
94 //\r
95 // Locate dependent protocols\r
96 //\r
97 Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);\r
98 ASSERT_EFI_ERROR (Status);\r
99\r
100\r
101 //\r
102 // Add our default strings to the HII database. They will be modified later.\r
103 //\r
104 HiiHandle = HiiAddPackages (\r
105 &gEfiMemorySubClassDriverGuid,\r
106 NULL,\r
107 MemorySubClassStrings,\r
108 NULL\r
109 );\r
110 ASSERT (HiiHandle != NULL);\r
111\r
112 //\r
113 // Create physical array and associated data for all mainboard memory\r
114 // This will translate into a Type 16 SMBIOS Record\r
115 //\r
116 ArrayInstance = 1;\r
117\r
118 McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (0x3, 0x8);\r
119 TotalMemorySize = McD0PciCfg32 (QNC_ACCESS_PORT_MDR);\r
120\r
121 ArrayLocationData.MemoryArrayLocation = EfiMemoryArrayLocationSystemBoard;\r
122 ArrayLocationData.MemoryArrayUse = EfiMemoryArrayUseSystemMemory;\r
123\r
124 ArrayLocationData.MemoryErrorCorrection = EfiMemoryErrorCorrectionNone;\r
125\r
126 Data = 0x40000000;//(UINT32) RShiftU64(MemConfigData->RowInfo.MaxMemory, 10);\r
127\r
128 ArrayLocationData.MaximumMemoryCapacity.Exponent = (UINT16) LowBitSet32 (Data);\r
129 ArrayLocationData.MaximumMemoryCapacity.Value = (UINT16) (Data >> ArrayLocationData.MaximumMemoryCapacity.Exponent);\r
130\r
131 NumSlots = 2;// (UINT8)(MemConfigData->RowInfo.MaxRows >> 1);\r
132 ArrayLocationData.NumberMemoryDevices = (UINT16)(NumSlots);\r
133\r
134 //\r
135 // Report top level physical array to Type 16 SMBIOS Record\r
136 //\r
137 Type16Record = AllocatePool(sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);\r
138 ZeroMem(Type16Record, sizeof(SMBIOS_TABLE_TYPE16) + 1 + 1);\r
139\r
140 Type16Record->Hdr.Type = EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY;\r
141 Type16Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE16);\r
142 Type16Record->Hdr.Handle = 0;\r
143\r
144 Type16Record->Location = (UINT8)ArrayLocationData.MemoryArrayLocation;\r
145\r
146 Type16Record->Use = (UINT8)ArrayLocationData.MemoryArrayUse;\r
147\r
148 Type16Record->MemoryErrorCorrection = (UINT8)ArrayLocationData.MemoryErrorCorrection;\r
149\r
150 MemoryCapacity = (UINT32) ArrayLocationData.MaximumMemoryCapacity.Value * (1 << ((UINT32) ArrayLocationData.MaximumMemoryCapacity.Exponent - 10));\r
151 Type16Record->MaximumCapacity = MemoryCapacity;\r
152\r
153 Type16Record->MemoryErrorInformationHandle = 0xfffe;\r
154\r
155 Type16Record->NumberOfMemoryDevices = ArrayLocationData.NumberMemoryDevices;\r
156 //\r
157 // Don't change it. This handle will be referenced by type 17 records\r
158 //\r
159 MemArraySmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
160 Status = Smbios->Add (Smbios, NULL, &MemArraySmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type16Record);\r
161 FreePool(Type16Record);\r
162 ASSERT_EFI_ERROR (Status);\r
163\r
164 // Do associated data for each DIMM\r
165 //RowConfArray = &MemConfigData->RowConfArray;\r
166\r
167 //\r
168 // Get total memory size for the construction of smbios record type 19\r
169 //\r
170 //TotalMemorySize = 0;// MSG_BUS_READ(0x0208);\r
171\r
172 //\r
173 // Generate Memory Array Mapped Address info\r
174 //\r
175 Type19Record = AllocatePool(sizeof (SMBIOS_TABLE_TYPE19));\r
176 ZeroMem(Type19Record, sizeof(SMBIOS_TABLE_TYPE19));\r
177 Type19Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;\r
178 Type19Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);\r
179 Type19Record->Hdr.Handle = 0;\r
180 Type19Record->StartingAddress = 0;\r
181 Type19Record->EndingAddress = (UINT32)RShiftU64(TotalMemorySize, 10) - 1;\r
182 Type19Record->MemoryArrayHandle = MemArraySmbiosHandle;\r
183 Type19Record->PartitionWidth = (UINT8)(NumSlots);\r
184\r
185 //\r
186 // Generate Memory Array Mapped Address info (TYPE 19)\r
187 //\r
188 MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
189 Status = Smbios->Add (Smbios, NULL, &MemArrayMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type19Record);\r
190 FreePool(Type19Record);\r
191 ASSERT_EFI_ERROR (Status);\r
192\r
193\r
194 // Use SPD data to generate Device Type info\r
195 ZeroMem (&ArrayLink, sizeof (EFI_MEMORY_ARRAY_LINK_DATA));\r
196 ArrayLink.MemoryDeviceLocator = STRING_TOKEN(STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0);\r
197 ArrayLink.MemoryBankLocator = STRING_TOKEN(STR_MEMORY_SUBCLASS_DEVICE_LOCATOR_0);\r
198 ArrayLink.MemoryAssetTag = STRING_TOKEN(STR_MEMORY_SUBCLASS_UNKNOWN);\r
199 ArrayLink.MemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;\r
200 ArrayLink.MemoryArrayLink.Instance = ArrayInstance;\r
201 ArrayLink.MemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;\r
202 ArrayLink.MemorySubArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;\r
203 ArrayLink.MemorySubArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;\r
204 ArrayLink.MemoryFormFactor = EfiMemoryFormFactorChip;\r
205 ArrayLink.MemoryType = EfiMemoryTypeDdr2;\r
206\r
207\r
208 StrCpy (StringBuffer, L"NO DIMM,MEMROY DOWN");\r
209 ArrayLink.MemoryManufacturer = HiiSetString (\r
210 HiiHandle,\r
211 0,\r
212 StringBuffer,\r
213 NULL\r
214 );\r
215 ArrayLink.MemorySerialNumber = HiiSetString (\r
216 HiiHandle,\r
217 0,\r
218 StringBuffer,\r
219 NULL\r
220 );\r
221\r
222 ArrayLink.MemoryPartNumber = HiiSetString (\r
223 HiiHandle,\r
224 0,\r
225 StringBuffer,\r
226 NULL\r
227 );\r
228\r
229 //\r
230 // Hardcode value. Need to revise for different configuration.\r
231 //\r
232 ArrayLink.MemoryTotalWidth = 64;\r
233 ArrayLink.MemoryDataWidth = 64;\r
234\r
235 DimmMemorySize = TotalMemorySize;// MSG_BUS_READ(0x0208);\r
236\r
237 ArrayLink.MemoryDeviceSize.Exponent = (UINT16) LowBitSet64 (DimmMemorySize);\r
238 ArrayLink.MemoryDeviceSize.Value = (UINT16) RShiftU64(DimmMemorySize, ArrayLink.MemoryDeviceSize.Exponent);\r
239 ArrayLink.MemoryTypeDetail.Synchronous = 1;\r
240 Data = 800;\r
241 ArrayLink.MemorySpeed = *((EFI_EXP_BASE10_DATA *) &Data);\r
242\r
243\r
244\r
245 DevLocStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryDeviceLocator, NULL);\r
246 DevLocStrLen = StrLen(DevLocStr);\r
247 ASSERT(DevLocStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
248\r
249 BankLocStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryBankLocator, NULL);\r
250 BankLocStrLen = StrLen(BankLocStr);\r
251 ASSERT(BankLocStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
252\r
253 ManuStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryManufacturer, NULL);\r
254 ManuStrLen = StrLen(ManuStr);\r
255 ASSERT(ManuStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
256\r
257 SerialNumStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemorySerialNumber, NULL);\r
258 SerialNumStrLen = StrLen(SerialNumStr);\r
259 ASSERT(SerialNumStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
260\r
261 AssertTagStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryAssetTag, NULL);\r
262 AssertTagStrLen = StrLen(AssertTagStr);\r
263 ASSERT(AssertTagStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
264\r
265 PartNumStr = HiiGetPackageString(&gEfiMemorySubClassDriverGuid, ArrayLink.MemoryPartNumber, NULL);\r
266 PartNumStrLen = StrLen(PartNumStr);\r
267 ASSERT(PartNumStrLen <= SMBIOS_STRING_MAX_LENGTH);\r
268\r
269 //\r
270 // Report DIMM level memory module information to smbios (Type 6)\r
271 //\r
272 DataSize = sizeof(SMBIOS_TABLE_TYPE6) + DevLocStrLen + 1 + 1;\r
273 Type6Record = AllocatePool(DataSize);\r
274 ZeroMem(Type6Record, DataSize);\r
275 Type6Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_MODULE_INFORMATON;\r
276 Type6Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE6);\r
277 Type6Record->Hdr.Handle = 0;\r
278 Type6Record->SocketDesignation = 1;\r
279 if (ArrayLink.MemorySpeed.Value == 0) {\r
280 Type6Record->CurrentSpeed = 0;\r
281 } else {\r
282 //\r
283 // Memory speed is in ns unit\r
284 //\r
285 Type6Record->CurrentSpeed = (UINT8)(1000 / (ArrayLink.MemorySpeed.Value));\r
286 }\r
287 //\r
288 // Device Size\r
289 //\r
290 MemoryDeviceSize = (UINTN)(ArrayLink.MemoryDeviceSize.Value) * (UINTN)(1 << ArrayLink.MemoryDeviceSize.Exponent);\r
291 if (MemoryDeviceSize == 0) {\r
292 *(UINT8*)&(Type6Record->InstalledSize) = 0x7F;\r
293 *(UINT8*)&(Type6Record->EnabledSize) = 0x7F;\r
294 } else {\r
295 MemoryDeviceSize = (UINTN) RShiftU64 ((UINT64) MemoryDeviceSize, 21);\r
296 while (MemoryDeviceSize != 0) {\r
297 (*(UINT8*)&(Type6Record->InstalledSize))++;\r
298 (*(UINT8*)&(Type6Record->EnabledSize))++;\r
299 MemoryDeviceSize = (UINTN) RShiftU64 ((UINT64) MemoryDeviceSize,1);\r
300 }\r
301 }\r
302\r
303 if (ArrayLink.MemoryFormFactor == EfiMemoryFormFactorDimm ||\r
304 ArrayLink.MemoryFormFactor == EfiMemoryFormFactorFbDimm) {\r
305 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<8;\r
306 }\r
307 if (ArrayLink.MemoryFormFactor == EfiMemoryFormFactorSimm) {\r
308 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<7;\r
309 }\r
310 if (ArrayLink.MemoryType == EfiMemoryTypeSdram) {\r
311 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<10;\r
312 }\r
313 if (ArrayLink.MemoryTypeDetail.Edo == 1) {\r
314 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<4;\r
315 }\r
316 if (ArrayLink.MemoryTypeDetail.FastPaged == 1) {\r
317 *(UINT16*)&Type6Record->CurrentMemoryType |= 1<<3;\r
318 }\r
319 OptionalStrStart = (CHAR8 *)(Type6Record + 1);\r
320 UnicodeStrToAsciiStr(DevLocStr, OptionalStrStart);\r
321 MemModuleInfoSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
322 Status = Smbios->Add (Smbios, NULL, &MemModuleInfoSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type6Record);\r
323 FreePool(Type6Record);\r
324 ASSERT_EFI_ERROR (Status);\r
325 //\r
326 // Report DIMM level Device Type to smbios (Type 17)\r
327 //\r
328 DataSize = sizeof (SMBIOS_TABLE_TYPE17) + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1 + PartNumStrLen + 1 + 1;\r
329 Type17Record = AllocatePool(DataSize);\r
330 ZeroMem(Type17Record, DataSize);\r
331 Type17Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;\r
332 Type17Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE17);\r
333 Type17Record->Hdr.Handle = 0;\r
334\r
335 Type17Record->MemoryArrayHandle = MemArraySmbiosHandle;\r
336 Type17Record->MemoryErrorInformationHandle = 0xfffe;\r
337 Type17Record->TotalWidth = ArrayLink.MemoryTotalWidth;\r
338 Type17Record->DataWidth = ArrayLink.MemoryDataWidth;\r
339 //\r
340 // Device Size\r
341 //\r
342 MemoryDeviceSize = ((UINTN) ArrayLink.MemoryDeviceSize.Value) << (ArrayLink.MemoryDeviceSize.Exponent - 10);\r
343 MemoryDeviceSizeUnitMega = FALSE;\r
344 //\r
345 // kilo as unit\r
346 //\r
347 if (MemoryDeviceSize > 0xffff) {\r
348 MemoryDeviceSize = MemoryDeviceSize >> 10;\r
349 //\r
350 // Mega as unit\r
351 //\r
352 MemoryDeviceSizeUnitMega = TRUE;\r
353 }\r
354\r
355 MemoryDeviceSize = MemoryDeviceSize & 0x7fff;\r
356 if (MemoryDeviceSize != 0 && MemoryDeviceSizeUnitMega == FALSE) {\r
357 MemoryDeviceSize |= 0x8000;\r
358 }\r
359 Type17Record->Size = (UINT16)MemoryDeviceSize;\r
360\r
361 Type17Record->FormFactor = (UINT8)ArrayLink.MemoryFormFactor;\r
362 Type17Record->DeviceLocator = 1;\r
363 Type17Record->BankLocator = 2;\r
364 Type17Record->MemoryType = (UINT8)ArrayLink.MemoryType;\r
365 CopyMem (\r
366 (UINT8 *) &Type17Record->TypeDetail,\r
367 &ArrayLink.MemoryTypeDetail,\r
368 2\r
369 );\r
370\r
371 Type17Record->Speed = ArrayLink.MemorySpeed.Value;\r
372 Type17Record->Manufacturer = 3;\r
373 Type17Record->SerialNumber = 4;\r
374 Type17Record->AssetTag = 5;\r
375 Type17Record->PartNumber = 6;\r
376 //\r
377 // temporary solution for save device label information.\r
378 //\r
379 Type17Record->Attributes = (UINT8)(Dimm + 1);\r
380\r
381 OptionalStrStart = (CHAR8 *)(Type17Record + 1);\r
382 UnicodeStrToAsciiStr(DevLocStr, OptionalStrStart);\r
383 UnicodeStrToAsciiStr(BankLocStr, OptionalStrStart + DevLocStrLen + 1);\r
384 UnicodeStrToAsciiStr(ManuStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1);\r
385 UnicodeStrToAsciiStr(SerialNumStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1);\r
386 UnicodeStrToAsciiStr(AssertTagStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1);\r
387 UnicodeStrToAsciiStr(PartNumStr, OptionalStrStart + DevLocStrLen + 1 + BankLocStrLen + 1 + ManuStrLen + 1 + SerialNumStrLen + 1 + AssertTagStrLen + 1);\r
388 MemDevSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
389 Status = Smbios->Add (Smbios, NULL, &MemDevSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type17Record);\r
390 FreePool(Type17Record);\r
391 ASSERT_EFI_ERROR (Status);\r
392\r
393 //\r
394 // Generate Memory Device Mapped Address info\r
395 //\r
396 ZeroMem(&DeviceStartAddress, sizeof(EFI_MEMORY_DEVICE_START_ADDRESS_DATA));\r
397 DeviceStartAddress.MemoryDeviceStartAddress = 0;\r
398 DeviceStartAddress.MemoryDeviceEndAddress = DeviceStartAddress.MemoryDeviceStartAddress + DimmMemorySize-1;\r
399 DeviceStartAddress.PhysicalMemoryDeviceLink.ProducerName = gEfiMemorySubClassDriverGuid;\r
400 DeviceStartAddress.PhysicalMemoryDeviceLink.Instance = ArrayInstance;\r
401 DeviceStartAddress.PhysicalMemoryDeviceLink.SubInstance = (UINT16)(Dimm + 1);\r
402 DeviceStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemorySubClassDriverGuid;\r
403 DeviceStartAddress.PhysicalMemoryArrayLink.Instance = ArrayInstance;\r
404 DeviceStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;\r
405\r
406 //\r
407 // Single channel mode\r
408 //\r
409 DeviceStartAddress.MemoryDevicePartitionRowPosition = 0x01;\r
410 DeviceStartAddress.MemoryDeviceInterleavePosition = 0x00;\r
411 DeviceStartAddress.MemoryDeviceInterleaveDataDepth = 0x00;\r
412\r
413 //\r
414 // Generate Memory Device Mapped Address info (TYPE 20)\r
415 //\r
416 Type20Record = AllocatePool(sizeof (SMBIOS_TABLE_TYPE20));\r
417 ZeroMem(Type20Record, sizeof (SMBIOS_TABLE_TYPE20));\r
418 Type20Record->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS;\r
419 Type20Record->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE20);\r
420 Type20Record->Hdr.Handle = 0;\r
421\r
422 Type20Record->StartingAddress = (UINT32)RShiftU64 (DeviceStartAddress.MemoryDeviceStartAddress, 10);\r
423 Type20Record->EndingAddress = (UINT32)RShiftU64 (DeviceStartAddress.MemoryDeviceEndAddress, 10);\r
424 Type20Record->MemoryDeviceHandle = MemDevSmbiosHandle;\r
425 Type20Record->MemoryArrayMappedAddressHandle = MemArrayMappedAddrSmbiosHandle;\r
426 Type20Record->PartitionRowPosition = DeviceStartAddress.MemoryDevicePartitionRowPosition;\r
427 Type20Record->InterleavePosition = DeviceStartAddress.MemoryDeviceInterleavePosition;\r
428 Type20Record->InterleavedDataDepth = DeviceStartAddress.MemoryDeviceInterleaveDataDepth;\r
429 MemDevMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
430 Status = Smbios->Add (Smbios, NULL, &MemDevMappedAddrSmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) Type20Record);\r
431 FreePool(Type20Record);\r
432 ASSERT_EFI_ERROR (Status);\r
433\r
434 return Status;\r
435}\r