Home | History | Annotate | Download | only in TcgDxe
      1 /** @file
      2   This module implements TCG EFI Protocol.
      3 
      4 Caution: This module requires additional review when modified.
      5 This driver will have external input - TcgDxePassThroughToTpm
      6 This external input must be validated carefully to avoid security issue like
      7 buffer overflow, integer overflow.
      8 
      9 TcgDxePassThroughToTpm() will receive untrusted input and do basic validation.
     10 
     11 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
     12 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
     13 This program and the accompanying materials
     14 are licensed and made available under the terms and conditions of the BSD License
     15 which accompanies this distribution.  The full text of the license may be found at
     16 http://opensource.org/licenses/bsd-license.php
     17 
     18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     20 
     21 **/
     22 
     23 #include <PiDxe.h>
     24 #include <IndustryStandard/Tpm12.h>
     25 #include <IndustryStandard/Acpi.h>
     26 #include <IndustryStandard/PeImage.h>
     27 #include <IndustryStandard/TcpaAcpi.h>
     28 
     29 #include <Guid/GlobalVariable.h>
     30 #include <Guid/HobList.h>
     31 #include <Guid/TcgEventHob.h>
     32 #include <Guid/EventGroup.h>
     33 #include <Guid/EventExitBootServiceFailed.h>
     34 #include <Guid/TpmInstance.h>
     35 
     36 #include <Protocol/DevicePath.h>
     37 #include <Protocol/TcgService.h>
     38 #include <Protocol/AcpiTable.h>
     39 #include <Protocol/MpService.h>
     40 
     41 #include <Library/DebugLib.h>
     42 #include <Library/BaseMemoryLib.h>
     43 #include <Library/UefiRuntimeServicesTableLib.h>
     44 #include <Library/UefiDriverEntryPoint.h>
     45 #include <Library/HobLib.h>
     46 #include <Library/UefiBootServicesTableLib.h>
     47 #include <Library/BaseLib.h>
     48 #include <Library/MemoryAllocationLib.h>
     49 #include <Library/PrintLib.h>
     50 #include <Library/Tpm12DeviceLib.h>
     51 #include <Library/PcdLib.h>
     52 #include <Library/UefiLib.h>
     53 #include <Library/ReportStatusCodeLib.h>
     54 #include <Library/Tpm12CommandLib.h>
     55 #include <Library/BaseCryptLib.h>
     56 
     57 #define TCG_DXE_DATA_FROM_THIS(this)  \
     58   BASE_CR (this, TCG_DXE_DATA, TcgProtocol)
     59 
     60 typedef struct _TCG_DXE_DATA {
     61   EFI_TCG_PROTOCOL                  TcgProtocol;
     62   TCG_EFI_BOOT_SERVICE_CAPABILITY   BsCap;
     63   EFI_TCG_CLIENT_ACPI_TABLE         *TcgClientAcpiTable;
     64   EFI_TCG_SERVER_ACPI_TABLE         *TcgServerAcpiTable;
     65   UINTN                             EventLogSize;
     66   UINT8                             *LastEvent;
     67 } TCG_DXE_DATA;
     68 
     69 
     70 
     71 EFI_TCG_CLIENT_ACPI_TABLE           mTcgClientAcpiTemplate = {
     72   {
     73     EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
     74     sizeof (mTcgClientAcpiTemplate),
     75     0x02                      //Revision
     76     //
     77     // Compiler initializes the remaining bytes to 0
     78     // These fields should be filled in in production
     79     //
     80   },
     81   0,                          // 0 for PC Client Platform Class
     82   0,                          // Log Area Max Length
     83   (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1)  // Log Area Start Address
     84 };
     85 
     86 //
     87 // The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
     88 // the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,
     89 // this _UID can be changed and should match with the _UID setting of the TPM
     90 // ACPI device object
     91 //
     92 EFI_TCG_SERVER_ACPI_TABLE           mTcgServerAcpiTemplate = {
     93   {
     94     EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
     95     sizeof (mTcgServerAcpiTemplate),
     96     0x02                      //Revision
     97     //
     98     // Compiler initializes the remaining bytes to 0
     99     // These fields should be filled in in production
    100     //
    101   },
    102   1,                          // 1 for Server Platform Class
    103   0,                          // Reserved
    104   0,                          // Log Area Max Length
    105   (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address
    106   0x0120,                     // TCG Specification revision 1.2
    107   0,                          // Device Flags
    108   0,                          // Interrupt Flags
    109   0,                          // GPE
    110   {0},                        // Reserved 3 bytes
    111   0,                          // Global System Interrupt
    112   {
    113     EFI_ACPI_3_0_SYSTEM_MEMORY,
    114     0,
    115     0,
    116     EFI_ACPI_3_0_BYTE,
    117     0                         // Base Address
    118   },
    119   0,                          // Reserved
    120   {0},                        // Configuration Address
    121   0xFF,                       // ACPI _UID value of the device, can be changed for different platforms
    122   0,                          // ACPI _UID value of the device, can be changed for different platforms
    123   0,                          // ACPI _UID value of the device, can be changed for different platforms
    124   0                           // ACPI _UID value of the device, can be changed for different platforms
    125 };
    126 
    127 UINTN  mBootAttempts  = 0;
    128 CHAR16 mBootVarName[] = L"BootOrder";
    129 
    130 /**
    131   Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
    132   Caller is responsible to free LocationBuf.
    133 
    134   @param[out] LocationBuf          Returns Processor Location Buffer.
    135   @param[out] Num                  Returns processor number.
    136 
    137   @retval EFI_SUCCESS              Operation completed successfully.
    138   @retval EFI_UNSUPPORTED       MpService protocol not found.
    139 
    140 **/
    141 EFI_STATUS
    142 GetProcessorsCpuLocation (
    143     OUT  EFI_CPU_PHYSICAL_LOCATION   **LocationBuf,
    144     OUT  UINTN                       *Num
    145   )
    146 {
    147   EFI_STATUS                        Status;
    148   EFI_MP_SERVICES_PROTOCOL          *MpProtocol;
    149   UINTN                             ProcessorNum;
    150   UINTN                             EnabledProcessorNum;
    151   EFI_PROCESSOR_INFORMATION         ProcessorInfo;
    152   EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;
    153   UINTN                             Index;
    154 
    155   Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);
    156   if (EFI_ERROR (Status)) {
    157     //
    158     // MP protocol is not installed
    159     //
    160     return EFI_UNSUPPORTED;
    161   }
    162 
    163   Status = MpProtocol->GetNumberOfProcessors(
    164                          MpProtocol,
    165                          &ProcessorNum,
    166                          &EnabledProcessorNum
    167                          );
    168   if (EFI_ERROR(Status)){
    169     return Status;
    170   }
    171 
    172   Status = gBS->AllocatePool(
    173                   EfiBootServicesData,
    174                   sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,
    175                   (VOID **) &ProcessorLocBuf
    176                   );
    177   if (EFI_ERROR(Status)){
    178     return Status;
    179   }
    180 
    181   //
    182   // Get each processor Location info
    183   //
    184   for (Index = 0; Index < ProcessorNum; Index++) {
    185     Status = MpProtocol->GetProcessorInfo(
    186                            MpProtocol,
    187                            Index,
    188                            &ProcessorInfo
    189                            );
    190     if (EFI_ERROR(Status)){
    191       FreePool(ProcessorLocBuf);
    192       return Status;
    193     }
    194 
    195     //
    196     // Get all Processor Location info & measure
    197     //
    198     CopyMem(
    199       &ProcessorLocBuf[Index],
    200       &ProcessorInfo.Location,
    201       sizeof(EFI_CPU_PHYSICAL_LOCATION)
    202       );
    203   }
    204 
    205   *LocationBuf = ProcessorLocBuf;
    206   *Num = ProcessorNum;
    207 
    208   return Status;
    209 }
    210 
    211 /**
    212   This service provides EFI protocol capability information, state information
    213   about the TPM, and Event Log state information.
    214 
    215   @param[in]  This               Indicates the calling context
    216   @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
    217                                  structure and fills in the fields with the EFI protocol
    218                                  capability information and the current TPM state information.
    219   @param[out] TCGFeatureFlags    This is a pointer to the feature flags. No feature
    220                                  flags are currently defined so this parameter
    221                                  MUST be set to 0. However, in the future,
    222                                  feature flags may be defined that, for example,
    223                                  enable hash algorithm agility.
    224   @param[out] EventLogLocation   This is a pointer to the address of the event log in memory.
    225   @param[out] EventLogLastEntry  If the Event Log contains more than one entry,
    226                                  this is a pointer to the address of the start of
    227                                  the last entry in the event log in memory.
    228 
    229   @retval EFI_SUCCESS            Operation completed successfully.
    230   @retval EFI_INVALID_PARAMETER  ProtocolCapability does not match TCG capability.
    231 
    232 **/
    233 EFI_STATUS
    234 EFIAPI
    235 TcgDxeStatusCheck (
    236   IN      EFI_TCG_PROTOCOL                 *This,
    237   OUT     TCG_EFI_BOOT_SERVICE_CAPABILITY  *ProtocolCapability,
    238   OUT     UINT32                           *TCGFeatureFlags,
    239   OUT     EFI_PHYSICAL_ADDRESS             *EventLogLocation,
    240   OUT     EFI_PHYSICAL_ADDRESS             *EventLogLastEntry
    241   )
    242 {
    243   TCG_DXE_DATA                      *TcgData;
    244 
    245   TcgData = TCG_DXE_DATA_FROM_THIS (This);
    246 
    247   if (ProtocolCapability != NULL) {
    248     *ProtocolCapability = TcgData->BsCap;
    249   }
    250 
    251   if (TCGFeatureFlags != NULL) {
    252     *TCGFeatureFlags = 0;
    253   }
    254 
    255   if (EventLogLocation != NULL) {
    256     if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
    257       *EventLogLocation = TcgData->TcgClientAcpiTable->Lasa;
    258     } else {
    259       *EventLogLocation = TcgData->TcgServerAcpiTable->Lasa;
    260     }
    261   }
    262 
    263   if (EventLogLastEntry != NULL) {
    264     if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {
    265       *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;
    266     } else {
    267       *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)TcgData->LastEvent;
    268     }
    269   }
    270 
    271   return EFI_SUCCESS;
    272 }
    273 
    274 /**
    275 Single function calculates SHA1 digest value for all raw data. It
    276 combines Sha1Init(), Sha1Update() and Sha1Final().
    277 
    278 @param[in]  Data          Raw data to be digested.
    279 @param[in]  DataLen       Size of the raw data.
    280 @param[out] Digest        Pointer to a buffer that stores the final digest.
    281 
    282 @retval     EFI_SUCCESS   Always successfully calculate the final digest.
    283 **/
    284 EFI_STATUS
    285 EFIAPI
    286 TpmCommHashAll (
    287   IN  CONST UINT8       *Data,
    288   IN        UINTN       DataLen,
    289   OUT       TPM_DIGEST  *Digest
    290   )
    291 {
    292   VOID   *Sha1Ctx;
    293   UINTN  CtxSize;
    294 
    295   CtxSize = Sha1GetContextSize ();
    296   Sha1Ctx = AllocatePool (CtxSize);
    297   ASSERT (Sha1Ctx != NULL);
    298 
    299   Sha1Init (Sha1Ctx);
    300   Sha1Update (Sha1Ctx, Data, DataLen);
    301   Sha1Final (Sha1Ctx, (UINT8 *)Digest);
    302 
    303   FreePool (Sha1Ctx);
    304 
    305   return EFI_SUCCESS;
    306 }
    307 
    308 /**
    309   This service abstracts the capability to do a hash operation on a data buffer.
    310 
    311   @param[in]      This             Indicates the calling context
    312   @param[in]      HashData         Pointer to the data buffer to be hashed
    313   @param[in]      HashDataLen      Length of the data buffer to be hashed
    314   @param[in]      AlgorithmId      Identification of the Algorithm to use for the hashing operation
    315   @param[in, out] HashedDataLen    Resultant length of the hashed data
    316   @param[in, out] HashedDataResult Resultant buffer of the hashed data
    317 
    318   @retval EFI_SUCCESS              Operation completed successfully.
    319   @retval EFI_INVALID_PARAMETER    HashDataLen is NULL.
    320   @retval EFI_INVALID_PARAMETER    HashDataLenResult is NULL.
    321   @retval EFI_OUT_OF_RESOURCES     Cannot allocate buffer of size *HashedDataLen.
    322   @retval EFI_UNSUPPORTED          AlgorithmId not supported.
    323   @retval EFI_BUFFER_TOO_SMALL     *HashedDataLen < sizeof (TCG_DIGEST).
    324 
    325 **/
    326 EFI_STATUS
    327 EFIAPI
    328 TcgDxeHashAll (
    329   IN      EFI_TCG_PROTOCOL          *This,
    330   IN      UINT8                     *HashData,
    331   IN      UINT64                    HashDataLen,
    332   IN      TCG_ALGORITHM_ID          AlgorithmId,
    333   IN OUT  UINT64                    *HashedDataLen,
    334   IN OUT  UINT8                     **HashedDataResult
    335   )
    336 {
    337   if (HashedDataLen == NULL || HashedDataResult == NULL) {
    338     return EFI_INVALID_PARAMETER;
    339   }
    340 
    341   switch (AlgorithmId) {
    342     case TPM_ALG_SHA:
    343       if (*HashedDataLen == 0) {
    344         *HashedDataLen    = sizeof (TPM_DIGEST);
    345         *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);
    346         if (*HashedDataResult == NULL) {
    347           return EFI_OUT_OF_RESOURCES;
    348         }
    349       }
    350 
    351       if (*HashedDataLen < sizeof (TPM_DIGEST)) {
    352         *HashedDataLen = sizeof (TPM_DIGEST);
    353         return EFI_BUFFER_TOO_SMALL;
    354       }
    355       *HashedDataLen = sizeof (TPM_DIGEST);
    356 
    357       if (*HashedDataResult == NULL) {
    358         *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);
    359       }
    360 
    361       return TpmCommHashAll (
    362                HashData,
    363                (UINTN) HashDataLen,
    364                (TPM_DIGEST*)*HashedDataResult
    365                );
    366     default:
    367       return EFI_UNSUPPORTED;
    368   }
    369 }
    370 
    371 /**
    372 Add a new entry to the Event Log.
    373 
    374 @param[in, out] EventLogPtr   Pointer to the Event Log data.
    375 @param[in, out] LogSize       Size of the Event Log.
    376 @param[in]      MaxSize       Maximum size of the Event Log.
    377 @param[in]      NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
    378 @param[in]      NewEventData  Pointer to the new event data.
    379 
    380 @retval EFI_SUCCESS           The new event log entry was added.
    381 @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    382 
    383 **/
    384 EFI_STATUS
    385 TpmCommLogEvent (
    386   IN OUT  UINT8                     **EventLogPtr,
    387   IN OUT  UINTN                     *LogSize,
    388   IN      UINTN                     MaxSize,
    389   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
    390   IN      UINT8                     *NewEventData
    391   )
    392 {
    393   UINTN                            NewLogSize;
    394 
    395   //
    396   // Prevent Event Overflow
    397   //
    398   if (NewEventHdr->EventSize > (UINTN)(~0) - sizeof (*NewEventHdr)) {
    399     return EFI_OUT_OF_RESOURCES;
    400   }
    401 
    402   NewLogSize = sizeof (*NewEventHdr) + NewEventHdr->EventSize;
    403   if (NewLogSize > MaxSize - *LogSize) {
    404     return EFI_OUT_OF_RESOURCES;
    405   }
    406 
    407   *EventLogPtr += *LogSize;
    408   *LogSize += NewLogSize;
    409   CopyMem (*EventLogPtr, NewEventHdr, sizeof (*NewEventHdr));
    410   CopyMem (
    411     *EventLogPtr + sizeof (*NewEventHdr),
    412     NewEventData,
    413     NewEventHdr->EventSize
    414     );
    415   return EFI_SUCCESS;
    416 }
    417 
    418 /**
    419   Add a new entry to the Event Log.
    420 
    421   @param[in] TcgData       TCG_DXE_DATA structure.
    422   @param[in] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
    423   @param[in] NewEventData  Pointer to the new event data.
    424 
    425   @retval EFI_SUCCESS           The new event log entry was added.
    426   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    427 
    428 **/
    429 EFI_STATUS
    430 EFIAPI
    431 TcgDxeLogEventI (
    432   IN      TCG_DXE_DATA              *TcgData,
    433   IN      TCG_PCR_EVENT_HDR         *NewEventHdr,
    434   IN      UINT8                     *NewEventData
    435   )
    436 {
    437   if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
    438     TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgClientAcpiTable->Lasa;
    439     return TpmCommLogEvent (
    440              &TcgData->LastEvent,
    441              &TcgData->EventLogSize,
    442              (UINTN)TcgData->TcgClientAcpiTable->Laml,
    443              NewEventHdr,
    444              NewEventData
    445              );
    446   } else {
    447     TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgServerAcpiTable->Lasa;
    448     return TpmCommLogEvent (
    449              &TcgData->LastEvent,
    450              &TcgData->EventLogSize,
    451              (UINTN)TcgData->TcgServerAcpiTable->Laml,
    452              NewEventHdr,
    453              NewEventData
    454              );
    455   }
    456 }
    457 
    458 /**
    459   This service abstracts the capability to add an entry to the Event Log.
    460 
    461   @param[in]      This           Indicates the calling context
    462   @param[in]      TCGLogData     Pointer to the start of the data buffer containing
    463                                  the TCG_PCR_EVENT data structure. All fields in
    464                                  this structure are properly filled by the caller.
    465   @param[in, out] EventNumber    The event number of the event just logged
    466   @param[in]      Flags          Indicate additional flags. Only one flag has been
    467                                  defined at this time, which is 0x01 and means the
    468                                  extend operation should not be performed. All
    469                                  other bits are reserved.
    470 
    471   @retval EFI_SUCCESS            Operation completed successfully.
    472   @retval EFI_OUT_OF_RESOURCES   Insufficient memory in the event log to complete this action.
    473 
    474 **/
    475 EFI_STATUS
    476 EFIAPI
    477 TcgDxeLogEvent (
    478   IN      EFI_TCG_PROTOCOL          *This,
    479   IN      TCG_PCR_EVENT             *TCGLogData,
    480   IN OUT  UINT32                    *EventNumber,
    481   IN      UINT32                    Flags
    482   )
    483 {
    484   TCG_DXE_DATA  *TcgData;
    485 
    486   if (TCGLogData == NULL){
    487     return EFI_INVALID_PARAMETER;
    488   }
    489 
    490   TcgData = TCG_DXE_DATA_FROM_THIS (This);
    491 
    492   if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {
    493     return EFI_DEVICE_ERROR;
    494   }
    495   return TcgDxeLogEventI (
    496            TcgData,
    497            (TCG_PCR_EVENT_HDR*)TCGLogData,
    498            TCGLogData->Event
    499            );
    500 }
    501 
    502 /**
    503   This service is a proxy for commands to the TPM.
    504 
    505   @param[in]  This                        Indicates the calling context
    506   @param[in]  TpmInputParameterBlockSize  Size of the TPM input parameter block
    507   @param[in]  TpmInputParameterBlock      Pointer to the TPM input parameter block
    508   @param[in]  TpmOutputParameterBlockSize Size of the TPM output parameter block
    509   @param[in]  TpmOutputParameterBlock     Pointer to the TPM output parameter block
    510 
    511   @retval     EFI_SUCCESS                 Operation completed successfully.
    512   @retval     EFI_INVALID_PARAMETER       Invalid ordinal.
    513   @retval     EFI_UNSUPPORTED             Current Task Priority Level  >= EFI_TPL_CALLBACK.
    514   @retval     EFI_TIMEOUT                 The TIS timed-out.
    515 
    516 **/
    517 EFI_STATUS
    518 EFIAPI
    519 TcgDxePassThroughToTpm (
    520   IN      EFI_TCG_PROTOCOL          *This,
    521   IN      UINT32                    TpmInputParameterBlockSize,
    522   IN      UINT8                     *TpmInputParameterBlock,
    523   IN      UINT32                    TpmOutputParameterBlockSize,
    524   IN      UINT8                     *TpmOutputParameterBlock
    525   )
    526 {
    527   if (TpmInputParameterBlock == NULL ||
    528       TpmOutputParameterBlock == NULL ||
    529       TpmInputParameterBlockSize == 0 ||
    530       TpmOutputParameterBlockSize == 0) {
    531     return EFI_INVALID_PARAMETER;
    532   }
    533 
    534   return Tpm12SubmitCommand (
    535            TpmInputParameterBlockSize,
    536            TpmInputParameterBlock,
    537            &TpmOutputParameterBlockSize,
    538            TpmOutputParameterBlock
    539            );
    540 }
    541 
    542 /**
    543   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
    544   and add an entry to the Event Log.
    545 
    546   @param[in]      TcgData       TCG_DXE_DATA structure.
    547   @param[in]      HashData      Physical address of the start of the data buffer
    548                                 to be hashed, extended, and logged.
    549   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData
    550   @param[in, out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
    551   @param[in]      NewEventData  Pointer to the new event data.
    552 
    553   @retval EFI_SUCCESS           Operation completed successfully.
    554   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
    555   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
    556 
    557 **/
    558 EFI_STATUS
    559 EFIAPI
    560 TcgDxeHashLogExtendEventI (
    561   IN      TCG_DXE_DATA              *TcgData,
    562   IN      UINT8                     *HashData,
    563   IN      UINT64                    HashDataLen,
    564   IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,
    565   IN      UINT8                     *NewEventData
    566   )
    567 {
    568   EFI_STATUS                        Status;
    569 
    570   if (!TcgData->BsCap.TPMPresentFlag) {
    571     return EFI_DEVICE_ERROR;
    572   }
    573 
    574   if (HashDataLen > 0 || HashData != NULL) {
    575     Status = TpmCommHashAll (
    576                HashData,
    577                (UINTN) HashDataLen,
    578                &NewEventHdr->Digest
    579                );
    580     if (EFI_ERROR(Status)) {
    581       DEBUG ((DEBUG_ERROR, "TpmCommHashAll Failed. %x\n", Status));
    582       goto Done;
    583     }
    584   }
    585 
    586   Status = Tpm12Extend (
    587              &NewEventHdr->Digest,
    588              NewEventHdr->PCRIndex,
    589              NULL
    590              );
    591   if (!EFI_ERROR (Status)) {
    592     Status = TcgDxeLogEventI (TcgData, NewEventHdr, NewEventData);
    593   }
    594 
    595 Done:
    596   if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {
    597     DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status));
    598     TcgData->BsCap.TPMPresentFlag = FALSE;
    599     REPORT_STATUS_CODE (
    600       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    601       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
    602       );
    603     Status = EFI_DEVICE_ERROR;
    604   }
    605 
    606   return Status;
    607 }
    608 
    609 /**
    610   This service abstracts the capability to do a hash operation on a data buffer,
    611   extend a specific TPM PCR with the hash result, and add an entry to the Event Log
    612 
    613   @param[in]      This               Indicates the calling context
    614   @param[in]      HashData           Physical address of the start of the data buffer
    615                                      to be hashed, extended, and logged.
    616   @param[in]      HashDataLen        The length, in bytes, of the buffer referenced by HashData
    617   @param[in]      AlgorithmId        Identification of the Algorithm to use for the hashing operation
    618   @param[in, out] TCGLogData         The physical address of the start of the data
    619                                      buffer containing the TCG_PCR_EVENT data structure.
    620   @param[in, out] EventNumber        The event number of the event just logged.
    621   @param[out]     EventLogLastEntry  Physical address of the first byte of the entry
    622                                      just placed in the Event Log. If the Event Log was
    623                                      empty when this function was called then this physical
    624                                      address will be the same as the physical address of
    625                                      the start of the Event Log.
    626 
    627   @retval EFI_SUCCESS                Operation completed successfully.
    628   @retval EFI_UNSUPPORTED            AlgorithmId != TPM_ALG_SHA.
    629   @retval EFI_UNSUPPORTED            Current TPL >= EFI_TPL_CALLBACK.
    630   @retval EFI_DEVICE_ERROR           The command was unsuccessful.
    631 
    632 **/
    633 EFI_STATUS
    634 EFIAPI
    635 TcgDxeHashLogExtendEvent (
    636   IN      EFI_TCG_PROTOCOL          *This,
    637   IN      EFI_PHYSICAL_ADDRESS      HashData,
    638   IN      UINT64                    HashDataLen,
    639   IN      TPM_ALGORITHM_ID          AlgorithmId,
    640   IN OUT  TCG_PCR_EVENT             *TCGLogData,
    641   IN OUT  UINT32                    *EventNumber,
    642      OUT  EFI_PHYSICAL_ADDRESS      *EventLogLastEntry
    643   )
    644 {
    645   TCG_DXE_DATA  *TcgData;
    646   EFI_STATUS    Status;
    647 
    648   if (TCGLogData == NULL || EventLogLastEntry == NULL){
    649     return EFI_INVALID_PARAMETER;
    650   }
    651 
    652   TcgData = TCG_DXE_DATA_FROM_THIS (This);
    653 
    654   if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {
    655     return EFI_DEVICE_ERROR;
    656   }
    657 
    658   if (AlgorithmId != TPM_ALG_SHA) {
    659     return EFI_UNSUPPORTED;
    660   }
    661 
    662   if (HashData == 0 && HashDataLen > 0) {
    663     return EFI_INVALID_PARAMETER;
    664   }
    665 
    666   Status = TcgDxeHashLogExtendEventI (
    667              TcgData,
    668              (UINT8 *) (UINTN) HashData,
    669              HashDataLen,
    670              (TCG_PCR_EVENT_HDR*)TCGLogData,
    671              TCGLogData->Event
    672              );
    673 
    674   if (!EFI_ERROR(Status)){
    675     *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN) TcgData->LastEvent;
    676   }
    677 
    678   return Status;
    679 }
    680 
    681 TCG_DXE_DATA                 mTcgDxeData = {
    682   {
    683     TcgDxeStatusCheck,
    684     TcgDxeHashAll,
    685     TcgDxeLogEvent,
    686     TcgDxePassThroughToTpm,
    687     TcgDxeHashLogExtendEvent
    688   },
    689   {
    690     sizeof (mTcgDxeData.BsCap),
    691     { 1, 2, 0, 0 },
    692     { 1, 2, 0, 0 },
    693     1,
    694     TRUE,
    695     FALSE
    696   },
    697   &mTcgClientAcpiTemplate,
    698   &mTcgServerAcpiTemplate,
    699   0,
    700   NULL
    701 };
    702 
    703 /**
    704   Initialize the Event Log and log events passed from the PEI phase.
    705 
    706   @retval EFI_SUCCESS           Operation completed successfully.
    707   @retval EFI_OUT_OF_RESOURCES  Out of memory.
    708 
    709 **/
    710 EFI_STATUS
    711 EFIAPI
    712 SetupEventLog (
    713   VOID
    714   )
    715 {
    716   EFI_STATUS            Status;
    717   TCG_PCR_EVENT         *TcgEvent;
    718   EFI_PEI_HOB_POINTERS  GuidHob;
    719   EFI_PHYSICAL_ADDRESS  Lasa;
    720 
    721   if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
    722     Lasa = mTcgClientAcpiTemplate.Lasa;
    723 
    724     Status = gBS->AllocatePages (
    725                     AllocateMaxAddress,
    726                     EfiACPIMemoryNVS,
    727                     EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),
    728                     &Lasa
    729                     );
    730     if (EFI_ERROR (Status)) {
    731       return Status;
    732     }
    733     mTcgClientAcpiTemplate.Lasa = Lasa;
    734     //
    735     // To initialize them as 0xFF is recommended
    736     // because the OS can know the last entry for that.
    737     //
    738     SetMem ((VOID *)(UINTN)mTcgClientAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);
    739     mTcgClientAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);
    740 
    741   } else {
    742     Lasa = mTcgServerAcpiTemplate.Lasa;
    743 
    744     Status = gBS->AllocatePages (
    745                     AllocateMaxAddress,
    746                     EfiACPIMemoryNVS,
    747                     EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),
    748                     &Lasa
    749                     );
    750     if (EFI_ERROR (Status)) {
    751       return Status;
    752     }
    753     mTcgServerAcpiTemplate.Lasa = Lasa;
    754     //
    755     // To initialize them as 0xFF is recommended
    756     // because the OS can know the last entry for that.
    757     //
    758     SetMem ((VOID *)(UINTN)mTcgServerAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);
    759     mTcgServerAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);
    760   }
    761 
    762   GuidHob.Raw = GetHobList ();
    763   while (!EFI_ERROR (Status) &&
    764          (GuidHob.Raw = GetNextGuidHob (&gTcgEventEntryHobGuid, GuidHob.Raw)) != NULL) {
    765     TcgEvent    = GET_GUID_HOB_DATA (GuidHob.Guid);
    766     GuidHob.Raw = GET_NEXT_HOB (GuidHob);
    767     Status = TcgDxeLogEventI (
    768                &mTcgDxeData,
    769                (TCG_PCR_EVENT_HDR*)TcgEvent,
    770                TcgEvent->Event
    771                );
    772   }
    773 
    774   return Status;
    775 }
    776 
    777 /**
    778   Measure and log an action string, and extend the measurement result into PCR[5].
    779 
    780   @param[in] String           A specific string that indicates an Action event.
    781 
    782   @retval EFI_SUCCESS         Operation completed successfully.
    783   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
    784 
    785 **/
    786 EFI_STATUS
    787 EFIAPI
    788 TcgMeasureAction (
    789   IN      CHAR8                     *String
    790   )
    791 {
    792   TCG_PCR_EVENT_HDR                 TcgEvent;
    793 
    794   TcgEvent.PCRIndex  = 5;
    795   TcgEvent.EventType = EV_EFI_ACTION;
    796   TcgEvent.EventSize = (UINT32)AsciiStrLen (String);
    797   return TcgDxeHashLogExtendEventI (
    798            &mTcgDxeData,
    799            (UINT8*)String,
    800            TcgEvent.EventSize,
    801            &TcgEvent,
    802            (UINT8 *) String
    803            );
    804 }
    805 
    806 /**
    807   Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
    808 
    809   @retval EFI_SUCCESS         Operation completed successfully.
    810   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
    811 
    812 **/
    813 EFI_STATUS
    814 EFIAPI
    815 MeasureHandoffTables (
    816   VOID
    817   )
    818 {
    819   EFI_STATUS                        Status;
    820   TCG_PCR_EVENT_HDR                 TcgEvent;
    821   EFI_HANDOFF_TABLE_POINTERS        HandoffTables;
    822   UINTN                             ProcessorNum;
    823   EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;
    824 
    825   ProcessorLocBuf = NULL;
    826   Status = EFI_SUCCESS;
    827 
    828   if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {
    829     //
    830     // Tcg Server spec.
    831     // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
    832     //
    833     Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);
    834 
    835     if (!EFI_ERROR(Status)){
    836       TcgEvent.PCRIndex  = 1;
    837       TcgEvent.EventType = EV_TABLE_OF_DEVICES;
    838       TcgEvent.EventSize = sizeof (HandoffTables);
    839 
    840       HandoffTables.NumberOfTables = 1;
    841       HandoffTables.TableEntry[0].VendorGuid  = gEfiMpServiceProtocolGuid;
    842       HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;
    843 
    844       Status = TcgDxeHashLogExtendEventI (
    845                  &mTcgDxeData,
    846                  (UINT8*)(UINTN)ProcessorLocBuf,
    847                  sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,
    848                  &TcgEvent,
    849                  (UINT8*)&HandoffTables
    850                  );
    851 
    852       FreePool(ProcessorLocBuf);
    853     }
    854   }
    855 
    856   return Status;
    857 }
    858 
    859 /**
    860   Measure and log Separator event, and extend the measurement result into a specific PCR.
    861 
    862   @param[in] PCRIndex         PCR index.
    863 
    864   @retval EFI_SUCCESS         Operation completed successfully.
    865   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
    866 
    867 **/
    868 EFI_STATUS
    869 EFIAPI
    870 MeasureSeparatorEvent (
    871   IN      TPM_PCRINDEX              PCRIndex
    872   )
    873 {
    874   TCG_PCR_EVENT_HDR                 TcgEvent;
    875   UINT32                            EventData;
    876 
    877   EventData = 0;
    878   TcgEvent.PCRIndex  = PCRIndex;
    879   TcgEvent.EventType = EV_SEPARATOR;
    880   TcgEvent.EventSize = (UINT32)sizeof (EventData);
    881   return TcgDxeHashLogExtendEventI (
    882            &mTcgDxeData,
    883            (UINT8 *)&EventData,
    884            sizeof (EventData),
    885            &TcgEvent,
    886            (UINT8 *)&EventData
    887            );
    888 }
    889 
    890 /**
    891   Read an EFI Variable.
    892 
    893   This function allocates a buffer to return the contents of the variable. The caller is
    894   responsible for freeing the buffer.
    895 
    896   @param[in]  VarName     A Null-terminated string that is the name of the vendor's variable.
    897   @param[in]  VendorGuid  A unique identifier for the vendor.
    898   @param[out] VarSize     The size of the variable data.
    899 
    900   @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
    901 
    902 **/
    903 VOID *
    904 EFIAPI
    905 ReadVariable (
    906   IN      CHAR16                    *VarName,
    907   IN      EFI_GUID                  *VendorGuid,
    908   OUT     UINTN                     *VarSize
    909   )
    910 {
    911   EFI_STATUS                        Status;
    912   VOID                              *VarData;
    913 
    914   *VarSize = 0;
    915   Status = gRT->GetVariable (
    916                   VarName,
    917                   VendorGuid,
    918                   NULL,
    919                   VarSize,
    920                   NULL
    921                   );
    922   if (Status != EFI_BUFFER_TOO_SMALL) {
    923     return NULL;
    924   }
    925 
    926   VarData = AllocatePool (*VarSize);
    927   if (VarData != NULL) {
    928     Status = gRT->GetVariable (
    929                     VarName,
    930                     VendorGuid,
    931                     NULL,
    932                     VarSize,
    933                     VarData
    934                     );
    935     if (EFI_ERROR (Status)) {
    936       FreePool (VarData);
    937       VarData = NULL;
    938       *VarSize = 0;
    939     }
    940   }
    941   return VarData;
    942 }
    943 
    944 /**
    945   Measure and log an EFI variable, and extend the measurement result into a specific PCR.
    946 
    947   @param[in]  PCRIndex          PCR Index.
    948   @param[in]  EventType         Event type.
    949   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
    950   @param[in]  VendorGuid        A unique identifier for the vendor.
    951   @param[in]  VarData           The content of the variable data.
    952   @param[in]  VarSize           The size of the variable data.
    953 
    954   @retval EFI_SUCCESS           Operation completed successfully.
    955   @retval EFI_OUT_OF_RESOURCES  Out of memory.
    956   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
    957 
    958 **/
    959 EFI_STATUS
    960 EFIAPI
    961 MeasureVariable (
    962   IN      TPM_PCRINDEX              PCRIndex,
    963   IN      TCG_EVENTTYPE             EventType,
    964   IN      CHAR16                    *VarName,
    965   IN      EFI_GUID                  *VendorGuid,
    966   IN      VOID                      *VarData,
    967   IN      UINTN                     VarSize
    968   )
    969 {
    970   EFI_STATUS                        Status;
    971   TCG_PCR_EVENT_HDR                 TcgEvent;
    972   UINTN                             VarNameLength;
    973   EFI_VARIABLE_DATA                 *VarLog;
    974 
    975   VarNameLength      = StrLen (VarName);
    976   TcgEvent.PCRIndex  = PCRIndex;
    977   TcgEvent.EventType = EventType;
    978   TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
    979                         - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
    980 
    981   VarLog = (EFI_VARIABLE_DATA*)AllocatePool (TcgEvent.EventSize);
    982   if (VarLog == NULL) {
    983     return EFI_OUT_OF_RESOURCES;
    984   }
    985 
    986   VarLog->VariableName       = *VendorGuid;
    987   VarLog->UnicodeNameLength  = VarNameLength;
    988   VarLog->VariableDataLength = VarSize;
    989   CopyMem (
    990      VarLog->UnicodeName,
    991      VarName,
    992      VarNameLength * sizeof (*VarName)
    993      );
    994   CopyMem (
    995      (CHAR16 *)VarLog->UnicodeName + VarNameLength,
    996      VarData,
    997      VarSize
    998      );
    999 
   1000   Status = TcgDxeHashLogExtendEventI (
   1001              &mTcgDxeData,
   1002              (UINT8*)VarLog,
   1003              TcgEvent.EventSize,
   1004              &TcgEvent,
   1005              (UINT8*)VarLog
   1006              );
   1007   FreePool (VarLog);
   1008   return Status;
   1009 }
   1010 
   1011 /**
   1012   Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
   1013 
   1014   @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.
   1015   @param[in]   VendorGuid       A unique identifier for the vendor.
   1016   @param[out]  VarSize          The size of the variable data.
   1017   @param[out]  VarData          Pointer to the content of the variable.
   1018 
   1019   @retval EFI_SUCCESS           Operation completed successfully.
   1020   @retval EFI_OUT_OF_RESOURCES  Out of memory.
   1021   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
   1022 
   1023 **/
   1024 EFI_STATUS
   1025 EFIAPI
   1026 ReadAndMeasureBootVariable (
   1027   IN      CHAR16                    *VarName,
   1028   IN      EFI_GUID                  *VendorGuid,
   1029   OUT     UINTN                     *VarSize,
   1030   OUT     VOID                      **VarData
   1031   )
   1032 {
   1033   EFI_STATUS                        Status;
   1034 
   1035   *VarData = ReadVariable (VarName, VendorGuid, VarSize);
   1036   if (*VarData == NULL) {
   1037     return EFI_NOT_FOUND;
   1038   }
   1039 
   1040   Status = MeasureVariable (
   1041              5,
   1042              EV_EFI_VARIABLE_BOOT,
   1043              VarName,
   1044              VendorGuid,
   1045              *VarData,
   1046              *VarSize
   1047              );
   1048   return Status;
   1049 }
   1050 
   1051 /**
   1052   Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
   1053 
   1054   The EFI boot variables are BootOrder and Boot#### variables.
   1055 
   1056   @retval EFI_SUCCESS           Operation completed successfully.
   1057   @retval EFI_OUT_OF_RESOURCES  Out of memory.
   1058   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
   1059 
   1060 **/
   1061 EFI_STATUS
   1062 EFIAPI
   1063 MeasureAllBootVariables (
   1064   VOID
   1065   )
   1066 {
   1067   EFI_STATUS                        Status;
   1068   UINT16                            *BootOrder;
   1069   UINTN                             BootCount;
   1070   UINTN                             Index;
   1071   VOID                              *BootVarData;
   1072   UINTN                             Size;
   1073 
   1074   Status = ReadAndMeasureBootVariable (
   1075              mBootVarName,
   1076              &gEfiGlobalVariableGuid,
   1077              &BootCount,
   1078              (VOID **) &BootOrder
   1079              );
   1080   if (Status == EFI_NOT_FOUND || BootOrder == NULL) {
   1081     return EFI_SUCCESS;
   1082   }
   1083 
   1084   if (EFI_ERROR (Status)) {
   1085     //
   1086     // BootOrder can't be NULL if status is not EFI_NOT_FOUND
   1087     //
   1088     FreePool (BootOrder);
   1089     return Status;
   1090   }
   1091 
   1092   BootCount /= sizeof (*BootOrder);
   1093   for (Index = 0; Index < BootCount; Index++) {
   1094     UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);
   1095     Status = ReadAndMeasureBootVariable (
   1096                mBootVarName,
   1097                &gEfiGlobalVariableGuid,
   1098                &Size,
   1099                &BootVarData
   1100                );
   1101     if (!EFI_ERROR (Status)) {
   1102       FreePool (BootVarData);
   1103     }
   1104   }
   1105 
   1106   FreePool (BootOrder);
   1107   return EFI_SUCCESS;
   1108 }
   1109 
   1110 /**
   1111   Ready to Boot Event notification handler.
   1112 
   1113   Sequence of OS boot events is measured in this event notification handler.
   1114 
   1115   @param[in]  Event     Event whose notification function is being invoked
   1116   @param[in]  Context   Pointer to the notification function's context
   1117 
   1118 **/
   1119 VOID
   1120 EFIAPI
   1121 OnReadyToBoot (
   1122   IN      EFI_EVENT                 Event,
   1123   IN      VOID                      *Context
   1124   )
   1125 {
   1126   EFI_STATUS                        Status;
   1127   TPM_PCRINDEX                      PcrIndex;
   1128 
   1129   if (mBootAttempts == 0) {
   1130 
   1131     //
   1132     // Measure handoff tables.
   1133     //
   1134     Status = MeasureHandoffTables ();
   1135     if (EFI_ERROR (Status)) {
   1136       DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));
   1137     }
   1138 
   1139     //
   1140     // Measure BootOrder & Boot#### variables.
   1141     //
   1142     Status = MeasureAllBootVariables ();
   1143     if (EFI_ERROR (Status)) {
   1144       DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));
   1145     }
   1146 
   1147     //
   1148     // 1. This is the first boot attempt.
   1149     //
   1150     Status = TcgMeasureAction (
   1151                EFI_CALLING_EFI_APPLICATION
   1152                );
   1153     if (EFI_ERROR (Status)) {
   1154       DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));
   1155     }
   1156 
   1157     //
   1158     // 2. Draw a line between pre-boot env and entering post-boot env.
   1159     //
   1160     for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {
   1161       Status = MeasureSeparatorEvent (PcrIndex);
   1162       if (EFI_ERROR (Status)) {
   1163         DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n"));
   1164       }
   1165     }
   1166 
   1167     //
   1168     // 3. Measure GPT. It would be done in SAP driver.
   1169     //
   1170 
   1171     //
   1172     // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
   1173     //
   1174 
   1175     //
   1176     // 5. Read & Measure variable. BootOrder already measured.
   1177     //
   1178   } else {
   1179     //
   1180     // 6. Not first attempt, meaning a return from last attempt
   1181     //
   1182     Status = TcgMeasureAction (
   1183                EFI_RETURNING_FROM_EFI_APPLICATOIN
   1184                );
   1185     if (EFI_ERROR (Status)) {
   1186       DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN));
   1187     }
   1188   }
   1189 
   1190   DEBUG ((EFI_D_INFO, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
   1191   //
   1192   // Increase boot attempt counter.
   1193   //
   1194   mBootAttempts++;
   1195 }
   1196 
   1197 /**
   1198   Install TCG ACPI Table when ACPI Table Protocol is available.
   1199 
   1200   A system's firmware uses an ACPI table to identify the system's TCG capabilities
   1201   to the Post-Boot environment. The information in this ACPI table is not guaranteed
   1202   to be valid until the Host Platform transitions from pre-boot state to post-boot state.
   1203 
   1204   @param[in]  Event     Event whose notification function is being invoked
   1205   @param[in]  Context   Pointer to the notification function's context
   1206 **/
   1207 VOID
   1208 EFIAPI
   1209 InstallAcpiTable (
   1210   IN EFI_EVENT                      Event,
   1211   IN VOID*                          Context
   1212   )
   1213 {
   1214   UINTN                             TableKey;
   1215   EFI_STATUS                        Status;
   1216   EFI_ACPI_TABLE_PROTOCOL           *AcpiTable;
   1217   UINT8                             Checksum;
   1218   UINT64                            OemTableId;
   1219 
   1220   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
   1221   if (EFI_ERROR (Status)) {
   1222     return;
   1223   }
   1224 
   1225   if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
   1226     CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));
   1227     OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
   1228     CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
   1229     mTcgClientAcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
   1230     mTcgClientAcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
   1231     mTcgClientAcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
   1232     //
   1233     // The ACPI table must be checksumed before calling the InstallAcpiTable()
   1234     // service of the ACPI table protocol to install it.
   1235     //
   1236     Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));
   1237     mTcgClientAcpiTemplate.Header.Checksum = Checksum;
   1238 
   1239     Status = AcpiTable->InstallAcpiTable (
   1240                             AcpiTable,
   1241                             &mTcgClientAcpiTemplate,
   1242                             sizeof (mTcgClientAcpiTemplate),
   1243                             &TableKey
   1244                             );
   1245   } else {
   1246     CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));
   1247     OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
   1248     CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
   1249     mTcgServerAcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
   1250     mTcgServerAcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
   1251     mTcgServerAcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
   1252     //
   1253     // The ACPI table must be checksumed before calling the InstallAcpiTable()
   1254     // service of the ACPI table protocol to install it.
   1255     //
   1256     Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));
   1257     mTcgServerAcpiTemplate.Header.Checksum = Checksum;
   1258 
   1259     mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);
   1260     Status = AcpiTable->InstallAcpiTable (
   1261                             AcpiTable,
   1262                             &mTcgServerAcpiTemplate,
   1263                             sizeof (mTcgServerAcpiTemplate),
   1264                             &TableKey
   1265                             );
   1266   }
   1267 
   1268   if (EFI_ERROR (Status)) {
   1269     DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure"));
   1270   }
   1271 }
   1272 
   1273 /**
   1274   Exit Boot Services Event notification handler.
   1275 
   1276   Measure invocation and success of ExitBootServices.
   1277 
   1278   @param[in]  Event     Event whose notification function is being invoked
   1279   @param[in]  Context   Pointer to the notification function's context
   1280 
   1281 **/
   1282 VOID
   1283 EFIAPI
   1284 OnExitBootServices (
   1285   IN      EFI_EVENT                 Event,
   1286   IN      VOID                      *Context
   1287   )
   1288 {
   1289   EFI_STATUS    Status;
   1290 
   1291   //
   1292   // Measure invocation of ExitBootServices,
   1293   //
   1294   Status = TcgMeasureAction (
   1295              EFI_EXIT_BOOT_SERVICES_INVOCATION
   1296              );
   1297   if (EFI_ERROR (Status)) {
   1298     DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));
   1299   }
   1300 
   1301   //
   1302   // Measure success of ExitBootServices
   1303   //
   1304   Status = TcgMeasureAction (
   1305              EFI_EXIT_BOOT_SERVICES_SUCCEEDED
   1306              );
   1307   if (EFI_ERROR (Status)){
   1308     DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));
   1309   }
   1310 }
   1311 
   1312 /**
   1313   Exit Boot Services Failed Event notification handler.
   1314 
   1315   Measure Failure of ExitBootServices.
   1316 
   1317   @param[in]  Event     Event whose notification function is being invoked
   1318   @param[in]  Context   Pointer to the notification function's context
   1319 
   1320 **/
   1321 VOID
   1322 EFIAPI
   1323 OnExitBootServicesFailed (
   1324   IN      EFI_EVENT                 Event,
   1325   IN      VOID                      *Context
   1326   )
   1327 {
   1328   EFI_STATUS    Status;
   1329 
   1330   //
   1331   // Measure Failure of ExitBootServices,
   1332   //
   1333   Status = TcgMeasureAction (
   1334              EFI_EXIT_BOOT_SERVICES_FAILED
   1335              );
   1336   if (EFI_ERROR (Status)){
   1337     DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));
   1338   }
   1339 }
   1340 
   1341 /**
   1342   Get TPM Deactivated state.
   1343 
   1344   @param[out] TPMDeactivatedFlag   Returns TPM Deactivated state.
   1345 
   1346   @retval EFI_SUCCESS              Operation completed successfully.
   1347   @retval EFI_DEVICE_ERROR         The operation was unsuccessful.
   1348 
   1349 **/
   1350 EFI_STATUS
   1351 GetTpmStatus (
   1352   OUT BOOLEAN  *TPMDeactivatedFlag
   1353   )
   1354 {
   1355   EFI_STATUS         Status;
   1356   TPM_STCLEAR_FLAGS  VolatileFlags;
   1357 
   1358   Status = Tpm12GetCapabilityFlagVolatile (&VolatileFlags);
   1359   if (!EFI_ERROR (Status)) {
   1360     *TPMDeactivatedFlag = VolatileFlags.deactivated;
   1361   }
   1362 
   1363   return Status;
   1364 }
   1365 
   1366 /**
   1367   The driver's entry point.
   1368 
   1369   It publishes EFI TCG Protocol.
   1370 
   1371   @param[in] ImageHandle  The firmware allocated handle for the EFI image.
   1372   @param[in] SystemTable  A pointer to the EFI System Table.
   1373 
   1374   @retval EFI_SUCCESS     The entry point is executed successfully.
   1375   @retval other           Some error occurs when executing this entry point.
   1376 
   1377 **/
   1378 EFI_STATUS
   1379 EFIAPI
   1380 DriverEntry (
   1381   IN    EFI_HANDLE                  ImageHandle,
   1382   IN    EFI_SYSTEM_TABLE            *SystemTable
   1383   )
   1384 {
   1385   EFI_STATUS                        Status;
   1386   EFI_EVENT                         Event;
   1387   VOID                              *Registration;
   1388 
   1389   if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
   1390     DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));
   1391     return EFI_UNSUPPORTED;
   1392   }
   1393 
   1394   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
   1395     DEBUG ((EFI_D_ERROR, "TPM error!\n"));
   1396     return EFI_DEVICE_ERROR;
   1397   }
   1398 
   1399   Status = Tpm12RequestUseTpm ();
   1400   if (EFI_ERROR (Status)) {
   1401     DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));
   1402     return Status;
   1403   }
   1404 
   1405   Status = GetTpmStatus (&mTcgDxeData.BsCap.TPMDeactivatedFlag);
   1406   if (EFI_ERROR (Status)) {
   1407     DEBUG ((
   1408       EFI_D_ERROR,
   1409       "Line %d in file " __FILE__ ":\n    "
   1410       "DriverEntry: TPM not working properly\n",
   1411       __LINE__
   1412       ));
   1413     return Status;
   1414   }
   1415 
   1416   Status = gBS->InstallProtocolInterface (
   1417                   &ImageHandle,
   1418                   &gEfiTcgProtocolGuid,
   1419                   EFI_NATIVE_INTERFACE,
   1420                   &mTcgDxeData.TcgProtocol
   1421                   );
   1422   if (!EFI_ERROR (Status) && (!mTcgDxeData.BsCap.TPMDeactivatedFlag) && mTcgDxeData.BsCap.TPMPresentFlag) {
   1423     //
   1424     // Setup the log area and copy event log from hob list to it
   1425     //
   1426     Status = SetupEventLog ();
   1427     ASSERT_EFI_ERROR (Status);
   1428 
   1429     //
   1430     // Measure handoff tables, Boot#### variables etc.
   1431     //
   1432     Status = EfiCreateEventReadyToBootEx (
   1433                TPL_CALLBACK,
   1434                OnReadyToBoot,
   1435                NULL,
   1436                &Event
   1437                );
   1438 
   1439     Status = gBS->CreateEventEx (
   1440                     EVT_NOTIFY_SIGNAL,
   1441                     TPL_NOTIFY,
   1442                     OnExitBootServices,
   1443                     NULL,
   1444                     &gEfiEventExitBootServicesGuid,
   1445                     &Event
   1446                     );
   1447 
   1448     //
   1449     // Measure Exit Boot Service failed
   1450     //
   1451     Status = gBS->CreateEventEx (
   1452                     EVT_NOTIFY_SIGNAL,
   1453                     TPL_NOTIFY,
   1454                     OnExitBootServicesFailed,
   1455                     NULL,
   1456                     &gEventExitBootServicesFailedGuid,
   1457                     &Event
   1458                     );
   1459   }
   1460 
   1461   //
   1462   // Install ACPI Table
   1463   //
   1464   EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);
   1465 
   1466   return Status;
   1467 }
   1468