1 /** @file
2   Routines that support Memory SubClass data records translation.
3 
4 Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "Thunk.h"
16 
17 /**
18   Field Filling Function for Memory SubClass record type 2 -- Physical Memory
19   Array.
20 
21   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
22   @param Offset           Offset of SMBIOS record which RecordData will be filled.
23   @param RecordData       RecordData buffer will be filled.
24   @param RecordDataSize   The size of RecordData buffer.
25 
26   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
27 **/
28 EFI_STATUS
SmbiosFldMemoryType2(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)29 SmbiosFldMemoryType2 (
30   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
31   IN      UINT32                    Offset,
32   IN      VOID                      *RecordData,
33   IN      UINT32                    RecordDataSize
34   )
35 {
36   EFI_STATUS                            Status;
37   EFI_MEMORY_ARRAY_LOCATION_DATA        *PhyMemArray;
38   FRAMEWORK_MEMORY_ARRAY_LOCATION_DATA  *FrameworkPhyMemArray;
39   UINT32                                MemoryCapacity;
40   UINT16                                NumberMemoryDevices;
41   UINT16                                Test16;
42 
43   Status      = EFI_SUCCESS;
44   PhyMemArray = (EFI_MEMORY_ARRAY_LOCATION_DATA *) RecordData;
45   FrameworkPhyMemArray = (FRAMEWORK_MEMORY_ARRAY_LOCATION_DATA *) RecordData;
46 
47   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE16, Location))  = (UINT8) (PhyMemArray->MemoryArrayLocation);
48   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE16, Use))  = (UINT8) (PhyMemArray->MemoryArrayUse);
49   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE16, MemoryErrorCorrection))  = (UINT8) (PhyMemArray->MemoryErrorCorrection);
50 
51   if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
52     MemoryCapacity = (UINT32) (((UINTN) PhyMemArray->MaximumMemoryCapacity.Value) << PhyMemArray->MaximumMemoryCapacity.Exponent);
53     NumberMemoryDevices = PhyMemArray->NumberMemoryDevices;
54   } else {
55     //
56     // Support EDk/Framework defined Data strucutre.
57     //
58     MemoryCapacity      = FrameworkPhyMemArray->MaximumMemoryCapacity;
59     NumberMemoryDevices = FrameworkPhyMemArray->NumberMemoryDevices;
60   }
61 
62   CopyMem (
63     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE16, MaximumCapacity),
64     &MemoryCapacity,
65     4
66     );
67 
68   Test16 = 0xfffe;
69   CopyMem (
70     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE16, MemoryErrorInformationHandle),
71     &Test16,
72     2
73     );
74 
75   CopyMem (
76     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE16, NumberOfMemoryDevices),
77     &NumberMemoryDevices,
78     2
79     );
80 
81   return Status;
82 }
83 
84 /**
85   Field Filling Function for Memory SubClass record type 3 -
86   - Memory Device: SMBIOS Type 17
87 
88   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
89   @param Offset           Offset of SMBIOS record which RecordData will be filled.
90   @param RecordData       RecordData buffer will be filled.
91   @param RecordDataSize   The size of RecordData buffer.
92 
93   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
94 **/
95 EFI_STATUS
SmbiosFldMemoryType3(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)96 SmbiosFldMemoryType3 (
97   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
98   IN      UINT32                    Offset,
99   IN      VOID                      *RecordData,
100   IN      UINT32                    RecordDataSize
101   )
102 {
103   EFI_MEMORY_ARRAY_LINK_DATA       *MemDevice;
104   FRAMEWORK_MEMORY_ARRAY_LINK_DATA *FrameworkMemDevice;
105   UINT64                           MemoryDeviceSize;
106   BOOLEAN                          MemoryDeviceSizeUnitMega;
107   UINT16                           MemoryDeviceSpeed;
108   UINT16                           MemoryDeviceExponent;
109   UINT16                           Test16;
110 
111   MemDevice = (EFI_MEMORY_ARRAY_LINK_DATA *) RecordData;
112   FrameworkMemDevice = (FRAMEWORK_MEMORY_ARRAY_LINK_DATA *) RecordData;
113   MemoryDeviceSpeed  = 0;
114   MemoryDeviceExponent = 0;
115 
116   //
117   // Memory Device Locator
118   //
119   SmbiosFldString (
120     StructureNode,
121     OFFSET_OF (SMBIOS_TABLE_TYPE17, DeviceLocator),
122     &(MemDevice->MemoryDeviceLocator),
123     sizeof (STRING_REF)
124     );
125 
126   //
127   // Memory Bank Locator
128   //
129   SmbiosFldString (
130     StructureNode,
131     OFFSET_OF (SMBIOS_TABLE_TYPE17, BankLocator),
132     &(MemDevice->MemoryBankLocator),
133     sizeof (STRING_REF)
134     );
135 
136   //
137   // Memory Manufacturer
138   //
139   SmbiosFldString (
140     StructureNode,
141     OFFSET_OF (SMBIOS_TABLE_TYPE17, Manufacturer),
142     &(MemDevice->MemoryManufacturer),
143     sizeof (STRING_REF)
144     );
145 
146   //
147   // Memory Serial Number
148   //
149   SmbiosFldString (
150     StructureNode,
151     OFFSET_OF (SMBIOS_TABLE_TYPE17, SerialNumber),
152     &(MemDevice->MemorySerialNumber),
153     sizeof (STRING_REF)
154     );
155 
156   //
157   // Memory Asset Tag
158   //
159   SmbiosFldString (
160     StructureNode,
161     OFFSET_OF (SMBIOS_TABLE_TYPE17, AssetTag),
162     &(MemDevice->MemoryAssetTag),
163     sizeof (STRING_REF)
164     );
165 
166   //
167   // Memory Part Number
168   //
169   SmbiosFldString (
170     StructureNode,
171     OFFSET_OF (SMBIOS_TABLE_TYPE17, PartNumber),
172     &(MemDevice->MemoryPartNumber),
173     sizeof (STRING_REF)
174     );
175 
176   //
177   // Memory Array Link
178   //
179   SmbiosFldInterLink (
180     StructureNode,
181     (UINT16) OFFSET_OF (SMBIOS_TABLE_TYPE17, MemoryArrayHandle),
182     16, // SMBIOS type 16
183     &MemDevice->MemoryArrayLink,
184     &gEfiMemorySubClassGuid
185     );
186 
187   //
188   // Set Memory Error Information Handle to Not supported
189   //
190   Test16 = 0xfffe;
191   CopyMem (
192     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE17, MemoryErrorInformationHandle),
193     &Test16,
194     sizeof (EFI_SMBIOS_HANDLE)
195     );
196 
197   //
198   // Total width
199   //
200   CopyMem (
201     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, TotalWidth),
202     &MemDevice->MemoryTotalWidth,
203     2
204     );
205 
206   //
207   // Data Width
208   //
209   CopyMem (
210     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, DataWidth),
211     &MemDevice->MemoryDataWidth,
212     2
213     );
214 
215   //
216   // Device Size
217   //
218   if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
219     //
220     // Form Factor
221     //
222     CopyMem (
223       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, FormFactor),
224       &MemDevice->MemoryFormFactor,
225       1
226       );
227 
228     //
229     // Device Set
230     //
231     CopyMem (
232       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, DeviceSet),
233       &MemDevice->MemoryDeviceSet,
234       1
235       );
236 
237     //
238     // Type
239     //
240     CopyMem (
241       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, MemoryType),
242       &MemDevice->MemoryType,
243       1
244       );
245 
246     //
247     // Type Detail
248     //
249     CopyMem (
250       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, TypeDetail),
251       &MemDevice->MemoryTypeDetail,
252       2
253       );
254 
255     //
256     // Speed
257     //
258     MemoryDeviceSpeed    = MemDevice->MemorySpeed.Value;
259     MemoryDeviceExponent = MemDevice->MemorySpeed.Exponent;
260     while (MemoryDeviceExponent-- > 0) {
261       MemoryDeviceSpeed = (UINT16) (MemoryDeviceSpeed * 10);
262     }
263 
264     CopyMem (
265       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, Speed),
266       &MemoryDeviceSpeed,
267       2
268       );
269 
270     MemoryDeviceSize = (UINT64) (((UINTN) MemDevice->MemoryDeviceSize.Value) << MemDevice->MemoryDeviceSize.Exponent);
271   } else {
272     //
273     // Form Factor
274     //
275     CopyMem (
276       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, FormFactor),
277       &FrameworkMemDevice->MemoryFormFactor,
278       1
279       );
280 
281     //
282     // Device Set
283     //
284     CopyMem (
285       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, DeviceSet),
286       &FrameworkMemDevice->MemoryDeviceSet,
287       1
288       );
289 
290     //
291     // Type
292     //
293     CopyMem (
294       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, MemoryType),
295       &FrameworkMemDevice->MemoryType,
296       1
297       );
298 
299     //
300     // Type Detail
301     //
302     CopyMem (
303       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, TypeDetail),
304       &FrameworkMemDevice->MemoryTypeDetail,
305       2
306       );
307 
308     //
309     // Speed
310     //
311     CopyMem (
312       (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, Speed),
313       &FrameworkMemDevice->MemorySpeed,
314       2
315       );
316 
317     MemoryDeviceSize = FrameworkMemDevice->MemoryDeviceSize;
318   }
319 
320   MemoryDeviceSizeUnitMega  = FALSE;
321   MemoryDeviceSize          = RShiftU64 (MemoryDeviceSize, 10);
322   //
323   // kilo as unit
324   //
325   if (MemoryDeviceSize > 0xffff) {
326     MemoryDeviceSize = RShiftU64 (MemoryDeviceSize, 10);
327     //
328     // Mega as unit
329     //
330     MemoryDeviceSizeUnitMega = TRUE;
331   }
332 
333   MemoryDeviceSize = MemoryDeviceSize & 0x7fff;
334   if (MemoryDeviceSize != 0 && !MemoryDeviceSizeUnitMega) {
335     MemoryDeviceSize |= 0x8000;
336   }
337 
338   CopyMem (
339     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE17, Size),
340     &MemoryDeviceSize,
341     2
342     );
343 
344   return EFI_SUCCESS;
345 }
346 
347 /**
348   Field Filling Function for Memory SubClass record type 3 -
349   - Memory Device: SMBIOS Type 6
350 
351   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
352   @param Offset           Offset of SMBIOS record which RecordData will be filled.
353   @param RecordData       RecordData buffer will be filled.
354   @param RecordDataSize   The size of RecordData buffer.
355 
356   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
357 **/
358 EFI_STATUS
SmbiosFldSMBIOSType6(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)359 SmbiosFldSMBIOSType6 (
360   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
361   IN      UINT32                    Offset,
362   IN      VOID                      *RecordData,
363   IN      UINT32                    RecordDataSize
364   )
365 {
366   EFI_MEMORY_ARRAY_LINK_DATA       *MemDevice;
367   UINT64                           MemoryDeviceSize;
368   UINT8                            MemSize;
369   UINT16                           MemType;
370   UINT8                            MemSpeed;
371   FRAMEWORK_MEMORY_ARRAY_LINK_DATA *FrameworkMemDevice;
372   UINT16                           MemoryDeviceSpeed;
373   UINT16                           MemoryDeviceExponent;
374 
375   MemDevice            = (EFI_MEMORY_ARRAY_LINK_DATA *) RecordData;
376   FrameworkMemDevice   = (FRAMEWORK_MEMORY_ARRAY_LINK_DATA *) RecordData;
377   MemoryDeviceExponent = 0;
378 
379   //
380   // Memory Device Locator
381   //
382   SmbiosFldString (
383     StructureNode,
384     OFFSET_OF (SMBIOS_TABLE_TYPE6, SocketDesignation),
385     &(MemDevice->MemoryDeviceLocator),
386     2
387     );
388 
389   if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
390     MemoryDeviceSpeed    = MemDevice->MemorySpeed.Value;
391     MemoryDeviceExponent = MemDevice->MemorySpeed.Exponent;
392     while (MemoryDeviceExponent-- > 0) {
393       MemoryDeviceSpeed = (UINT16) (MemoryDeviceSpeed * 10);
394     }
395     MemoryDeviceSize = (UINT64) (((UINTN) MemDevice->MemoryDeviceSize.Value) << MemDevice->MemoryDeviceSize.Exponent);
396   } else {
397     //
398     // Support EDk/Framework defined Data strucutre.
399     //
400     MemoryDeviceSpeed = FrameworkMemDevice->MemorySpeed;
401     MemoryDeviceSize  = FrameworkMemDevice->MemoryDeviceSize;
402   }
403 
404   if (MemoryDeviceSpeed == 0) {
405     MemSpeed = 0;
406   } else {
407     //
408     // Memory speed is in ns unit
409     //
410     MemSpeed = (UINT8)(1000 / MemoryDeviceSpeed);
411   }
412 
413   CopyMem (
414    (UINT8*)StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE6, CurrentSpeed),
415    &MemSpeed,
416    1
417   );
418 
419 
420   //
421   // Device Size
422   //
423   MemSize = 0;
424   if (MemoryDeviceSize == 0) {
425     MemSize = 0x7F;
426   } else {
427     MemoryDeviceSize = RShiftU64 (MemoryDeviceSize, 21);
428     while (MemoryDeviceSize != 0) {
429       MemSize++;
430       MemoryDeviceSize = RShiftU64(MemoryDeviceSize,1);
431     }
432   }
433 
434   CopyMem (
435     (UINT8*)StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE6, InstalledSize),
436     &MemSize,
437     1
438     );
439 
440   CopyMem (
441     (UINT8*)StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE6, EnabledSize),
442     &MemSize,
443     1
444     );
445 
446   //
447   // According SMBIOS SPEC Type 6 definition
448   //
449   MemType = 0;
450   if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {
451     if (MemDevice->MemoryFormFactor == EfiMemoryFormFactorDimm ||
452         MemDevice->MemoryFormFactor == EfiMemoryFormFactorFbDimm) {
453       MemType |= 1<<8;
454     }
455 
456     if (MemDevice->MemoryFormFactor == EfiMemoryFormFactorSimm) {
457       MemType |= 1<<7;
458     }
459 
460     if (MemDevice->MemoryType == EfiMemoryTypeSdram) {
461       MemType |= 1<<10;
462     }
463 
464     if (MemDevice->MemoryTypeDetail.Edo == 1) {
465       MemType |= 1<<4;
466     }
467 
468     if (MemDevice->MemoryTypeDetail.FastPaged == 1) {
469       MemType |= 1<<3;
470     }
471   } else {
472     //
473     // Support EDk/Framework defined Data strucutre.
474     //
475     if (FrameworkMemDevice->MemoryFormFactor == EfiMemoryFormFactorDimm ||
476         FrameworkMemDevice->MemoryFormFactor == EfiMemoryFormFactorFbDimm) {
477       MemType |= 1<<8;
478     }
479 
480     if (FrameworkMemDevice->MemoryFormFactor == EfiMemoryFormFactorSimm) {
481       MemType |= 1<<7;
482     }
483 
484     if (FrameworkMemDevice->MemoryType == EfiMemoryTypeSdram) {
485       MemType |= 1<<10;
486     }
487 
488     if (FrameworkMemDevice->MemoryTypeDetail.Edo == 1) {
489       MemType |= 1<<4;
490     }
491 
492     if (FrameworkMemDevice->MemoryTypeDetail.FastPaged == 1) {
493       MemType |= 1<<3;
494     }
495   }
496   //
497   // Form Factor
498   //
499   CopyMem (
500     (UINT8*)StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE6, CurrentMemoryType),
501     &MemType,
502     2
503     );
504 
505 
506   return EFI_SUCCESS;
507 }
508 
509 /**
510   Field Filling Function for Memory SubClass record type 4
511   -- Memory Array Mapped Address: SMBIOS Type 19
512 
513   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
514   @param Offset           Offset of SMBIOS record which RecordData will be filled.
515   @param RecordData       RecordData buffer will be filled.
516   @param RecordDataSize   The size of RecordData buffer.
517 
518   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
519 **/
520 EFI_STATUS
SmbiosFldMemoryType4(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)521 SmbiosFldMemoryType4 (
522   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
523   IN      UINT32                    Offset,
524   IN      VOID                      *RecordData,
525   IN      UINT32                    RecordDataSize
526   )
527 {
528   EFI_MEMORY_ARRAY_START_ADDRESS_DATA  *Masa;
529   EFI_PHYSICAL_ADDRESS                 TempData;
530 
531   Masa = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) RecordData;
532 
533   //
534   // Starting Address
535   //
536   TempData = RShiftU64 (Masa->MemoryArrayStartAddress, 10);
537   CopyMem (
538     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE19, StartingAddress),
539     &TempData,
540     4
541     );
542 
543   //
544   // Ending Address
545   //
546   TempData = RShiftU64 (Masa->MemoryArrayEndAddress, 10);
547   CopyMem (
548     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE19, EndingAddress),
549     &TempData,
550     4
551     );
552 
553   //
554   // Partition Width
555   //
556   CopyMem (
557     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE19, PartitionWidth),
558     &Masa->MemoryArrayPartitionWidth,
559     1
560     );
561 
562   //
563   // Physical Memory Array Link
564   //
565   return SmbiosFldInterLink (
566           StructureNode,
567           (UINT16) OFFSET_OF (SMBIOS_TABLE_TYPE19, MemoryArrayHandle),
568           16, // SMBIOS type 16
569           &Masa->PhysicalMemoryArrayLink,
570           &gEfiMemorySubClassGuid
571           );
572 
573 }
574 
575 /**
576   Field Filling Function for Memory SubClass record type 5
577   -- Memory Device Mapped Address: SMBIOS Type 20
578 
579   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
580   @param Offset           Offset of SMBIOS record which RecordData will be filled.
581   @param RecordData       RecordData buffer will be filled.
582   @param RecordDataSize   The size of RecordData buffer.
583 
584   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
585 **/
586 EFI_STATUS
SmbiosFldMemoryType5(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)587 SmbiosFldMemoryType5 (
588   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
589   IN      UINT32                    Offset,
590   IN      VOID                      *RecordData,
591   IN      UINT32                    RecordDataSize
592   )
593 {
594   EFI_MEMORY_DEVICE_START_ADDRESS_DATA *Mdsa;
595   EFI_PHYSICAL_ADDRESS                 TempData;
596 
597   Mdsa = (EFI_MEMORY_DEVICE_START_ADDRESS_DATA *) RecordData;
598 
599   //
600   // Starting Address
601   //
602   TempData = RShiftU64 (Mdsa->MemoryDeviceStartAddress, 10);
603   CopyMem (
604     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE20, StartingAddress),
605     &TempData,
606     4
607     );
608 
609   //
610   // Ending Address
611   //
612   TempData = RShiftU64 (Mdsa->MemoryDeviceEndAddress, 10);
613   CopyMem (
614     (UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE20, EndingAddress),
615     &TempData,
616     4
617     );
618 
619   //
620   // Memory Device Link
621   //
622   SmbiosFldInterLink (
623     StructureNode,
624     (UINT16) OFFSET_OF (SMBIOS_TABLE_TYPE20, MemoryDeviceHandle),
625     17, // SMBIOS type 17
626     &Mdsa->PhysicalMemoryDeviceLink,
627     &gEfiMemorySubClassGuid
628     );
629 
630   //
631   // Memory Array Mapped Address Link
632   //
633   SmbiosFldInterLink (
634     StructureNode,
635     (UINT16) OFFSET_OF (SMBIOS_TABLE_TYPE20, MemoryArrayMappedAddressHandle),
636     19, // SMBIOS type 19
637     &Mdsa->PhysicalMemoryArrayLink,
638     &gEfiMemorySubClassGuid
639     );
640 
641   //
642   // Memory Device Partition Row Position
643   //
644   *(UINT8 *) ((UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE20, PartitionRowPosition)) = (UINT8) Mdsa->MemoryDevicePartitionRowPosition;
645 
646   //
647   // Memory Device Interleave Position
648   //
649   *(UINT8 *) ((UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE20, InterleavePosition)) = (UINT8) Mdsa->MemoryDeviceInterleavePosition;
650 
651   //
652   // Memory Device Interleave Data Depth
653   //
654   *(UINT8 *) ((UINT8 *) StructureNode->Structure + OFFSET_OF (SMBIOS_TABLE_TYPE20, InterleavedDataDepth)) = (UINT8) Mdsa->MemoryDeviceInterleaveDataDepth;
655 
656   return EFI_SUCCESS;
657 }
658 
659 /**
660   Field Filling Function for Memory SubClass record type 6
661   -- Memory Channel Type: SMBIOS Type 37
662 
663   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
664   @param Offset           Offset of SMBIOS record which RecordData will be filled.
665   @param RecordData       RecordData buffer will be filled.
666   @param RecordDataSize   The size of RecordData buffer.
667 
668   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
669 **/
670 EFI_STATUS
SmbiosFldMemoryType6(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)671 SmbiosFldMemoryType6 (
672   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
673   IN      UINT32                    Offset,
674   IN      VOID                      *RecordData,
675   IN      UINT32                    RecordDataSize
676   )
677 {
678   EFI_MEMORY_CHANNEL_TYPE_DATA  *McTa;
679   EFI_STATUS                    Status;
680 
681   McTa  = (EFI_MEMORY_CHANNEL_TYPE_DATA *) RecordData;
682 
683   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE37, ChannelType))  = (UINT8) (McTa->MemoryChannelType);
684 
685   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE37, MaximumChannelLoad))  = (UINT8) (McTa->MemoryChannelMaximumLoad);
686 
687   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE37, MemoryDeviceCount))  = (UINT8) (McTa->MemoryChannelDeviceCount);
688 
689   //
690   // Update the length field
691   // Multiple device loads are filled through SmbiosFldMemoryType7
692   //
693   StructureNode->Structure->Length = (UINT8)(StructureNode->Structure->Length +
694                                        sizeof(MEMORY_DEVICE) * McTa->MemoryChannelDeviceCount);
695   Status = SmbiosEnlargeStructureBuffer(
696              StructureNode,
697              StructureNode->Structure->Length,
698              StructureNode->StructureSize,
699              StructureNode->StructureSize + sizeof(MEMORY_DEVICE) * McTa->MemoryChannelDeviceCount
700              );
701   return Status;
702 }
703 
704 /**
705   Field Filling Function for Memory SubClass record type 7
706   -- Memory Channel Device: SMBIOS Type 37
707 
708   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
709   @param Offset           Offset of SMBIOS record which RecordData will be filled.
710   @param RecordData       RecordData buffer will be filled.
711   @param RecordDataSize   The size of RecordData buffer.
712 
713   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
714 **/
715 EFI_STATUS
SmbiosFldMemoryType7(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)716 SmbiosFldMemoryType7 (
717   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
718   IN      UINT32                    Offset,
719   IN      VOID                      *RecordData,
720   IN      UINT32                    RecordDataSize
721   )
722 {
723   EFI_MEMORY_CHANNEL_DEVICE_DATA  *Mcdd;
724   UINTN                           DeviceLoadOffset;
725   UINTN                           DeviceLoadHandleOffset;
726 
727   Mcdd = (EFI_MEMORY_CHANNEL_DEVICE_DATA *) RecordData;
728 
729   if (Mcdd->DeviceId < 1) {
730     return EFI_INVALID_PARAMETER;
731   }
732 
733   DeviceLoadOffset        = OFFSET_OF (SMBIOS_TABLE_TYPE37, MemoryDevice[0]) + 3 * (Mcdd->DeviceId - 1);
734   DeviceLoadHandleOffset  = OFFSET_OF (SMBIOS_TABLE_TYPE37, MemoryDevice[1]) + 3 * (Mcdd->DeviceId - 1);
735 
736   *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + DeviceLoadOffset) = (UINT8) (Mcdd->MemoryChannelDeviceLoad);
737 
738   //
739   // Memory Device Handle Link
740   //
741   return SmbiosFldInterLink (
742           StructureNode,
743           (UINT16) DeviceLoadHandleOffset,
744           17, // Smbios type 17 -- Physical Memory Device
745           &Mcdd->DeviceLink,
746           &gEfiMemorySubClassGuid
747           );
748 
749 }
750 
751 /**
752   Field Filling Function for Memory SubClass record type 8
753   -- Memory Controller information: SMBIOS Type 5
754 
755   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
756   @param Offset           Offset of SMBIOS record which RecordData will be filled.
757   @param RecordData       RecordData buffer will be filled.
758   @param RecordDataSize   The size of RecordData buffer.
759 
760   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
761 **/
762 EFI_STATUS
SmbiosFldMemoryType8(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)763 SmbiosFldMemoryType8 (
764   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
765   IN      UINT32                    Offset,
766   IN      VOID                      *RecordData,
767   IN      UINT32                    RecordDataSize
768   )
769 {
770   EFI_MEMORY_CONTROLLER_INFORMATION_DATA *MemoryController;
771   UINT32                                 NewMinimalSize;
772   UINT16                                 Count;
773   EFI_INTER_LINK_DATA                    *Link;
774   EFI_STATUS                             Status;
775 
776   NewMinimalSize   = 0;
777 
778   //
779   // There is an update from EFI_MEMORY_CONTROLLER_INFORMATION to
780   // EFI_MEMORY_CONTROLLER_INFORMATION_DATA. Multiple MemoryModuleConfig
781   // handles are filled.
782   //
783   MemoryController = (EFI_MEMORY_CONTROLLER_INFORMATION_DATA *)RecordData;
784 
785   //
786   // ErrorDetectingMethod
787   //
788   CopyMem (
789     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, ErrDetectMethod),
790     &MemoryController->ErrorDetectingMethod,
791     1
792     );
793 
794   //
795   // ErrorCorrectingCapability
796   //
797   CopyMem (
798     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, ErrCorrectCapability),
799     &MemoryController->ErrorCorrectingCapability,
800     1
801     );
802 
803   //
804   // MemorySupportedInterleave
805   //
806   CopyMem (
807     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, SupportInterleave),
808     &MemoryController->MemorySupportedInterleave,
809     1
810     );
811 
812   //
813   // MemoryCurrentInterleave
814   //
815   CopyMem (
816     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, CurrentInterleave),
817     &MemoryController->MemoryCurrentInterleave,
818     1
819     );
820 
821   //
822   // MaxMemoryModuleSize
823   //
824   CopyMem (
825     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, MaxMemoryModuleSize),
826     &MemoryController->MaxMemoryModuleSize,
827     1
828     );
829 
830   //
831   // MemorySpeedType
832   //
833   CopyMem (
834     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, SupportSpeed),
835     &MemoryController->MemorySpeedType,
836     2
837     );
838 
839   //
840   // MemorySupportedType
841   //
842   CopyMem (
843     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, SupportMemoryType),
844     &MemoryController->MemorySupportedType,
845     2
846     );
847 
848   //
849   // MemoryModuleVoltage
850   //
851   CopyMem (
852     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, MemoryModuleVoltage),
853     &MemoryController->MemoryModuleVoltage,
854     1
855     );
856 
857   //
858   // NumberofMemorySlot
859   //
860   CopyMem (
861     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, AssociatedMemorySlotNum),
862     &MemoryController->NumberofMemorySlot,
863     1
864     );
865 
866   if (MemoryController->NumberofMemorySlot == 0) {
867     //
868     // EnabledCorrectingCapability
869     //
870     CopyMem (
871       (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, MemoryModuleConfigHandles),
872       &MemoryController->EnabledCorrectingCapability,
873       1
874       );
875   } else {
876     //
877     // Memory module configuration handles exist
878     // we should enlarge smbios entry buffer from minimal size
879     //
880     NewMinimalSize = (MemoryController->NumberofMemorySlot) * sizeof(UINT16) + StructureNode->StructureSize;
881     StructureNode->Structure->Length = (UINT8) (NewMinimalSize - 2);
882     Status = SmbiosEnlargeStructureBuffer (StructureNode, StructureNode->Structure->Length, StructureNode->StructureSize, NewMinimalSize);
883     ASSERT_EFI_ERROR (Status);
884 
885     //
886     // MemoryModuleConfigHandles
887     //
888     for (Count = 0, Link = MemoryController->MemoryModuleConfig;
889          Count < MemoryController->NumberofMemorySlot;
890          Count++, Link++) {
891       SmbiosFldInterLink (
892         StructureNode,
893         (UINT16) (OFFSET_OF (SMBIOS_TABLE_TYPE5, MemoryModuleConfigHandles) + Count * sizeof(UINT16)),
894         6, // SMBIOS type 6
895         Link,
896         &gEfiMemorySubClassGuid
897         );
898     }
899 
900     //
901     // EnabledCorrectingCapability
902     //
903     CopyMem (
904       (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE5, MemoryModuleConfigHandles) + (MemoryController->NumberofMemorySlot) * sizeof(UINT16),
905       &MemoryController->EnabledCorrectingCapability,
906       1
907       );
908   }
909 
910   return EFI_SUCCESS;
911 }
912 
913 /**
914   Field Filling Function for Memory SubClass record type
915   -- Memory 32 Bit Error Information: SMBIOS Type 18
916 
917   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
918   @param Offset           Offset of SMBIOS record which RecordData will be filled.
919   @param RecordData       RecordData buffer will be filled.
920   @param RecordDataSize   The size of RecordData buffer.
921 
922   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
923 **/
924 EFI_STATUS
SmbiosFldMemoryType9(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)925 SmbiosFldMemoryType9 (
926   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
927   IN      UINT32                    Offset,
928   IN      VOID                      *RecordData,
929   IN      UINT32                    RecordDataSize
930   )
931 {
932   EFI_MEMORY_32BIT_ERROR_INFORMATION *MemoryInfo;
933 
934   MemoryInfo = (EFI_MEMORY_32BIT_ERROR_INFORMATION *)RecordData;
935 
936   //
937   // MemoryErrorType
938   //
939   CopyMem (
940     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, ErrorType),
941     &MemoryInfo->MemoryErrorType,
942     1
943     );
944 
945   //
946   // MemoryErrorGranularity
947   //
948   CopyMem (
949     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, ErrorGranularity),
950     &MemoryInfo->MemoryErrorGranularity,
951     1
952     );
953 
954   //
955   // MemoryErrorOperation
956   //
957   CopyMem (
958     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, ErrorOperation),
959     &MemoryInfo->MemoryErrorOperation,
960     1
961     );
962 
963   //
964   // VendorSyndrome
965   //
966   CopyMem (
967     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, VendorSyndrome),
968     &MemoryInfo->VendorSyndrome,
969     4
970     );
971 
972   //
973   // MemoryArrayErrorAddress
974   //
975   CopyMem (
976     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, MemoryArrayErrorAddress),
977     &MemoryInfo->MemoryArrayErrorAddress,
978     4
979     );
980 
981   //
982   // DeviceErrorAddress
983   //
984   CopyMem (
985     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, DeviceErrorAddress),
986     &MemoryInfo->DeviceErrorAddress,
987     4
988     );
989 
990   //
991   // DeviceErrorResolution
992   //
993   CopyMem (
994     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE18, ErrorResolution),
995     &MemoryInfo->DeviceErrorResolution,
996     4
997     );
998 
999   return EFI_SUCCESS;
1000 }
1001 
1002 /**
1003   Field Filling Function for Memory SubClass record type
1004   -- Memory 64 Bit Error Information: SMBIOS Type 33
1005 
1006   @param StructureNode    Pointer to SMBIOS_STRUCTURE_NODE which is current processed.
1007   @param Offset           Offset of SMBIOS record which RecordData will be filled.
1008   @param RecordData       RecordData buffer will be filled.
1009   @param RecordDataSize   The size of RecordData buffer.
1010 
1011   @retval EFI_SUCCESS   Success fill RecordData into SMBIOS's record buffer.
1012 **/
1013 EFI_STATUS
SmbiosFldMemoryType10(IN OUT SMBIOS_STRUCTURE_NODE * StructureNode,IN UINT32 Offset,IN VOID * RecordData,IN UINT32 RecordDataSize)1014 SmbiosFldMemoryType10 (
1015   IN OUT  SMBIOS_STRUCTURE_NODE     *StructureNode,
1016   IN      UINT32                    Offset,
1017   IN      VOID                      *RecordData,
1018   IN      UINT32                    RecordDataSize
1019   )
1020 {
1021   EFI_MEMORY_64BIT_ERROR_INFORMATION *MemoryInfo;
1022 
1023   MemoryInfo = (EFI_MEMORY_64BIT_ERROR_INFORMATION *)RecordData;
1024 
1025   //
1026   // MemoryErrorType
1027   //
1028   CopyMem (
1029     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, ErrorType),
1030     &MemoryInfo->MemoryErrorType,
1031     1
1032     );
1033 
1034   //
1035   // MemoryErrorGranularity
1036   //
1037   CopyMem (
1038     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, ErrorGranularity),
1039     &MemoryInfo->MemoryErrorGranularity,
1040     1
1041     );
1042 
1043   //
1044   // MemoryErrorOperation
1045   //
1046   CopyMem (
1047     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, ErrorOperation),
1048     &MemoryInfo->MemoryErrorOperation,
1049     1
1050     );
1051 
1052   //
1053   // VendorSyndrome
1054   //
1055   CopyMem (
1056     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, VendorSyndrome),
1057     &MemoryInfo->VendorSyndrome,
1058     4
1059     );
1060 
1061   //
1062   // MemoryArrayErrorAddress
1063   //
1064   CopyMem (
1065     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, MemoryArrayErrorAddress),
1066     &MemoryInfo->MemoryArrayErrorAddress,
1067     8
1068     );
1069 
1070   //
1071   // DeviceErrorAddress
1072   //
1073   CopyMem (
1074     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, DeviceErrorAddress),
1075     &MemoryInfo->DeviceErrorAddress,
1076     8
1077     );
1078 
1079   //
1080   // DeviceErrorResolution
1081   //
1082   CopyMem (
1083     (UINT8 *) (StructureNode->Structure) + OFFSET_OF (SMBIOS_TABLE_TYPE33, ErrorResolution),
1084     &MemoryInfo->DeviceErrorResolution,
1085     4
1086     );
1087 
1088   return EFI_SUCCESS;
1089 }
1090