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