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