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