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
GetProcessorsCpuLocation(OUT EFI_CPU_PHYSICAL_LOCATION ** LocationBuf,OUT UINTN * Num)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
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)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
TpmCommHashAll(IN CONST UINT8 * Data,IN UINTN DataLen,OUT TPM_DIGEST * Digest)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
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)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
TpmCommLogEvent(IN OUT UINT8 ** EventLogPtr,IN OUT UINTN * LogSize,IN UINTN MaxSize,IN TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)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
TcgDxeLogEventI(IN TCG_DXE_DATA * TcgData,IN TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)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
TcgDxeLogEvent(IN EFI_TCG_PROTOCOL * This,IN TCG_PCR_EVENT * TCGLogData,IN OUT UINT32 * EventNumber,IN UINT32 Flags)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
TcgDxePassThroughToTpm(IN EFI_TCG_PROTOCOL * This,IN UINT32 TpmInputParameterBlockSize,IN UINT8 * TpmInputParameterBlock,IN UINT32 TpmOutputParameterBlockSize,IN UINT8 * TpmOutputParameterBlock)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
TcgDxeHashLogExtendEventI(IN TCG_DXE_DATA * TcgData,IN UINT8 * HashData,IN UINT64 HashDataLen,IN OUT TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)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
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)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
SetupEventLog(VOID)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
TcgMeasureAction(IN CHAR8 * String)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
MeasureHandoffTables(VOID)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
MeasureSeparatorEvent(IN TPM_PCRINDEX PCRIndex)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
ReadVariable(IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,OUT UINTN * VarSize)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
MeasureVariable(IN TPM_PCRINDEX PCRIndex,IN TCG_EVENTTYPE EventType,IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,IN VOID * VarData,IN UINTN VarSize)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
ReadAndMeasureBootVariable(IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,OUT UINTN * VarSize,OUT VOID ** VarData)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
MeasureAllBootVariables(VOID)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
OnReadyToBoot(IN EFI_EVENT Event,IN VOID * Context)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
InstallAcpiTable(IN EFI_EVENT Event,IN VOID * Context)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
OnExitBootServices(IN EFI_EVENT Event,IN VOID * Context)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
OnExitBootServicesFailed(IN EFI_EVENT Event,IN VOID * Context)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
GetTpmStatus(OUT BOOLEAN * TPMDeactivatedFlag)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
DriverEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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