1 /** @file
2   This driver measures SMBIOS table to TPM.
3 
4 Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PiDxe.h>
10 
11 #include <Protocol/Smbios.h>
12 #include <IndustryStandard/SmBios.h>
13 #include <IndustryStandard/UefiTcgPlatform.h>
14 #include <Guid/EventGroup.h>
15 #include <Guid/SmBios.h>
16 #include <Library/DebugLib.h>
17 #include <Library/UefiDriverEntryPoint.h>
18 #include <Library/UefiLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/PcdLib.h>
24 #include <Library/TpmMeasurementLib.h>
25 
26 #define FIELD_SIZE_OF(TYPE, Field) ((UINTN)sizeof(((TYPE *)0)->Field))
27 
28 typedef struct {
29   UINT8  Type;
30   UINTN  Offset;
31   UINTN  Size;
32   UINT32 Flags;
33 } SMBIOS_FILTER_TABLE;
34 #define SMBIOS_FILTER_TABLE_FLAG_IS_STRING  BIT0
35 
36 typedef struct {
37   UINT8                Type;
38   SMBIOS_FILTER_TABLE  *Filter; // NULL means all fields
39   UINTN                FilterCount;
40 } SMBIOS_FILTER_STRUCT;
41 
42 //
43 // Platform Specific Policy
44 //
45 SMBIOS_FILTER_TABLE  mSmbiosFilterType1BlackList[] = {
46   {0x01, OFFSET_OF(SMBIOS_TABLE_TYPE1, SerialNumber),         FIELD_SIZE_OF(SMBIOS_TABLE_TYPE1, SerialNumber),         SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
47   {0x01, OFFSET_OF(SMBIOS_TABLE_TYPE1, Uuid),                 FIELD_SIZE_OF(SMBIOS_TABLE_TYPE1, Uuid),                 0},
48   {0x01, OFFSET_OF(SMBIOS_TABLE_TYPE1, WakeUpType),           FIELD_SIZE_OF(SMBIOS_TABLE_TYPE1, WakeUpType),           0},
49 };
50 SMBIOS_FILTER_TABLE  mSmbiosFilterType2BlackList[] = {
51   {0x02, OFFSET_OF(SMBIOS_TABLE_TYPE2, SerialNumber),         FIELD_SIZE_OF(SMBIOS_TABLE_TYPE2, SerialNumber),         SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
52   {0x02, OFFSET_OF(SMBIOS_TABLE_TYPE2, LocationInChassis),    FIELD_SIZE_OF(SMBIOS_TABLE_TYPE2, LocationInChassis),    SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
53 };
54 SMBIOS_FILTER_TABLE  mSmbiosFilterType3BlackList[] = {
55   {0x03, OFFSET_OF(SMBIOS_TABLE_TYPE3, SerialNumber),         FIELD_SIZE_OF(SMBIOS_TABLE_TYPE3, SerialNumber),         SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
56   {0x03, OFFSET_OF(SMBIOS_TABLE_TYPE3, AssetTag),             FIELD_SIZE_OF(SMBIOS_TABLE_TYPE3, AssetTag),             SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
57 };
58 SMBIOS_FILTER_TABLE  mSmbiosFilterType4BlackList[] = {
59   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, SerialNumber),         FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, SerialNumber),         SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
60   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, AssetTag),             FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, AssetTag),             SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
61   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, PartNumber),           FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, PartNumber),           SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
62   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, CoreCount),            FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, CoreCount),            0},
63   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, EnabledCoreCount),     FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, EnabledCoreCount),     0},
64   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, ThreadCount),          FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, ThreadCount),          0},
65   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, CoreCount2),           FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, CoreCount2),           0},
66   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, EnabledCoreCount2),    FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, EnabledCoreCount2),    0},
67   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, ThreadCount2),         FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, ThreadCount2),         0},
68   {0x04, OFFSET_OF(SMBIOS_TABLE_TYPE4, Voltage),              FIELD_SIZE_OF(SMBIOS_TABLE_TYPE4, Voltage),              0},
69 };
70 SMBIOS_FILTER_TABLE  mSmbiosFilterType17BlackList[] = {
71   {0x11, OFFSET_OF(SMBIOS_TABLE_TYPE17, SerialNumber),        FIELD_SIZE_OF(SMBIOS_TABLE_TYPE17, SerialNumber),        SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
72   {0x11, OFFSET_OF(SMBIOS_TABLE_TYPE17, AssetTag),            FIELD_SIZE_OF(SMBIOS_TABLE_TYPE17, AssetTag),            SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
73   {0x11, OFFSET_OF(SMBIOS_TABLE_TYPE17, PartNumber),          FIELD_SIZE_OF(SMBIOS_TABLE_TYPE17, PartNumber),          SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
74 };
75 SMBIOS_FILTER_TABLE  mSmbiosFilterType22BlackList[] = {
76   {0x16, OFFSET_OF(SMBIOS_TABLE_TYPE22, SerialNumber),        FIELD_SIZE_OF(SMBIOS_TABLE_TYPE22, SerialNumber),        SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
77   {0x16, OFFSET_OF(SMBIOS_TABLE_TYPE22, SBDSSerialNumber),    FIELD_SIZE_OF(SMBIOS_TABLE_TYPE22, SBDSSerialNumber),    0},
78   {0x16, OFFSET_OF(SMBIOS_TABLE_TYPE22, SBDSManufactureDate), FIELD_SIZE_OF(SMBIOS_TABLE_TYPE22, SBDSManufactureDate), 0},
79 };
80 SMBIOS_FILTER_TABLE  mSmbiosFilterType23BlackList[] = {
81   {0x17, OFFSET_OF(SMBIOS_TABLE_TYPE23, ResetCount),          FIELD_SIZE_OF(SMBIOS_TABLE_TYPE23, ResetCount),          0},
82 };
83 SMBIOS_FILTER_TABLE  mSmbiosFilterType27BlackList[] = {
84   {0x1B, OFFSET_OF(SMBIOS_TABLE_TYPE27, NominalSpeed),        FIELD_SIZE_OF(SMBIOS_TABLE_TYPE27, NominalSpeed),        0},
85 };
86 SMBIOS_FILTER_TABLE  mSmbiosFilterType39BlackList[] = {
87   {0x27, OFFSET_OF(SMBIOS_TABLE_TYPE39, SerialNumber),        FIELD_SIZE_OF(SMBIOS_TABLE_TYPE39, SerialNumber),        SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
88   {0x27, OFFSET_OF(SMBIOS_TABLE_TYPE39, AssetTagNumber),      FIELD_SIZE_OF(SMBIOS_TABLE_TYPE39, AssetTagNumber),      SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
89   {0x27, OFFSET_OF(SMBIOS_TABLE_TYPE39, ModelPartNumber),     FIELD_SIZE_OF(SMBIOS_TABLE_TYPE39, ModelPartNumber),     SMBIOS_FILTER_TABLE_FLAG_IS_STRING},
90 };
91 
92 SMBIOS_FILTER_STRUCT  mSmbiosFilterStandardTableBlackList[] = {
93   {0x01, mSmbiosFilterType1BlackList,  sizeof(mSmbiosFilterType1BlackList)/sizeof(mSmbiosFilterType1BlackList[0])},
94   {0x02, mSmbiosFilterType2BlackList,  sizeof(mSmbiosFilterType2BlackList)/sizeof(mSmbiosFilterType2BlackList[0])},
95   {0x03, mSmbiosFilterType3BlackList,  sizeof(mSmbiosFilterType3BlackList)/sizeof(mSmbiosFilterType3BlackList[0])},
96   {0x04, mSmbiosFilterType4BlackList,  sizeof(mSmbiosFilterType4BlackList)/sizeof(mSmbiosFilterType4BlackList[0])},
97   {0x0B, NULL, 0},
98   {0x0F, NULL, 0},
99   {0x11, mSmbiosFilterType17BlackList, sizeof(mSmbiosFilterType17BlackList)/sizeof(mSmbiosFilterType17BlackList[0])},
100   {0x12, NULL, 0},
101   {0x16, mSmbiosFilterType22BlackList, sizeof(mSmbiosFilterType22BlackList)/sizeof(mSmbiosFilterType22BlackList[0])},
102   {0x17, mSmbiosFilterType23BlackList, sizeof(mSmbiosFilterType23BlackList)/sizeof(mSmbiosFilterType23BlackList[0])},
103   {0x1B, mSmbiosFilterType27BlackList, sizeof(mSmbiosFilterType27BlackList)/sizeof(mSmbiosFilterType27BlackList[0])},
104   {0x1F, NULL, 0},
105   {0x21, NULL, 0},
106   {0x27, mSmbiosFilterType39BlackList, sizeof(mSmbiosFilterType39BlackList)/sizeof(mSmbiosFilterType39BlackList[0])},
107 };
108 
109 EFI_SMBIOS_PROTOCOL *mSmbios;
110 UINTN               mMaxLen;
111 
112 #pragma pack (1)
113 
114 #define SMBIOS_HANDOFF_TABLE_DESC  "SmbiosTable"
115 typedef struct {
116   UINT8                             TableDescriptionSize;
117   UINT8                             TableDescription[sizeof(SMBIOS_HANDOFF_TABLE_DESC)];
118   UINT64                            NumberOfTables;
119   EFI_CONFIGURATION_TABLE           TableEntry[1];
120 } SMBIOS_HANDOFF_TABLE_POINTERS2;
121 
122 #pragma pack ()
123 
124 /**
125 
126   This function dump raw data.
127 
128   @param  Data  raw data
129   @param  Size  raw data size
130 
131 **/
132 VOID
InternalDumpData(IN UINT8 * Data,IN UINTN Size)133 InternalDumpData (
134   IN UINT8  *Data,
135   IN UINTN  Size
136   )
137 {
138   UINTN  Index;
139   for (Index = 0; Index < Size; Index++) {
140     DEBUG ((EFI_D_VERBOSE, "%02x", (UINTN)Data[Index]));
141   }
142 }
143 
144 /**
145 
146   This function dump raw data with colume format.
147 
148   @param  Data  raw data
149   @param  Size  raw data size
150 
151 **/
152 VOID
InternalDumpHex(IN UINT8 * Data,IN UINTN Size)153 InternalDumpHex (
154   IN UINT8  *Data,
155   IN UINTN  Size
156   )
157 {
158   UINTN   Index;
159   UINTN   Count;
160   UINTN   Left;
161 
162 #define COLUME_SIZE  (16 * 2)
163 
164   Count = Size / COLUME_SIZE;
165   Left  = Size % COLUME_SIZE;
166   for (Index = 0; Index < Count; Index++) {
167     DEBUG ((EFI_D_VERBOSE, "%04x: ", Index * COLUME_SIZE));
168     InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
169     DEBUG ((EFI_D_VERBOSE, "\n"));
170   }
171 
172   if (Left != 0) {
173     DEBUG ((EFI_D_VERBOSE, "%04x: ", Index * COLUME_SIZE));
174     InternalDumpData (Data + Index * COLUME_SIZE, Left);
175     DEBUG ((EFI_D_VERBOSE, "\n"));
176   }
177 }
178 
179 
180 /**
181 
182   This function get filter structure by SMBIOS type.
183 
184   @param  Type  SMBIOS type
185 
186 **/
187 SMBIOS_FILTER_STRUCT *
GetFilterStructByType(IN UINT8 Type)188 GetFilterStructByType (
189   IN UINT8 Type
190   )
191 {
192   UINTN  Index;
193   for (Index = 0; Index < sizeof(mSmbiosFilterStandardTableBlackList)/sizeof(mSmbiosFilterStandardTableBlackList[0]); Index++) {
194     if (mSmbiosFilterStandardTableBlackList[Index].Type == Type) {
195       return &mSmbiosFilterStandardTableBlackList[Index];
196     }
197   }
198   return NULL;
199 }
200 
201 /**
202 
203   This function get SMBIOS string in SMBIOS table.
204 
205   @param  Head      SMBIOS table head
206   @param  StringId  SMBIOS string ID
207   @param  StringLen length of SMBIOS string
208 
209   @return SMBIOS string data
210 **/
211 CHAR8 *
GetSmbiosStringById(IN EFI_SMBIOS_TABLE_HEADER * Head,IN SMBIOS_TABLE_STRING StringId,OUT UINTN * StringLen)212 GetSmbiosStringById (
213   IN   EFI_SMBIOS_TABLE_HEADER          *Head,
214   IN   SMBIOS_TABLE_STRING              StringId,
215   OUT  UINTN                            *StringLen
216   )
217 {
218   UINTN  Size;
219   UINTN  StrLen;
220   CHAR8  *CharInStr;
221   UINTN  StringsNumber;
222   CHAR8  *String;
223 
224   CharInStr = (CHAR8 *)Head + Head->Length;
225   Size = Head->Length;
226   StringsNumber = 0;
227   StrLen = 0;
228   //
229   // look for the two consecutive zeros, check the string limit by the way.
230   //
231   String = NULL;
232   while (*CharInStr != 0 || *(CharInStr+1) != 0) {
233     if (*CharInStr == 0) {
234       Size += 1;
235       CharInStr++;
236     }
237     String = CharInStr;
238 
239     for (StrLen = 0 ; StrLen < mMaxLen; StrLen++) {
240       if (*(CharInStr+StrLen) == 0) {
241         break;
242       }
243     }
244     *StringLen = StrLen;
245 
246     if (StrLen == mMaxLen) {
247       return NULL;
248     }
249 
250     //
251     // forward the pointer
252     //
253     CharInStr += StrLen;
254     Size += StrLen;
255     StringsNumber += 1;
256     if (StringsNumber == StringId) {
257       break;
258     }
259   }
260 
261   return String;
262 }
263 
264 /**
265 
266   This function update SMBIOS table based on policy.
267 
268   @param  TableEntry      SMBIOS table
269   @param  TableEntrySize  SMBIOS table size
270 
271 **/
272 VOID
FilterSmbiosEntry(IN OUT VOID * TableEntry,IN UINTN TableEntrySize)273 FilterSmbiosEntry (
274   IN OUT VOID   *TableEntry,
275   IN UINTN      TableEntrySize
276   )
277 {
278   SMBIOS_FILTER_STRUCT  *FilterStruct;
279   SMBIOS_FILTER_TABLE   *Filter;
280   UINTN                 Index;
281   SMBIOS_TABLE_STRING   StringId;
282   CHAR8                 *String;
283   UINTN                 StringLen;
284 
285   DEBUG ((EFI_D_INFO, "Smbios Table (Type - %d):\n", ((SMBIOS_STRUCTURE *)TableEntry)->Type));
286   DEBUG_CODE (InternalDumpHex (TableEntry, TableEntrySize););
287 
288   //
289   // Skip measurement for OEM types.
290   //
291   if (((SMBIOS_STRUCTURE *)TableEntry)->Type >= SMBIOS_OEM_BEGIN) {
292     // zero all table fields, except header
293     ZeroMem ((UINT8 *)TableEntry + sizeof(SMBIOS_STRUCTURE), TableEntrySize - sizeof(SMBIOS_STRUCTURE));
294   } else {
295     FilterStruct = GetFilterStructByType (((SMBIOS_STRUCTURE *)TableEntry)->Type);
296     if (FilterStruct != NULL) {
297       if (FilterStruct->Filter == NULL || FilterStruct->FilterCount == 0) {
298         // zero all table fields, except header
299         ZeroMem ((UINT8 *)TableEntry + sizeof(SMBIOS_STRUCTURE), TableEntrySize - sizeof(SMBIOS_STRUCTURE));
300       } else {
301         Filter = FilterStruct->Filter;
302         for (Index = 0; Index < FilterStruct->FilterCount; Index++) {
303           if (((SMBIOS_STRUCTURE *) TableEntry)->Length >= (Filter[Index].Offset + Filter[Index].Size)) {
304             //
305             // The field is present in the SMBIOS entry.
306             //
307             if ((Filter[Index].Flags & SMBIOS_FILTER_TABLE_FLAG_IS_STRING) != 0) {
308               CopyMem (&StringId, (UINT8 *)TableEntry + Filter[Index].Offset, sizeof(StringId));
309               if (StringId != 0) {
310                 // set ' ' for string field
311                 String = GetSmbiosStringById (TableEntry, StringId, &StringLen);
312                 ASSERT (String != NULL);
313                 //DEBUG ((EFI_D_INFO,"StrId(0x%x)-%a(%d)\n", StringId, String, StringLen));
314                 SetMem (String, StringLen, ' ');
315               }
316             }
317             // zero non-string field
318             ZeroMem ((UINT8 *)TableEntry + Filter[Index].Offset, Filter[Index].Size);
319           }
320         }
321       }
322     }
323   }
324 
325   DEBUG ((EFI_D_INFO, "Filter Smbios Table (Type - %d):\n", ((SMBIOS_STRUCTURE *)TableEntry)->Type));
326   DEBUG_CODE (InternalDumpHex (TableEntry, TableEntrySize););
327 }
328 
329 /**
330 
331   Get the full size of SMBIOS structure including optional strings that follow the formatted structure.
332 
333   @param Head                   Pointer to the beginning of SMBIOS structure.
334   @param NumberOfStrings        The returned number of optional strings that follow the formatted structure.
335 
336   @return Size                  The returned size.
337 **/
338 UINTN
GetSmbiosStructureSize(IN EFI_SMBIOS_TABLE_HEADER * Head,OUT UINTN * NumberOfStrings)339 GetSmbiosStructureSize (
340   IN   EFI_SMBIOS_TABLE_HEADER          *Head,
341   OUT  UINTN                            *NumberOfStrings
342   )
343 {
344   UINTN  Size;
345   UINTN  StrLen;
346   CHAR8  *CharInStr;
347   UINTN  StringsNumber;
348 
349   CharInStr = (CHAR8 *)Head + Head->Length;
350   Size = Head->Length;
351   StringsNumber = 0;
352   StrLen = 0;
353   //
354   // look for the two consecutive zeros, check the string limit by the way.
355   //
356   while (*CharInStr != 0 || *(CharInStr+1) != 0) {
357     if (*CharInStr == 0) {
358       Size += 1;
359       CharInStr++;
360     }
361 
362     for (StrLen = 0 ; StrLen < mMaxLen; StrLen++) {
363       if (*(CharInStr+StrLen) == 0) {
364         break;
365       }
366     }
367 
368     if (StrLen == mMaxLen) {
369       return 0;
370     }
371 
372     //
373     // forward the pointer
374     //
375     CharInStr += StrLen;
376     Size += StrLen;
377     StringsNumber += 1;
378   }
379 
380   //
381   // count ending two zeros.
382   //
383   Size += 2;
384 
385   if (NumberOfStrings != NULL) {
386     *NumberOfStrings = StringsNumber;
387   }
388   return Size;
389 }
390 
391 /**
392 
393   This function returns full SMBIOS table length.
394 
395   @param  TableAddress      SMBIOS table based address
396   @param  TableMaximumSize  Maximum size of SMBIOS table
397 
398   @return SMBIOS table length
399 
400 **/
401 UINTN
GetSmbiosTableLength(IN VOID * TableAddress,IN UINTN TableMaximumSize)402 GetSmbiosTableLength (
403   IN VOID  *TableAddress,
404   IN UINTN TableMaximumSize
405   )
406 {
407   VOID  *TableEntry;
408   VOID  *TableAddressEnd;
409   UINTN TableEntryLength;
410 
411   TableAddressEnd = (VOID *)((UINTN)TableAddress + TableMaximumSize);
412   TableEntry = TableAddress;
413   while (TableEntry < TableAddressEnd) {
414     TableEntryLength = GetSmbiosStructureSize (TableEntry, NULL);
415     if (TableEntryLength == 0) {
416       break;
417     }
418     if (((SMBIOS_STRUCTURE *)TableEntry)->Type == 127) {
419       TableEntry = (VOID *)((UINTN)TableEntry + TableEntryLength);
420       break;
421     }
422     TableEntry = (VOID *)((UINTN)TableEntry + TableEntryLength);
423   }
424 
425   return ((UINTN)TableEntry - (UINTN)TableAddress);
426 }
427 
428 /**
429 
430   This function updatess full SMBIOS table length.
431 
432   @param  TableAddress      SMBIOS table based address
433   @param  TableLength       SMBIOS table length
434 
435 **/
436 VOID
FilterSmbiosTable(IN OUT VOID * TableAddress,IN UINTN TableLength)437 FilterSmbiosTable (
438   IN OUT VOID  *TableAddress,
439   IN UINTN     TableLength
440   )
441 {
442   VOID   *TableAddressEnd;
443   VOID   *TableEntry;
444   UINTN  TableEntryLength;
445 
446   TableEntry = TableAddress;
447   TableAddressEnd = (VOID *)((UINTN)TableAddress + TableLength);
448   while ((UINTN)TableEntry < (UINTN)TableAddressEnd) {
449     TableEntryLength = GetSmbiosStructureSize (TableEntry, NULL);
450     if (TableEntryLength == 0) {
451       break;
452     }
453 
454     FilterSmbiosEntry (TableEntry, TableEntryLength);
455 
456     TableEntry = (VOID *)((UINTN)TableEntry + TableEntryLength);
457   }
458 }
459 
460 /**
461   Measure SMBIOS with EV_EFI_HANDOFF_TABLES to PCR[1].
462 
463   @param[in] Event      Event whose notification function is being invoked.
464   @param[in] Context    Pointer to the notification function's context.
465 
466 **/
467 VOID
468 EFIAPI
MeasureSmbiosTable(IN EFI_EVENT Event,IN VOID * Context)469 MeasureSmbiosTable (
470   IN      EFI_EVENT                 Event,
471   IN      VOID                      *Context
472   )
473 {
474   EFI_STATUS                        Status;
475   EFI_HANDOFF_TABLE_POINTERS        HandoffTables;
476   SMBIOS_HANDOFF_TABLE_POINTERS2    SmbiosHandoffTables2;
477   UINT32                            EventType;
478   VOID                              *EventLog;
479   UINT32                            EventLogSize;
480   SMBIOS_TABLE_ENTRY_POINT          *SmbiosTable;
481   SMBIOS_TABLE_3_0_ENTRY_POINT      *Smbios3Table;
482   VOID                              *SmbiosTableAddress;
483   VOID                              *TableAddress;
484   UINTN                             TableLength;
485 
486   SmbiosTable = NULL;
487   Smbios3Table = NULL;
488   SmbiosTableAddress = NULL;
489   TableLength = 0;
490 
491   if (mSmbios->MajorVersion >= 3) {
492     Status = EfiGetSystemConfigurationTable (
493                &gEfiSmbios3TableGuid,
494                (VOID **) &Smbios3Table
495                );
496     if (!EFI_ERROR (Status)) {
497       DEBUG ((EFI_D_INFO, "Smbios3Table:\n"));
498       DEBUG ((EFI_D_INFO, "  AnchorString                - '%c%c%c%c%c'\n",
499         Smbios3Table->AnchorString[0],
500         Smbios3Table->AnchorString[1],
501         Smbios3Table->AnchorString[2],
502         Smbios3Table->AnchorString[3],
503         Smbios3Table->AnchorString[4]
504         ));
505       DEBUG ((EFI_D_INFO, "  EntryPointStructureChecksum - 0x%02x\n", Smbios3Table->EntryPointStructureChecksum));
506       DEBUG ((EFI_D_INFO, "  EntryPointLength            - 0x%02x\n", Smbios3Table->EntryPointLength));
507       DEBUG ((EFI_D_INFO, "  MajorVersion                - 0x%02x\n", Smbios3Table->MajorVersion));
508       DEBUG ((EFI_D_INFO, "  MinorVersion                - 0x%02x\n", Smbios3Table->MinorVersion));
509       DEBUG ((EFI_D_INFO, "  DocRev                      - 0x%02x\n", Smbios3Table->DocRev));
510       DEBUG ((EFI_D_INFO, "  EntryPointRevision          - 0x%02x\n", Smbios3Table->EntryPointRevision));
511       DEBUG ((EFI_D_INFO, "  TableMaximumSize            - 0x%08x\n", Smbios3Table->TableMaximumSize));
512       DEBUG ((EFI_D_INFO, "  TableAddress                - 0x%016lx\n", Smbios3Table->TableAddress));
513     }
514   }
515 
516   if (Smbios3Table == NULL) {
517     Status = EfiGetSystemConfigurationTable (
518                &gEfiSmbiosTableGuid,
519                (VOID **) &SmbiosTable
520                );
521     if (!EFI_ERROR (Status)) {
522       DEBUG ((EFI_D_INFO, "SmbiosTable:\n"));
523       DEBUG ((EFI_D_INFO, "  AnchorString                - '%c%c%c%c'\n",
524         SmbiosTable->AnchorString[0],
525         SmbiosTable->AnchorString[1],
526         SmbiosTable->AnchorString[2],
527         SmbiosTable->AnchorString[3]
528         ));
529       DEBUG ((EFI_D_INFO, "  EntryPointStructureChecksum - 0x%02x\n", SmbiosTable->EntryPointStructureChecksum));
530       DEBUG ((EFI_D_INFO, "  EntryPointLength            - 0x%02x\n", SmbiosTable->EntryPointLength));
531       DEBUG ((EFI_D_INFO, "  MajorVersion                - 0x%02x\n", SmbiosTable->MajorVersion));
532       DEBUG ((EFI_D_INFO, "  MinorVersion                - 0x%02x\n", SmbiosTable->MinorVersion));
533       DEBUG ((EFI_D_INFO, "  MaxStructureSize            - 0x%08x\n", SmbiosTable->MaxStructureSize));
534       DEBUG ((EFI_D_INFO, "  EntryPointRevision          - 0x%02x\n", SmbiosTable->EntryPointRevision));
535       DEBUG ((EFI_D_INFO, "  FormattedArea               - '%c%c%c%c%c'\n",
536         SmbiosTable->FormattedArea[0],
537         SmbiosTable->FormattedArea[1],
538         SmbiosTable->FormattedArea[2],
539         SmbiosTable->FormattedArea[3],
540         SmbiosTable->FormattedArea[4]
541         ));
542       DEBUG ((EFI_D_INFO, "  IntermediateAnchorString    - '%c%c%c%c%c'\n",
543         SmbiosTable->IntermediateAnchorString[0],
544         SmbiosTable->IntermediateAnchorString[1],
545         SmbiosTable->IntermediateAnchorString[2],
546         SmbiosTable->IntermediateAnchorString[3],
547         SmbiosTable->IntermediateAnchorString[4]
548         ));
549       DEBUG ((EFI_D_INFO, "  IntermediateChecksum        - 0x%02x\n", SmbiosTable->IntermediateChecksum));
550       DEBUG ((EFI_D_INFO, "  TableLength                 - 0x%04x\n", SmbiosTable->TableLength));
551       DEBUG ((EFI_D_INFO, "  TableAddress                - 0x%08x\n", SmbiosTable->TableAddress));
552       DEBUG ((EFI_D_INFO, "  NumberOfSmbiosStructures    - 0x%04x\n", SmbiosTable->NumberOfSmbiosStructures));
553       DEBUG ((EFI_D_INFO, "  SmbiosBcdRevision           - 0x%02x\n", SmbiosTable->SmbiosBcdRevision));
554     }
555   }
556 
557   if (Smbios3Table != NULL) {
558     SmbiosTableAddress = (VOID *)(UINTN)Smbios3Table->TableAddress;
559     TableLength = GetSmbiosTableLength (SmbiosTableAddress, Smbios3Table->TableMaximumSize);
560   } else if (SmbiosTable != NULL) {
561     SmbiosTableAddress = (VOID *)(UINTN)SmbiosTable->TableAddress;
562     TableLength = SmbiosTable->TableLength;
563   }
564 
565   if (SmbiosTableAddress != NULL) {
566     DEBUG ((DEBUG_INFO, "The Smbios Table starts at: 0x%x\n", SmbiosTableAddress));
567     DEBUG ((DEBUG_INFO, "The Smbios Table size: 0x%x\n", TableLength));
568     DEBUG_CODE (InternalDumpHex ((UINT8 *)(UINTN)SmbiosTableAddress, TableLength););
569 
570     TableAddress = AllocateCopyPool ((UINTN)TableLength, (VOID *)(UINTN)SmbiosTableAddress);
571     if (TableAddress == NULL) {
572       return ;
573     }
574 
575     FilterSmbiosTable (TableAddress, TableLength);
576 
577     DEBUG ((DEBUG_INFO, "The final Smbios Table starts at: 0x%x\n", TableAddress));
578     DEBUG ((DEBUG_INFO, "The final Smbios Table size: 0x%x\n", TableLength));
579     DEBUG_CODE (InternalDumpHex (TableAddress, TableLength););
580 
581     HandoffTables.NumberOfTables = 1;
582     if (Smbios3Table != NULL) {
583       CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gEfiSmbios3TableGuid);
584       HandoffTables.TableEntry[0].VendorTable = Smbios3Table;
585     } else {
586       CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), &gEfiSmbiosTableGuid);
587       HandoffTables.TableEntry[0].VendorTable = SmbiosTable;
588     }
589     EventType = EV_EFI_HANDOFF_TABLES;
590     EventLog = &HandoffTables;
591     EventLogSize = sizeof (HandoffTables);
592 
593     if (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105) {
594       SmbiosHandoffTables2.TableDescriptionSize = sizeof(SmbiosHandoffTables2.TableDescription);
595       CopyMem (SmbiosHandoffTables2.TableDescription, SMBIOS_HANDOFF_TABLE_DESC, sizeof(SmbiosHandoffTables2.TableDescription));
596       SmbiosHandoffTables2.NumberOfTables = HandoffTables.NumberOfTables;
597       CopyMem (&(SmbiosHandoffTables2.TableEntry[0]), &(HandoffTables.TableEntry[0]), sizeof(SmbiosHandoffTables2.TableEntry[0]));
598       EventType = EV_EFI_HANDOFF_TABLES2;
599       EventLog = &SmbiosHandoffTables2;
600       EventLogSize = sizeof (SmbiosHandoffTables2);
601     }
602     Status = TpmMeasureAndLogData (
603                1,                       // PCRIndex
604                EventType,               // EventType
605                EventLog,                // EventLog
606                EventLogSize,            // LogLen
607                TableAddress,            // HashData
608                TableLength              // HashDataLen
609                );
610     if (!EFI_ERROR (Status)) {
611       gBS->CloseEvent (Event) ;
612     }
613   }
614 
615   return ;
616 }
617 
618 /**
619 
620   Driver to produce Smbios measurement.
621 
622   @param ImageHandle     Module's image handle
623   @param SystemTable     Pointer of EFI_SYSTEM_TABLE
624 
625   @return Status returned from EfiCreateEventReadyToBootEx().
626 
627 **/
628 EFI_STATUS
629 EFIAPI
SmbiosMeasurementDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)630 SmbiosMeasurementDriverEntryPoint (
631   IN EFI_HANDLE           ImageHandle,
632   IN EFI_SYSTEM_TABLE     *SystemTable
633   )
634 {
635   EFI_STATUS            Status;
636   EFI_EVENT             Event;
637 
638   Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);
639   ASSERT_EFI_ERROR (Status);
640   DEBUG ((DEBUG_INFO, "The Smbios Table Version: %x.%x\n", mSmbios->MajorVersion, mSmbios->MinorVersion));
641 
642   if (mSmbios->MajorVersion < 2 || (mSmbios->MajorVersion == 2 && mSmbios->MinorVersion < 7)){
643     mMaxLen = SMBIOS_STRING_MAX_LENGTH;
644   } else if (mSmbios->MajorVersion < 3) {
645     //
646     // Reference SMBIOS 2.7, chapter 6.1.3, it will have no limit on the length of each individual text string.
647     // However, the length of the entire structure table (including all strings) must be reported
648     // in the Structure Table Length field of the SMBIOS Structure Table Entry Point,
649     // which is a WORD field limited to 65,535 bytes.
650     //
651     mMaxLen = SMBIOS_TABLE_MAX_LENGTH;
652   } else {
653     //
654     // SMBIOS 3.0 defines the Structure table maximum size as DWORD field limited to 0xFFFFFFFF bytes.
655     // Locate the end of string as long as possible.
656     //
657     mMaxLen = SMBIOS_3_0_TABLE_MAX_LENGTH;
658   }
659 
660   //
661   // Measure Smbios tables
662   //
663   Status = EfiCreateEventReadyToBootEx (
664              TPL_CALLBACK,
665              MeasureSmbiosTable,
666              NULL,
667              &Event
668              );
669 
670   return Status;
671 }
672