1 /** @file
2   This module implements TrEE Protocol.
3 
4 Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include <PiDxe.h>
16 #include <IndustryStandard/Acpi.h>
17 #include <IndustryStandard/PeImage.h>
18 #include <IndustryStandard/TcpaAcpi.h>
19 
20 #include <Guid/GlobalVariable.h>
21 #include <Guid/HobList.h>
22 #include <Guid/TcgEventHob.h>
23 #include <Guid/EventGroup.h>
24 #include <Guid/EventExitBootServiceFailed.h>
25 #include <Guid/ImageAuthentication.h>
26 #include <Guid/TpmInstance.h>
27 
28 #include <Protocol/DevicePath.h>
29 #include <Protocol/AcpiTable.h>
30 #include <Protocol/MpService.h>
31 #include <Protocol/VariableWrite.h>
32 #include <Protocol/TrEEProtocol.h>
33 
34 #include <Library/DebugLib.h>
35 #include <Library/BaseMemoryLib.h>
36 #include <Library/UefiRuntimeServicesTableLib.h>
37 #include <Library/UefiDriverEntryPoint.h>
38 #include <Library/HobLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
40 #include <Library/BaseLib.h>
41 #include <Library/MemoryAllocationLib.h>
42 #include <Library/PrintLib.h>
43 #include <Library/Tpm2CommandLib.h>
44 #include <Library/PcdLib.h>
45 #include <Library/UefiLib.h>
46 #include <Library/Tpm2DeviceLib.h>
47 #include <Library/HashLib.h>
48 #include <Library/PerformanceLib.h>
49 #include <Library/ReportStatusCodeLib.h>
50 
51 #define PERF_ID_TREE_DXE  0x3120
52 
53 typedef struct {
54   CHAR16                                 *VariableName;
55   EFI_GUID                               *VendorGuid;
56 } VARIABLE_TYPE;
57 
58 #define  TREE_DEFAULT_MAX_COMMAND_SIZE        0x1000
59 #define  TREE_DEFAULT_MAX_RESPONSE_SIZE       0x1000
60 
61 typedef struct {
62   EFI_GUID               *EventGuid;
63   TREE_EVENT_LOG_FORMAT  LogFormat;
64 } TREE_EVENT_INFO_STRUCT;
65 
66 TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {
67   {&gTcgEventEntryHobGuid,             TREE_EVENT_LOG_FORMAT_TCG_1_2},
68 };
69 
70 #define TCG_EVENT_LOG_AREA_COUNT_MAX   2
71 
72 typedef struct {
73   TREE_EVENT_LOG_FORMAT             EventLogFormat;
74   EFI_PHYSICAL_ADDRESS              Lasa;
75   UINT64                            Laml;
76   UINTN                             EventLogSize;
77   UINT8                             *LastEvent;
78   BOOLEAN                           EventLogStarted;
79   BOOLEAN                           EventLogTruncated;
80 } TCG_EVENT_LOG_AREA_STRUCT;
81 
82 typedef struct _TCG_DXE_DATA {
83   TREE_BOOT_SERVICE_CAPABILITY      BsCap;
84   EFI_TCG_CLIENT_ACPI_TABLE         *TcgClientAcpiTable;
85   EFI_TCG_SERVER_ACPI_TABLE         *TcgServerAcpiTable;
86   TCG_EVENT_LOG_AREA_STRUCT         EventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX];
87 } TCG_DXE_DATA;
88 
89 EFI_TCG_CLIENT_ACPI_TABLE           mTcgClientAcpiTemplate = {
90   {
91     EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
92     sizeof (mTcgClientAcpiTemplate),
93     0x02                      //Revision
94     //
95     // Compiler initializes the remaining bytes to 0
96     // These fields should be filled in in production
97     //
98   },
99   0,                          // 0 for PC Client Platform Class
100   0,                          // Log Area Max Length
101   (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1)  // Log Area Start Address
102 };
103 
104 //
105 // The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
106 // the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,
107 // this _UID can be changed and should match with the _UID setting of the TPM
108 // ACPI device object
109 //
110 EFI_TCG_SERVER_ACPI_TABLE           mTcgServerAcpiTemplate = {
111   {
112     EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,
113     sizeof (mTcgServerAcpiTemplate),
114     0x02                      //Revision
115     //
116     // Compiler initializes the remaining bytes to 0
117     // These fields should be filled in in production
118     //
119   },
120   1,                          // 1 for Server Platform Class
121   0,                          // Reserved
122   0,                          // Log Area Max Length
123   (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address
124   0x0100,                     // TCG Specification revision 1.0
125   2,                          // Device Flags
126   0,                          // Interrupt Flags
127   0,                          // GPE
128   {0},                        // Reserved 3 bytes
129   0,                          // Global System Interrupt
130   {
131     EFI_ACPI_3_0_SYSTEM_MEMORY,
132     0,
133     0,
134     EFI_ACPI_3_0_BYTE,
135     0x0          // Base Address
136   },
137   0,                          // Reserved
138   {0},                        // Configuration Address
139   0xFF,                       // ACPI _UID value of the device, can be changed for different platforms
140   0,                          // ACPI _UID value of the device, can be changed for different platforms
141   0,                          // ACPI _UID value of the device, can be changed for different platforms
142   0                           // ACPI _UID value of the device, can be changed for different platforms
143 };
144 
145 TCG_DXE_DATA                 mTcgDxeData = {
146   {
147     sizeof (TREE_BOOT_SERVICE_CAPABILITY_1_0),     // Size
148     { 1, 0 },                       // StructureVersion
149     { 1, 0 },                       // ProtocolVersion
150     TREE_BOOT_HASH_ALG_SHA1,        // HashAlgorithmBitmap
151     TREE_EVENT_LOG_FORMAT_TCG_1_2,  // SupportedEventLogs
152     TRUE,                           // TrEEPresentFlag
153     TREE_DEFAULT_MAX_COMMAND_SIZE,  // MaxCommandSize
154     TREE_DEFAULT_MAX_RESPONSE_SIZE, // MaxResponseSize
155     0                               // ManufacturerID
156   },
157   &mTcgClientAcpiTemplate,
158   &mTcgServerAcpiTemplate,
159 };
160 
161 UINTN  mBootAttempts  = 0;
162 CHAR16 mBootVarName[] = L"BootOrder";
163 
164 VARIABLE_TYPE  mVariableType[] = {
165   {EFI_SECURE_BOOT_MODE_NAME,    &gEfiGlobalVariableGuid},
166   {EFI_PLATFORM_KEY_NAME,        &gEfiGlobalVariableGuid},
167   {EFI_KEY_EXCHANGE_KEY_NAME,    &gEfiGlobalVariableGuid},
168   {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},
169   {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},
170 };
171 
172 EFI_HANDLE mImageHandle;
173 
174 /**
175   Measure PE image into TPM log based on the authenticode image hashing in
176   PE/COFF Specification 8.0 Appendix A.
177 
178   Caution: This function may receive untrusted input.
179   PE/COFF image is external input, so this function will validate its data structure
180   within this image buffer before use.
181 
182   Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().
183 
184   @param[in]  PCRIndex       TPM PCR index
185   @param[in]  ImageAddress   Start address of image buffer.
186   @param[in]  ImageSize      Image size
187   @param[out] DigestList     Digeest list of this image.
188 
189   @retval EFI_SUCCESS            Successfully measure image.
190   @retval EFI_OUT_OF_RESOURCES   No enough resource to measure image.
191   @retval other error value
192 **/
193 EFI_STATUS
194 MeasurePeImageAndExtend (
195   IN  UINT32                    PCRIndex,
196   IN  EFI_PHYSICAL_ADDRESS      ImageAddress,
197   IN  UINTN                     ImageSize,
198   OUT TPML_DIGEST_VALUES        *DigestList
199   );
200 
201 /**
202 
203   This function dump raw data.
204 
205   @param  Data  raw data
206   @param  Size  raw data size
207 
208 **/
209 VOID
InternalDumpData(IN UINT8 * Data,IN UINTN Size)210 InternalDumpData (
211   IN UINT8  *Data,
212   IN UINTN  Size
213   )
214 {
215   UINTN  Index;
216   for (Index = 0; Index < Size; Index++) {
217     DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index]));
218   }
219 }
220 
221 /**
222 
223   This function dump raw data with colume format.
224 
225   @param  Data  raw data
226   @param  Size  raw data size
227 
228 **/
229 VOID
InternalDumpHex(IN UINT8 * Data,IN UINTN Size)230 InternalDumpHex (
231   IN UINT8  *Data,
232   IN UINTN  Size
233   )
234 {
235   UINTN   Index;
236   UINTN   Count;
237   UINTN   Left;
238 
239 #define COLUME_SIZE  (16 * 2)
240 
241   Count = Size / COLUME_SIZE;
242   Left  = Size % COLUME_SIZE;
243   for (Index = 0; Index < Count; Index++) {
244     DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));
245     InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
246     DEBUG ((EFI_D_INFO, "\n"));
247   }
248 
249   if (Left != 0) {
250     DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));
251     InternalDumpData (Data + Index * COLUME_SIZE, Left);
252     DEBUG ((EFI_D_INFO, "\n"));
253   }
254 }
255 
256 /**
257   Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
258   Caller is responsible to free LocationBuf.
259 
260   @param[out] LocationBuf          Returns Processor Location Buffer.
261   @param[out] Num                  Returns processor number.
262 
263   @retval EFI_SUCCESS              Operation completed successfully.
264   @retval EFI_UNSUPPORTED       MpService protocol not found.
265 
266 **/
267 EFI_STATUS
GetProcessorsCpuLocation(OUT EFI_CPU_PHYSICAL_LOCATION ** LocationBuf,OUT UINTN * Num)268 GetProcessorsCpuLocation (
269     OUT  EFI_CPU_PHYSICAL_LOCATION   **LocationBuf,
270     OUT  UINTN                       *Num
271   )
272 {
273   EFI_STATUS                        Status;
274   EFI_MP_SERVICES_PROTOCOL          *MpProtocol;
275   UINTN                             ProcessorNum;
276   UINTN                             EnabledProcessorNum;
277   EFI_PROCESSOR_INFORMATION         ProcessorInfo;
278   EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;
279   UINTN                             Index;
280 
281   Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);
282   if (EFI_ERROR (Status)) {
283     //
284     // MP protocol is not installed
285     //
286     return EFI_UNSUPPORTED;
287   }
288 
289   Status = MpProtocol->GetNumberOfProcessors(
290                          MpProtocol,
291                          &ProcessorNum,
292                          &EnabledProcessorNum
293                          );
294   if (EFI_ERROR(Status)){
295     return Status;
296   }
297 
298   Status = gBS->AllocatePool(
299                   EfiBootServicesData,
300                   sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,
301                   (VOID **) &ProcessorLocBuf
302                   );
303   if (EFI_ERROR(Status)){
304     return Status;
305   }
306 
307   //
308   // Get each processor Location info
309   //
310   for (Index = 0; Index < ProcessorNum; Index++) {
311     Status = MpProtocol->GetProcessorInfo(
312                            MpProtocol,
313                            Index,
314                            &ProcessorInfo
315                            );
316     if (EFI_ERROR(Status)){
317       FreePool(ProcessorLocBuf);
318       return Status;
319     }
320 
321     //
322     // Get all Processor Location info & measure
323     //
324     CopyMem(
325       &ProcessorLocBuf[Index],
326       &ProcessorInfo.Location,
327       sizeof(EFI_CPU_PHYSICAL_LOCATION)
328       );
329   }
330 
331   *LocationBuf = ProcessorLocBuf;
332   *Num = ProcessorNum;
333 
334   return Status;
335 }
336 
337 /**
338   The EFI_TREE_PROTOCOL GetCapability function call provides protocol
339   capability information and state information about the TrEE.
340 
341   @param[in]      This               Indicates the calling context
342   @param[in, out] ProtocolCapability The caller allocates memory for a TREE_BOOT_SERVICE_CAPABILITY
343                                      structure and sets the size field to the size of the structure allocated.
344                                      The callee fills in the fields with the EFI protocol capability information
345                                      and the current TrEE state information up to the number of fields which
346                                      fit within the size of the structure passed in.
347 
348   @retval EFI_SUCCESS            Operation completed successfully.
349   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
350                                  The ProtocolCapability variable will not be populated.
351   @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect.
352                                  The ProtocolCapability variable will not be populated.
353   @retval EFI_BUFFER_TOO_SMALL   The ProtocolCapability variable is too small to hold the full response.
354                                  It will be partially populated (required Size field will be set).
355 **/
356 EFI_STATUS
357 EFIAPI
TreeGetCapability(IN EFI_TREE_PROTOCOL * This,IN OUT TREE_BOOT_SERVICE_CAPABILITY * ProtocolCapability)358 TreeGetCapability (
359   IN EFI_TREE_PROTOCOL                *This,
360   IN OUT TREE_BOOT_SERVICE_CAPABILITY *ProtocolCapability
361   )
362 {
363   DEBUG ((EFI_D_INFO, "TreeGetCapability ...\n"));
364 
365   if ((This == NULL) || (ProtocolCapability == NULL)) {
366     return EFI_INVALID_PARAMETER;
367   }
368 
369   if (ProtocolCapability->Size < mTcgDxeData.BsCap.Size) {
370     ProtocolCapability->Size = mTcgDxeData.BsCap.Size;
371     return EFI_BUFFER_TOO_SMALL;
372   }
373 
374   CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, mTcgDxeData.BsCap.Size);
375   DEBUG ((EFI_D_INFO, "TreeGetCapability - %r\n", EFI_SUCCESS));
376   return EFI_SUCCESS;
377 }
378 
379 /**
380   This function dump event log.
381 
382   @param[in]  EventLogFormat     The type of the event log for which the information is requested.
383   @param[in]  EventLogLocation   A pointer to the memory address of the event log.
384   @param[in]  EventLogLastEntry  If the Event Log contains more than one entry, this is a pointer to the
385                                  address of the start of the last entry in the event log in memory.
386 **/
387 VOID
DumpEventLog(IN TREE_EVENT_LOG_FORMAT EventLogFormat,IN EFI_PHYSICAL_ADDRESS EventLogLocation,IN EFI_PHYSICAL_ADDRESS EventLogLastEntry)388 DumpEventLog (
389   IN TREE_EVENT_LOG_FORMAT EventLogFormat,
390   IN EFI_PHYSICAL_ADDRESS  EventLogLocation,
391   IN EFI_PHYSICAL_ADDRESS  EventLogLastEntry
392   )
393 {
394   TCG_PCR_EVENT_HDR         *EventHdr;
395   UINTN                     Index;
396 
397   DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));
398 
399   switch (EventLogFormat) {
400   case TREE_EVENT_LOG_FORMAT_TCG_1_2:
401     EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;
402     while ((UINTN)EventHdr <= EventLogLastEntry) {
403       DEBUG ((EFI_D_INFO, "  Event:\n"));
404       DEBUG ((EFI_D_INFO, "    PCRIndex  - %d\n", EventHdr->PCRIndex));
405       DEBUG ((EFI_D_INFO, "    EventType - 0x%08x\n", EventHdr->EventType));
406       DEBUG ((EFI_D_INFO, "    Digest    - "));
407       for (Index = 0; Index < sizeof(TCG_DIGEST); Index++) {
408         DEBUG ((EFI_D_INFO, "%02x ", EventHdr->Digest.digest[Index]));
409       }
410       DEBUG ((EFI_D_INFO, "\n"));
411       DEBUG ((EFI_D_INFO, "    EventSize - 0x%08x\n", EventHdr->EventSize));
412       InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);
413       EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize);
414     }
415     break;
416   }
417 
418   return ;
419 }
420 
421 /**
422   The EFI_TREE_PROTOCOL Get Event Log function call allows a caller to
423   retrieve the address of a given event log and its last entry.
424 
425   @param[in]  This               Indicates the calling context
426   @param[in]  EventLogFormat     The type of the event log for which the information is requested.
427   @param[out] EventLogLocation   A pointer to the memory address of the event log.
428   @param[out] EventLogLastEntry  If the Event Log contains more than one entry, this is a pointer to the
429                                  address of the start of the last entry in the event log in memory.
430   @param[out] EventLogTruncated  If the Event Log is missing at least one entry because an event would
431                                  have exceeded the area allocated for events, this value is set to TRUE.
432                                  Otherwise, the value will be FALSE and the Event Log will be complete.
433 
434   @retval EFI_SUCCESS            Operation completed successfully.
435   @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect
436                                  (e.g. asking for an event log whose format is not supported).
437 **/
438 EFI_STATUS
439 EFIAPI
TreeGetEventLog(IN EFI_TREE_PROTOCOL * This,IN TREE_EVENT_LOG_FORMAT EventLogFormat,OUT EFI_PHYSICAL_ADDRESS * EventLogLocation,OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry,OUT BOOLEAN * EventLogTruncated)440 TreeGetEventLog (
441   IN EFI_TREE_PROTOCOL     *This,
442   IN TREE_EVENT_LOG_FORMAT EventLogFormat,
443   OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,
444   OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,
445   OUT BOOLEAN              *EventLogTruncated
446   )
447 {
448   UINTN  Index;
449 
450   DEBUG ((EFI_D_INFO, "TreeGetEventLog ...\n"));
451 
452   if (This == NULL) {
453     return EFI_INVALID_PARAMETER;
454   }
455 
456   for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
457     if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {
458       break;
459     }
460   }
461 
462   if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {
463     return EFI_INVALID_PARAMETER;
464   }
465 
466   if (!mTcgDxeData.BsCap.TrEEPresentFlag) {
467     if (EventLogLocation != NULL) {
468       *EventLogLocation = 0;
469     }
470     if (EventLogLastEntry != NULL) {
471       *EventLogLastEntry = 0;
472     }
473     if (EventLogTruncated != NULL) {
474       *EventLogTruncated = FALSE;
475     }
476     return EFI_SUCCESS;
477   }
478 
479   if (EventLogLocation != NULL) {
480     *EventLogLocation = mTcgDxeData.EventLogAreaStruct[Index].Lasa;
481     DEBUG ((EFI_D_INFO, "TreeGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));
482   }
483 
484   if (EventLogLastEntry != NULL) {
485     if (!mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted) {
486       *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;
487     } else {
488       *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].LastEvent;
489     }
490     DEBUG ((EFI_D_INFO, "TreeGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));
491   }
492 
493   if (EventLogTruncated != NULL) {
494     *EventLogTruncated = mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated;
495     DEBUG ((EFI_D_INFO, "TreeGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));
496   }
497 
498   DEBUG ((EFI_D_INFO, "TreeGetEventLog - %r\n", EFI_SUCCESS));
499 
500   // Dump Event Log for debug purpose
501   if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {
502     DumpEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry);
503   }
504 
505   return EFI_SUCCESS;
506 }
507 
508 /**
509   Add a new entry to the Event Log.
510 
511   @param[in, out] EventLogPtr     Pointer to the Event Log data.
512   @param[in, out] LogSize         Size of the Event Log.
513   @param[in]      MaxSize         Maximum size of the Event Log.
514   @param[in]      NewEventHdr     Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.
515   @param[in]      NewEventHdrSize New event header size.
516   @param[in]      NewEventData    Pointer to the new event data.
517   @param[in]      NewEventSize    New event data size.
518 
519   @retval EFI_SUCCESS           The new event log entry was added.
520   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
521 
522 **/
523 EFI_STATUS
TcgCommLogEvent(IN OUT UINT8 ** EventLogPtr,IN OUT UINTN * LogSize,IN UINTN MaxSize,IN VOID * NewEventHdr,IN UINT32 NewEventHdrSize,IN UINT8 * NewEventData,IN UINT32 NewEventSize)524 TcgCommLogEvent (
525   IN OUT  UINT8                     **EventLogPtr,
526   IN OUT  UINTN                     *LogSize,
527   IN      UINTN                     MaxSize,
528   IN      VOID                      *NewEventHdr,
529   IN      UINT32                    NewEventHdrSize,
530   IN      UINT8                     *NewEventData,
531   IN      UINT32                    NewEventSize
532   )
533 {
534   UINTN                            NewLogSize;
535 
536   if (NewEventSize > MAX_ADDRESS -  NewEventHdrSize) {
537     return EFI_OUT_OF_RESOURCES;
538   }
539 
540   NewLogSize = NewEventHdrSize + NewEventSize;
541 
542   if (NewLogSize > MAX_ADDRESS -  *LogSize) {
543     return EFI_OUT_OF_RESOURCES;
544   }
545 
546   if (NewLogSize + *LogSize > MaxSize) {
547     DEBUG ((EFI_D_INFO, "  MaxSize    - 0x%x\n", MaxSize));
548     DEBUG ((EFI_D_INFO, "  NewLogSize - 0x%x\n", NewLogSize));
549     DEBUG ((EFI_D_INFO, "  LogSize    - 0x%x\n", *LogSize));
550     DEBUG ((EFI_D_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));
551     return EFI_OUT_OF_RESOURCES;
552   }
553 
554   *EventLogPtr += *LogSize;
555   *LogSize += NewLogSize;
556   CopyMem (*EventLogPtr, NewEventHdr, NewEventHdrSize);
557   CopyMem (
558     *EventLogPtr + NewEventHdrSize,
559     NewEventData,
560     NewEventSize
561     );
562   return EFI_SUCCESS;
563 }
564 
565 /**
566   Add a new entry to the Event Log.
567 
568   @param[in] EventLogFormat  The type of the event log for which the information is requested.
569   @param[in] NewEventHdr     Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.
570   @param[in] NewEventHdrSize New event header size.
571   @param[in] NewEventData    Pointer to the new event data.
572   @param[in] NewEventSize    New event data size.
573 
574   @retval EFI_SUCCESS           The new event log entry was added.
575   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
576 
577 **/
578 EFI_STATUS
TcgDxeLogEvent(IN TREE_EVENT_LOG_FORMAT EventLogFormat,IN VOID * NewEventHdr,IN UINT32 NewEventHdrSize,IN UINT8 * NewEventData,IN UINT32 NewEventSize)579 TcgDxeLogEvent (
580   IN      TREE_EVENT_LOG_FORMAT     EventLogFormat,
581   IN      VOID                      *NewEventHdr,
582   IN      UINT32                    NewEventHdrSize,
583   IN      UINT8                     *NewEventData,
584   IN      UINT32                    NewEventSize
585   )
586 {
587   EFI_STATUS   Status;
588   UINTN        Index;
589 
590   for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
591     if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {
592       break;
593     }
594   }
595 
596   if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {
597     return EFI_INVALID_PARAMETER;
598   }
599 
600   if (mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated) {
601     return EFI_VOLUME_FULL;
602   }
603 
604   mTcgDxeData.EventLogAreaStruct[Index].LastEvent = (UINT8*)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].Lasa;
605   Status = TcgCommLogEvent (
606              &mTcgDxeData.EventLogAreaStruct[Index].LastEvent,
607              &mTcgDxeData.EventLogAreaStruct[Index].EventLogSize,
608              (UINTN)mTcgDxeData.EventLogAreaStruct[Index].Laml,
609              NewEventHdr,
610              NewEventHdrSize,
611              NewEventData,
612              NewEventSize
613              );
614 
615   if (Status == EFI_DEVICE_ERROR) {
616     return EFI_DEVICE_ERROR;
617   } else if (Status == EFI_OUT_OF_RESOURCES) {
618     mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated = TRUE;
619     return EFI_VOLUME_FULL;
620   } else if (Status == EFI_SUCCESS) {
621     mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted = TRUE;
622   }
623 
624   return Status;
625 }
626 
627 /**
628   Add a new entry to the Event Log.
629 
630   @param[in]     DigestList    A list of digest.
631   @param[in,out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
632   @param[in]     NewEventData  Pointer to the new event data.
633 
634   @retval EFI_SUCCESS           The new event log entry was added.
635   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
636 **/
637 EFI_STATUS
TcgDxeLogHashEvent(IN TPML_DIGEST_VALUES * DigestList,IN OUT TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)638 TcgDxeLogHashEvent (
639   IN TPML_DIGEST_VALUES             *DigestList,
640   IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,
641   IN      UINT8                     *NewEventData
642   )
643 {
644   EFI_STATUS                        Status;
645   EFI_TPL                           OldTpl;
646   UINTN                             Index;
647   EFI_STATUS                        RetStatus;
648 
649   RetStatus = EFI_SUCCESS;
650   for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
651       DEBUG ((EFI_D_INFO, "  LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));
652       switch (mTreeEventInfo[Index].LogFormat) {
653       case TREE_EVENT_LOG_FORMAT_TCG_1_2:
654         Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
655         if (!EFI_ERROR (Status)) {
656           //
657           // Enter critical region
658           //
659           OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
660           Status = TcgDxeLogEvent (
661                      mTreeEventInfo[Index].LogFormat,
662                      NewEventHdr,
663                      sizeof(TCG_PCR_EVENT_HDR),
664                      NewEventData,
665                      NewEventHdr->EventSize
666                      );
667           if (Status != EFI_SUCCESS) {
668             RetStatus = Status;
669           }
670           gBS->RestoreTPL (OldTpl);
671           //
672           // Exit critical region
673           //
674         }
675         break;
676       }
677   }
678 
679   return RetStatus;
680 }
681 
682 /**
683   Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
684   and add an entry to the Event Log.
685 
686   @param[in]      Flags         Bitmap providing additional information.
687   @param[in]      HashData      Physical address of the start of the data buffer
688                                 to be hashed, extended, and logged.
689   @param[in]      HashDataLen   The length, in bytes, of the buffer referenced by HashData
690   @param[in, out] NewEventHdr   Pointer to a TCG_PCR_EVENT_HDR data structure.
691   @param[in]      NewEventData  Pointer to the new event data.
692 
693   @retval EFI_SUCCESS           Operation completed successfully.
694   @retval EFI_OUT_OF_RESOURCES  No enough memory to log the new event.
695   @retval EFI_DEVICE_ERROR      The command was unsuccessful.
696 
697 **/
698 EFI_STATUS
TcgDxeHashLogExtendEvent(IN UINT64 Flags,IN UINT8 * HashData,IN UINT64 HashDataLen,IN OUT TCG_PCR_EVENT_HDR * NewEventHdr,IN UINT8 * NewEventData)699 TcgDxeHashLogExtendEvent (
700   IN      UINT64                    Flags,
701   IN      UINT8                     *HashData,
702   IN      UINT64                    HashDataLen,
703   IN OUT  TCG_PCR_EVENT_HDR         *NewEventHdr,
704   IN      UINT8                     *NewEventData
705   )
706 {
707   EFI_STATUS                        Status;
708   TPML_DIGEST_VALUES                DigestList;
709 
710   if (!mTcgDxeData.BsCap.TrEEPresentFlag) {
711     return EFI_DEVICE_ERROR;
712   }
713 
714   Status = HashAndExtend (
715              NewEventHdr->PCRIndex,
716              HashData,
717              (UINTN)HashDataLen,
718              &DigestList
719              );
720   if (!EFI_ERROR (Status)) {
721     if ((Flags & TREE_EXTEND_ONLY) == 0) {
722       Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);
723     }
724   }
725 
726   if (Status == EFI_DEVICE_ERROR) {
727     DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEvent - %r. Disable TPM.\n", Status));
728     mTcgDxeData.BsCap.TrEEPresentFlag = FALSE;
729     REPORT_STATUS_CODE (
730       EFI_ERROR_CODE | EFI_ERROR_MINOR,
731       (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
732       );
733   }
734 
735   return Status;
736 }
737 
738 /**
739   The EFI_TREE_PROTOCOL HashLogExtendEvent function call provides callers with
740   an opportunity to extend and optionally log events without requiring
741   knowledge of actual TPM commands.
742   The extend operation will occur even if this function cannot create an event
743   log entry (e.g. due to the event log being full).
744 
745   @param[in]  This               Indicates the calling context
746   @param[in]  Flags              Bitmap providing additional information.
747   @param[in]  DataToHash         Physical address of the start of the data buffer to be hashed.
748   @param[in]  DataToHashLen      The length in bytes of the buffer referenced by DataToHash.
749   @param[in]  Event              Pointer to data buffer containing information about the event.
750 
751   @retval EFI_SUCCESS            Operation completed successfully.
752   @retval EFI_DEVICE_ERROR       The command was unsuccessful.
753   @retval EFI_VOLUME_FULL        The extend operation occurred, but the event could not be written to one or more event logs.
754   @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect.
755   @retval EFI_UNSUPPORTED        The PE/COFF image type is not supported.
756 **/
757 EFI_STATUS
758 EFIAPI
TreeHashLogExtendEvent(IN EFI_TREE_PROTOCOL * This,IN UINT64 Flags,IN EFI_PHYSICAL_ADDRESS DataToHash,IN UINT64 DataToHashLen,IN TrEE_EVENT * Event)759 TreeHashLogExtendEvent (
760   IN EFI_TREE_PROTOCOL    *This,
761   IN UINT64               Flags,
762   IN EFI_PHYSICAL_ADDRESS DataToHash,
763   IN UINT64               DataToHashLen,
764   IN TrEE_EVENT           *Event
765   )
766 {
767   EFI_STATUS         Status;
768   TCG_PCR_EVENT_HDR  NewEventHdr;
769   TPML_DIGEST_VALUES DigestList;
770 
771   DEBUG ((EFI_D_INFO, "TreeHashLogExtendEvent ...\n"));
772 
773   if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) {
774     return EFI_INVALID_PARAMETER;
775   }
776 
777   if (!mTcgDxeData.BsCap.TrEEPresentFlag) {
778     return EFI_UNSUPPORTED;
779   }
780 
781   if (Event->Size < Event->Header.HeaderSize + sizeof(UINT32)) {
782     return EFI_INVALID_PARAMETER;
783   }
784 
785   if (Event->Header.PCRIndex > MAX_PCR_INDEX) {
786     return EFI_INVALID_PARAMETER;
787   }
788 
789   NewEventHdr.PCRIndex  = Event->Header.PCRIndex;
790   NewEventHdr.EventType = Event->Header.EventType;
791   NewEventHdr.EventSize = Event->Size - sizeof(UINT32) - Event->Header.HeaderSize;
792   if ((Flags & PE_COFF_IMAGE) != 0) {
793     Status = MeasurePeImageAndExtend (
794                NewEventHdr.PCRIndex,
795                DataToHash,
796                (UINTN)DataToHashLen,
797                &DigestList
798                );
799     if (!EFI_ERROR (Status)) {
800       if ((Flags & TREE_EXTEND_ONLY) == 0) {
801         Status = TcgDxeLogHashEvent (&DigestList, &NewEventHdr, Event->Event);
802       }
803     }
804     if (Status == EFI_DEVICE_ERROR) {
805       DEBUG ((EFI_D_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status));
806       mTcgDxeData.BsCap.TrEEPresentFlag = FALSE;
807       REPORT_STATUS_CODE (
808         EFI_ERROR_CODE | EFI_ERROR_MINOR,
809         (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
810         );
811     }
812   } else {
813     Status = TcgDxeHashLogExtendEvent (
814                Flags,
815                (UINT8 *) (UINTN) DataToHash,
816                DataToHashLen,
817                &NewEventHdr,
818                Event->Event
819                );
820   }
821   DEBUG ((EFI_D_INFO, "TreeHashLogExtendEvent - %r\n", Status));
822   return Status;
823 }
824 
825 /**
826   This service enables the sending of commands to the TrEE.
827 
828   @param[in]  This                     Indicates the calling context
829   @param[in]  InputParameterBlockSize  Size of the TrEE input parameter block.
830   @param[in]  InputParameterBlock      Pointer to the TrEE input parameter block.
831   @param[in]  OutputParameterBlockSize Size of the TrEE output parameter block.
832   @param[in]  OutputParameterBlock     Pointer to the TrEE output parameter block.
833 
834   @retval EFI_SUCCESS            The command byte stream was successfully sent to the device and a response was successfully received.
835   @retval EFI_DEVICE_ERROR       The command was not successfully sent to the device or a response was not successfully received from the device.
836   @retval EFI_INVALID_PARAMETER  One or more of the parameters are incorrect.
837   @retval EFI_BUFFER_TOO_SMALL   The output parameter block is too small.
838 **/
839 EFI_STATUS
840 EFIAPI
TreeSubmitCommand(IN EFI_TREE_PROTOCOL * This,IN UINT32 InputParameterBlockSize,IN UINT8 * InputParameterBlock,IN UINT32 OutputParameterBlockSize,IN UINT8 * OutputParameterBlock)841 TreeSubmitCommand (
842   IN EFI_TREE_PROTOCOL *This,
843   IN UINT32            InputParameterBlockSize,
844   IN UINT8             *InputParameterBlock,
845   IN UINT32            OutputParameterBlockSize,
846   IN UINT8             *OutputParameterBlock
847   )
848 {
849   EFI_STATUS    Status;
850 
851   DEBUG ((EFI_D_INFO, "TreeSubmitCommand ...\n"));
852 
853   if ((This == NULL) ||
854       (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) ||
855       (OutputParameterBlockSize == 0) || (OutputParameterBlock == NULL)) {
856     return EFI_INVALID_PARAMETER;
857   }
858 
859   if (!mTcgDxeData.BsCap.TrEEPresentFlag) {
860     return EFI_UNSUPPORTED;
861   }
862 
863   if (InputParameterBlockSize > mTcgDxeData.BsCap.MaxCommandSize) {
864     return EFI_INVALID_PARAMETER;
865   }
866   if (OutputParameterBlockSize > mTcgDxeData.BsCap.MaxResponseSize) {
867     return EFI_INVALID_PARAMETER;
868   }
869 
870   Status = Tpm2SubmitCommand (
871              InputParameterBlockSize,
872              InputParameterBlock,
873              &OutputParameterBlockSize,
874              OutputParameterBlock
875              );
876   DEBUG ((EFI_D_INFO, "TreeSubmitCommand - %r\n", Status));
877   return Status;
878 }
879 
880 
881 EFI_TREE_PROTOCOL mTreeProtocol = {
882     TreeGetCapability,
883     TreeGetEventLog,
884     TreeHashLogExtendEvent,
885     TreeSubmitCommand
886 };
887 
888 /**
889   Initialize the Event Log and log events passed from the PEI phase.
890 
891   @retval EFI_SUCCESS           Operation completed successfully.
892   @retval EFI_OUT_OF_RESOURCES  Out of memory.
893 
894 **/
895 EFI_STATUS
SetupEventLog(VOID)896 SetupEventLog (
897   VOID
898   )
899 {
900   EFI_STATUS              Status;
901   VOID                    *TcgEvent;
902   EFI_PEI_HOB_POINTERS    GuidHob;
903   EFI_PHYSICAL_ADDRESS    Lasa;
904   UINTN                   Index;
905 
906   DEBUG ((EFI_D_INFO, "SetupEventLog\n"));
907 
908   //
909   // 1. Create Log Area
910   //
911   for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
912       mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTreeEventInfo[Index].LogFormat;
913       Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);
914       Status = gBS->AllocatePages (
915                       AllocateMaxAddress,
916                       EfiACPIMemoryNVS,
917                       EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),
918                       &Lasa
919                       );
920       if (EFI_ERROR (Status)) {
921         return Status;
922       }
923       mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa;
924       mTcgDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen);
925       //
926       // To initialize them as 0xFF is recommended
927       // because the OS can know the last entry for that.
928       //
929       SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);
930   }
931 
932   //
933   // 2. Create ACPI table for TCG1.2 only
934   //
935     if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
936       mTcgClientAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;
937       mTcgClientAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);
938     } else {
939       mTcgServerAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;
940       mTcgServerAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);
941     }
942 
943   //
944   // 3. Sync data from PEI to DXE
945   //
946   Status = EFI_SUCCESS;
947   for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {
948       GuidHob.Raw = GetHobList ();
949       Status = EFI_SUCCESS;
950       while (!EFI_ERROR (Status) &&
951              (GuidHob.Raw = GetNextGuidHob (mTreeEventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) {
952         TcgEvent    = GET_GUID_HOB_DATA (GuidHob.Guid);
953         GuidHob.Raw = GET_NEXT_HOB (GuidHob);
954         switch (mTreeEventInfo[Index].LogFormat) {
955         case TREE_EVENT_LOG_FORMAT_TCG_1_2:
956           Status = TcgDxeLogEvent (
957                      mTreeEventInfo[Index].LogFormat,
958                      TcgEvent,
959                      sizeof(TCG_PCR_EVENT_HDR),
960                      ((TCG_PCR_EVENT*)TcgEvent)->Event,
961                      ((TCG_PCR_EVENT_HDR*)TcgEvent)->EventSize
962                      );
963           break;
964         }
965       }
966   }
967 
968   return Status;
969 }
970 
971 /**
972   Measure and log an action string, and extend the measurement result into PCR[5].
973 
974   @param[in] String           A specific string that indicates an Action event.
975 
976   @retval EFI_SUCCESS         Operation completed successfully.
977   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
978 
979 **/
980 EFI_STATUS
TcgMeasureAction(IN CHAR8 * String)981 TcgMeasureAction (
982   IN      CHAR8                     *String
983   )
984 {
985   TCG_PCR_EVENT_HDR                 TcgEvent;
986 
987   TcgEvent.PCRIndex  = 5;
988   TcgEvent.EventType = EV_EFI_ACTION;
989   TcgEvent.EventSize = (UINT32)AsciiStrLen (String);
990   return TcgDxeHashLogExtendEvent (
991            0,
992            (UINT8*)String,
993            TcgEvent.EventSize,
994            &TcgEvent,
995            (UINT8 *) String
996            );
997 }
998 
999 /**
1000   Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
1001 
1002   @retval EFI_SUCCESS         Operation completed successfully.
1003   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
1004 
1005 **/
1006 EFI_STATUS
MeasureHandoffTables(VOID)1007 MeasureHandoffTables (
1008   VOID
1009   )
1010 {
1011   EFI_STATUS                        Status;
1012   TCG_PCR_EVENT_HDR                 TcgEvent;
1013   EFI_HANDOFF_TABLE_POINTERS        HandoffTables;
1014   UINTN                             ProcessorNum;
1015   EFI_CPU_PHYSICAL_LOCATION         *ProcessorLocBuf;
1016 
1017   ProcessorLocBuf = NULL;
1018   Status = EFI_SUCCESS;
1019 
1020   if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {
1021     //
1022     // Tcg Server spec.
1023     // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
1024     //
1025     Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);
1026 
1027     if (!EFI_ERROR(Status)){
1028       TcgEvent.PCRIndex  = 1;
1029       TcgEvent.EventType = EV_TABLE_OF_DEVICES;
1030       TcgEvent.EventSize = sizeof (HandoffTables);
1031 
1032       HandoffTables.NumberOfTables = 1;
1033       HandoffTables.TableEntry[0].VendorGuid  = gEfiMpServiceProtocolGuid;
1034       HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;
1035 
1036       Status = TcgDxeHashLogExtendEvent (
1037                  0,
1038                  (UINT8*)(UINTN)ProcessorLocBuf,
1039                  sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,
1040                  &TcgEvent,
1041                  (UINT8*)&HandoffTables
1042                  );
1043 
1044       FreePool(ProcessorLocBuf);
1045     }
1046   }
1047 
1048   return Status;
1049 }
1050 
1051 /**
1052   Measure and log Separator event, and extend the measurement result into a specific PCR.
1053 
1054   @param[in] PCRIndex         PCR index.
1055 
1056   @retval EFI_SUCCESS         Operation completed successfully.
1057   @retval EFI_DEVICE_ERROR    The operation was unsuccessful.
1058 
1059 **/
1060 EFI_STATUS
MeasureSeparatorEvent(IN TPM_PCRINDEX PCRIndex)1061 MeasureSeparatorEvent (
1062   IN      TPM_PCRINDEX              PCRIndex
1063   )
1064 {
1065   TCG_PCR_EVENT_HDR                 TcgEvent;
1066   UINT32                            EventData;
1067 
1068   DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex));
1069 
1070   EventData = 0;
1071   TcgEvent.PCRIndex  = PCRIndex;
1072   TcgEvent.EventType = EV_SEPARATOR;
1073   TcgEvent.EventSize = (UINT32)sizeof (EventData);
1074   return TcgDxeHashLogExtendEvent (
1075            0,
1076            (UINT8 *)&EventData,
1077            sizeof (EventData),
1078            &TcgEvent,
1079            (UINT8 *)&EventData
1080            );
1081 }
1082 
1083 /**
1084   Measure and log an EFI variable, and extend the measurement result into a specific PCR.
1085 
1086   @param[in]  PCRIndex          PCR Index.
1087   @param[in]  EventType         Event type.
1088   @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.
1089   @param[in]  VendorGuid        A unique identifier for the vendor.
1090   @param[in]  VarData           The content of the variable data.
1091   @param[in]  VarSize           The size of the variable data.
1092 
1093   @retval EFI_SUCCESS           Operation completed successfully.
1094   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1095   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1096 
1097 **/
1098 EFI_STATUS
MeasureVariable(IN TPM_PCRINDEX PCRIndex,IN TCG_EVENTTYPE EventType,IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,IN VOID * VarData,IN UINTN VarSize)1099 MeasureVariable (
1100   IN      TPM_PCRINDEX              PCRIndex,
1101   IN      TCG_EVENTTYPE             EventType,
1102   IN      CHAR16                    *VarName,
1103   IN      EFI_GUID                  *VendorGuid,
1104   IN      VOID                      *VarData,
1105   IN      UINTN                     VarSize
1106   )
1107 {
1108   EFI_STATUS                        Status;
1109   TCG_PCR_EVENT_HDR                 TcgEvent;
1110   UINTN                             VarNameLength;
1111   EFI_VARIABLE_DATA_TREE            *VarLog;
1112 
1113   DEBUG ((EFI_D_INFO, "TrEEDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType));
1114   DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
1115 
1116   VarNameLength      = StrLen (VarName);
1117   TcgEvent.PCRIndex  = PCRIndex;
1118   TcgEvent.EventType = EventType;
1119   TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
1120                         - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
1121 
1122   VarLog = (EFI_VARIABLE_DATA_TREE*)AllocatePool (TcgEvent.EventSize);
1123   if (VarLog == NULL) {
1124     return EFI_OUT_OF_RESOURCES;
1125   }
1126 
1127   VarLog->VariableName       = *VendorGuid;
1128   VarLog->UnicodeNameLength  = VarNameLength;
1129   VarLog->VariableDataLength = VarSize;
1130   CopyMem (
1131      VarLog->UnicodeName,
1132      VarName,
1133      VarNameLength * sizeof (*VarName)
1134      );
1135   if (VarSize != 0 && VarData != NULL) {
1136     CopyMem (
1137        (CHAR16 *)VarLog->UnicodeName + VarNameLength,
1138        VarData,
1139        VarSize
1140        );
1141   }
1142 
1143   Status = TcgDxeHashLogExtendEvent (
1144              0,
1145              (UINT8*)VarLog,
1146              TcgEvent.EventSize,
1147              &TcgEvent,
1148              (UINT8*)VarLog
1149              );
1150 
1151   FreePool (VarLog);
1152   return Status;
1153 }
1154 
1155 /**
1156   Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR.
1157 
1158   @param[in]  PCRIndex          PCR Index.
1159   @param[in]  EventType         Event type.
1160   @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.
1161   @param[in]   VendorGuid       A unique identifier for the vendor.
1162   @param[out]  VarSize          The size of the variable data.
1163   @param[out]  VarData          Pointer to the content of the variable.
1164 
1165   @retval EFI_SUCCESS           Operation completed successfully.
1166   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1167   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1168 
1169 **/
1170 EFI_STATUS
ReadAndMeasureVariable(IN TPM_PCRINDEX PCRIndex,IN TCG_EVENTTYPE EventType,IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,OUT UINTN * VarSize,OUT VOID ** VarData)1171 ReadAndMeasureVariable (
1172   IN      TPM_PCRINDEX              PCRIndex,
1173   IN      TCG_EVENTTYPE             EventType,
1174   IN      CHAR16                    *VarName,
1175   IN      EFI_GUID                  *VendorGuid,
1176   OUT     UINTN                     *VarSize,
1177   OUT     VOID                      **VarData
1178   )
1179 {
1180   EFI_STATUS                        Status;
1181 
1182   Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);
1183   if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {
1184     if (EFI_ERROR (Status)) {
1185       //
1186       // It is valid case, so we need handle it.
1187       //
1188       *VarData = NULL;
1189       *VarSize = 0;
1190     }
1191   } else {
1192     //
1193     // if status error, VarData is freed and set NULL by GetVariable2
1194     //
1195     if (EFI_ERROR (Status)) {
1196       return EFI_NOT_FOUND;
1197     }
1198   }
1199 
1200   Status = MeasureVariable (
1201              PCRIndex,
1202              EventType,
1203              VarName,
1204              VendorGuid,
1205              *VarData,
1206              *VarSize
1207              );
1208   return Status;
1209 }
1210 
1211 /**
1212   Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
1213 
1214   @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.
1215   @param[in]   VendorGuid       A unique identifier for the vendor.
1216   @param[out]  VarSize          The size of the variable data.
1217   @param[out]  VarData          Pointer to the content of the variable.
1218 
1219   @retval EFI_SUCCESS           Operation completed successfully.
1220   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1221   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1222 
1223 **/
1224 EFI_STATUS
ReadAndMeasureBootVariable(IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,OUT UINTN * VarSize,OUT VOID ** VarData)1225 ReadAndMeasureBootVariable (
1226   IN      CHAR16                    *VarName,
1227   IN      EFI_GUID                  *VendorGuid,
1228   OUT     UINTN                     *VarSize,
1229   OUT     VOID                      **VarData
1230   )
1231 {
1232   return ReadAndMeasureVariable (
1233            5,
1234            EV_EFI_VARIABLE_BOOT,
1235            VarName,
1236            VendorGuid,
1237            VarSize,
1238            VarData
1239            );
1240 }
1241 
1242 /**
1243   Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].
1244 
1245   @param[in]   VarName          A Null-terminated string that is the name of the vendor's variable.
1246   @param[in]   VendorGuid       A unique identifier for the vendor.
1247   @param[out]  VarSize          The size of the variable data.
1248   @param[out]  VarData          Pointer to the content of the variable.
1249 
1250   @retval EFI_SUCCESS           Operation completed successfully.
1251   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1252   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1253 
1254 **/
1255 EFI_STATUS
ReadAndMeasureSecureVariable(IN CHAR16 * VarName,IN EFI_GUID * VendorGuid,OUT UINTN * VarSize,OUT VOID ** VarData)1256 ReadAndMeasureSecureVariable (
1257   IN      CHAR16                    *VarName,
1258   IN      EFI_GUID                  *VendorGuid,
1259   OUT     UINTN                     *VarSize,
1260   OUT     VOID                      **VarData
1261   )
1262 {
1263   return ReadAndMeasureVariable (
1264            7,
1265            EV_EFI_VARIABLE_DRIVER_CONFIG,
1266            VarName,
1267            VendorGuid,
1268            VarSize,
1269            VarData
1270            );
1271 }
1272 
1273 /**
1274   Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
1275 
1276   The EFI boot variables are BootOrder and Boot#### variables.
1277 
1278   @retval EFI_SUCCESS           Operation completed successfully.
1279   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1280   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1281 
1282 **/
1283 EFI_STATUS
MeasureAllBootVariables(VOID)1284 MeasureAllBootVariables (
1285   VOID
1286   )
1287 {
1288   EFI_STATUS                        Status;
1289   UINT16                            *BootOrder;
1290   UINTN                             BootCount;
1291   UINTN                             Index;
1292   VOID                              *BootVarData;
1293   UINTN                             Size;
1294 
1295   Status = ReadAndMeasureBootVariable (
1296              mBootVarName,
1297              &gEfiGlobalVariableGuid,
1298              &BootCount,
1299              (VOID **) &BootOrder
1300              );
1301   if (Status == EFI_NOT_FOUND || BootOrder == NULL) {
1302     return EFI_SUCCESS;
1303   }
1304 
1305   if (EFI_ERROR (Status)) {
1306     //
1307     // BootOrder can't be NULL if status is not EFI_NOT_FOUND
1308     //
1309     FreePool (BootOrder);
1310     return Status;
1311   }
1312 
1313   BootCount /= sizeof (*BootOrder);
1314   for (Index = 0; Index < BootCount; Index++) {
1315     UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);
1316     Status = ReadAndMeasureBootVariable (
1317                mBootVarName,
1318                &gEfiGlobalVariableGuid,
1319                &Size,
1320                &BootVarData
1321                );
1322     if (!EFI_ERROR (Status)) {
1323       FreePool (BootVarData);
1324     }
1325   }
1326 
1327   FreePool (BootOrder);
1328   return EFI_SUCCESS;
1329 }
1330 
1331 /**
1332   Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.
1333 
1334   The EFI boot variables are BootOrder and Boot#### variables.
1335 
1336   @retval EFI_SUCCESS           Operation completed successfully.
1337   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1338   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1339 
1340 **/
1341 EFI_STATUS
MeasureAllSecureVariables(VOID)1342 MeasureAllSecureVariables (
1343   VOID
1344   )
1345 {
1346   EFI_STATUS                        Status;
1347   VOID                              *Data;
1348   UINTN                             DataSize;
1349   UINTN                             Index;
1350 
1351   Status = EFI_NOT_FOUND;
1352   for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {
1353     Status = ReadAndMeasureSecureVariable (
1354                mVariableType[Index].VariableName,
1355                mVariableType[Index].VendorGuid,
1356                &DataSize,
1357                &Data
1358                );
1359     if (!EFI_ERROR (Status)) {
1360       if (Data != NULL) {
1361         FreePool (Data);
1362       }
1363     }
1364   }
1365 
1366   return EFI_SUCCESS;
1367 }
1368 
1369 /**
1370   Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.
1371 
1372   @retval EFI_SUCCESS           Operation completed successfully.
1373   @retval EFI_OUT_OF_RESOURCES  Out of memory.
1374   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
1375 
1376 **/
1377 EFI_STATUS
MeasureLaunchOfFirmwareDebugger(VOID)1378 MeasureLaunchOfFirmwareDebugger (
1379   VOID
1380   )
1381 {
1382   TCG_PCR_EVENT_HDR                 TcgEvent;
1383 
1384   TcgEvent.PCRIndex  = 7;
1385   TcgEvent.EventType = EV_EFI_ACTION;
1386   TcgEvent.EventSize = sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1;
1387   return TcgDxeHashLogExtendEvent (
1388            0,
1389            (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,
1390            sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1,
1391            &TcgEvent,
1392            (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING
1393            );
1394 }
1395 
1396 /**
1397   Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.
1398 
1399   Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)
1400    - The contents of the SecureBoot variable
1401    - The contents of the PK variable
1402    - The contents of the KEK variable
1403    - The contents of the EFI_IMAGE_SECURITY_DATABASE variable
1404    - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable
1405    - Separator
1406    - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path
1407 
1408   NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,
1409   EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].
1410 
1411   @param[in]  Event     Event whose notification function is being invoked
1412   @param[in]  Context   Pointer to the notification function's context
1413 **/
1414 VOID
1415 EFIAPI
MeasureSecureBootPolicy(IN EFI_EVENT Event,IN VOID * Context)1416 MeasureSecureBootPolicy (
1417   IN EFI_EVENT                      Event,
1418   IN VOID                           *Context
1419   )
1420 {
1421   EFI_STATUS  Status;
1422   VOID        *Protocol;
1423 
1424   Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);
1425   if (EFI_ERROR (Status)) {
1426     return;
1427   }
1428 
1429   if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {
1430     Status = MeasureLaunchOfFirmwareDebugger ();
1431     DEBUG ((EFI_D_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));
1432   }
1433 
1434   Status = MeasureAllSecureVariables ();
1435   DEBUG ((EFI_D_INFO, "MeasureAllSecureVariables - %r\n", Status));
1436 
1437   //
1438   // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)
1439   // and ImageVerification (Authority)
1440   // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So
1441   // the Authority measurement happen before ReadToBoot event.
1442   //
1443   Status = MeasureSeparatorEvent (7);
1444   DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent - %r\n", Status));
1445   return ;
1446 }
1447 
1448 /**
1449   Ready to Boot Event notification handler.
1450 
1451   Sequence of OS boot events is measured in this event notification handler.
1452 
1453   @param[in]  Event     Event whose notification function is being invoked
1454   @param[in]  Context   Pointer to the notification function's context
1455 
1456 **/
1457 VOID
1458 EFIAPI
OnReadyToBoot(IN EFI_EVENT Event,IN VOID * Context)1459 OnReadyToBoot (
1460   IN      EFI_EVENT                 Event,
1461   IN      VOID                      *Context
1462   )
1463 {
1464   EFI_STATUS                        Status;
1465   TPM_PCRINDEX                      PcrIndex;
1466 
1467   PERF_START_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE);
1468   if (mBootAttempts == 0) {
1469 
1470     //
1471     // Measure handoff tables.
1472     //
1473     Status = MeasureHandoffTables ();
1474     if (EFI_ERROR (Status)) {
1475       DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));
1476     }
1477 
1478     //
1479     // Measure BootOrder & Boot#### variables.
1480     //
1481     Status = MeasureAllBootVariables ();
1482     if (EFI_ERROR (Status)) {
1483       DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));
1484     }
1485 
1486     //
1487     // 1. This is the first boot attempt.
1488     //
1489     Status = TcgMeasureAction (
1490                EFI_CALLING_EFI_APPLICATION
1491                );
1492     if (EFI_ERROR (Status)) {
1493       DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));
1494     }
1495 
1496     //
1497     // 2. Draw a line between pre-boot env and entering post-boot env.
1498     // PCR[7] is already done.
1499     //
1500     for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) {
1501       Status = MeasureSeparatorEvent (PcrIndex);
1502       if (EFI_ERROR (Status)) {
1503         DEBUG ((EFI_D_ERROR, "Seperator Event not Measured. Error!\n"));
1504       }
1505     }
1506 
1507     //
1508     // 3. Measure GPT. It would be done in SAP driver.
1509     //
1510 
1511     //
1512     // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
1513     //
1514 
1515     //
1516     // 5. Read & Measure variable. BootOrder already measured.
1517     //
1518   } else {
1519     //
1520     // 6. Not first attempt, meaning a return from last attempt
1521     //
1522     Status = TcgMeasureAction (
1523                EFI_RETURNING_FROM_EFI_APPLICATOIN
1524                );
1525     if (EFI_ERROR (Status)) {
1526       DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN));
1527     }
1528   }
1529 
1530   DEBUG ((EFI_D_INFO, "TPM2 TrEEDxe Measure Data when ReadyToBoot\n"));
1531   //
1532   // Increase boot attempt counter.
1533   //
1534   mBootAttempts++;
1535   PERF_END_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE + 1);
1536 }
1537 
1538 /**
1539   Install TCG ACPI Table when ACPI Table Protocol is available.
1540 
1541   A system's firmware uses an ACPI table to identify the system's TCG capabilities
1542   to the Post-Boot environment. The information in this ACPI table is not guaranteed
1543   to be valid until the Host Platform transitions from pre-boot state to post-boot state.
1544 
1545   @param[in]  Event     Event whose notification function is being invoked
1546   @param[in]  Context   Pointer to the notification function's context
1547 **/
1548 VOID
1549 EFIAPI
InstallAcpiTable(IN EFI_EVENT Event,IN VOID * Context)1550 InstallAcpiTable (
1551   IN EFI_EVENT                      Event,
1552   IN VOID                           *Context
1553   )
1554 {
1555   UINTN                             TableKey;
1556   EFI_STATUS                        Status;
1557   EFI_ACPI_TABLE_PROTOCOL           *AcpiTable;
1558   UINT8                             Checksum;
1559   UINT64                            OemTableId;
1560 
1561   Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
1562   if (EFI_ERROR (Status)) {
1563     return;
1564   }
1565 
1566   if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {
1567     CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));
1568     OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
1569     CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
1570     mTcgClientAcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
1571     mTcgClientAcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
1572     mTcgClientAcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
1573     //
1574     // The ACPI table must be checksumed before calling the InstallAcpiTable()
1575     // service of the ACPI table protocol to install it.
1576     //
1577     Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));
1578     mTcgClientAcpiTemplate.Header.Checksum = Checksum;
1579 
1580     Status = AcpiTable->InstallAcpiTable (
1581                             AcpiTable,
1582                             &mTcgClientAcpiTemplate,
1583                             sizeof (mTcgClientAcpiTemplate),
1584                             &TableKey
1585                             );
1586   } else {
1587     CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));
1588     OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
1589     CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
1590     mTcgServerAcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
1591     mTcgServerAcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
1592     mTcgServerAcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);
1593     //
1594     // The ACPI table must be checksumed before calling the InstallAcpiTable()
1595     // service of the ACPI table protocol to install it.
1596     //
1597     Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));
1598     mTcgServerAcpiTemplate.Header.Checksum = Checksum;
1599 
1600     mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);
1601     Status = AcpiTable->InstallAcpiTable (
1602                             AcpiTable,
1603                             &mTcgServerAcpiTemplate,
1604                             sizeof (mTcgServerAcpiTemplate),
1605                             &TableKey
1606                             );
1607   }
1608 
1609   if (EFI_ERROR (Status)) {
1610     DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure"));
1611   }
1612 }
1613 
1614 /**
1615   Exit Boot Services Event notification handler.
1616 
1617   Measure invocation and success of ExitBootServices.
1618 
1619   @param[in]  Event     Event whose notification function is being invoked
1620   @param[in]  Context   Pointer to the notification function's context
1621 
1622 **/
1623 VOID
1624 EFIAPI
OnExitBootServices(IN EFI_EVENT Event,IN VOID * Context)1625 OnExitBootServices (
1626   IN      EFI_EVENT                 Event,
1627   IN      VOID                      *Context
1628   )
1629 {
1630   EFI_STATUS    Status;
1631 
1632   //
1633   // Measure invocation of ExitBootServices,
1634   //
1635   Status = TcgMeasureAction (
1636              EFI_EXIT_BOOT_SERVICES_INVOCATION
1637              );
1638   if (EFI_ERROR (Status)) {
1639     DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));
1640   }
1641 
1642   //
1643   // Measure success of ExitBootServices
1644   //
1645   Status = TcgMeasureAction (
1646              EFI_EXIT_BOOT_SERVICES_SUCCEEDED
1647              );
1648   if (EFI_ERROR (Status)) {
1649     DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));
1650   }
1651 }
1652 
1653 /**
1654   Exit Boot Services Failed Event notification handler.
1655 
1656   Measure Failure of ExitBootServices.
1657 
1658   @param[in]  Event     Event whose notification function is being invoked
1659   @param[in]  Context   Pointer to the notification function's context
1660 
1661 **/
1662 VOID
1663 EFIAPI
OnExitBootServicesFailed(IN EFI_EVENT Event,IN VOID * Context)1664 OnExitBootServicesFailed (
1665   IN      EFI_EVENT                 Event,
1666   IN      VOID                      *Context
1667   )
1668 {
1669   EFI_STATUS    Status;
1670 
1671   //
1672   // Measure Failure of ExitBootServices,
1673   //
1674   Status = TcgMeasureAction (
1675              EFI_EXIT_BOOT_SERVICES_FAILED
1676              );
1677   if (EFI_ERROR (Status)) {
1678     DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));
1679   }
1680 
1681 }
1682 
1683 /**
1684   The function install TrEE protocol.
1685 
1686   @retval EFI_SUCCESS     TrEE protocol is installed.
1687   @retval other           Some error occurs.
1688 **/
1689 EFI_STATUS
InstallTrEE(VOID)1690 InstallTrEE (
1691   VOID
1692   )
1693 {
1694   EFI_STATUS        Status;
1695   EFI_HANDLE        Handle;
1696 
1697   Handle = NULL;
1698   Status = gBS->InstallMultipleProtocolInterfaces (
1699                   &Handle,
1700                   &gEfiTrEEProtocolGuid,
1701                   &mTreeProtocol,
1702                   NULL
1703                   );
1704   return Status;
1705 }
1706 
1707 /**
1708   The driver's entry point. It publishes EFI TrEE Protocol.
1709 
1710   @param[in] ImageHandle  The firmware allocated handle for the EFI image.
1711   @param[in] SystemTable  A pointer to the EFI System Table.
1712 
1713   @retval EFI_SUCCESS     The entry point is executed successfully.
1714   @retval other           Some error occurs when executing this entry point.
1715 **/
1716 EFI_STATUS
1717 EFIAPI
DriverEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1718 DriverEntry (
1719   IN    EFI_HANDLE                  ImageHandle,
1720   IN    EFI_SYSTEM_TABLE            *SystemTable
1721   )
1722 {
1723   EFI_STATUS                        Status;
1724   EFI_EVENT                         Event;
1725   VOID                              *Registration;
1726   UINT32                            MaxCommandSize;
1727   UINT32                            MaxResponseSize;
1728   TPML_PCR_SELECTION                Pcrs;
1729   UINTN                             Index;
1730   UINT32                            TpmHashAlgorithmBitmap;
1731 
1732   mImageHandle = ImageHandle;
1733 
1734   if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||
1735       CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){
1736     DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));
1737     return EFI_UNSUPPORTED;
1738   }
1739 
1740   if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {
1741     DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));
1742     return EFI_DEVICE_ERROR;
1743   }
1744 
1745   Status = Tpm2RequestUseTpm ();
1746   if (EFI_ERROR (Status)) {
1747     DEBUG ((EFI_D_ERROR, "TPM2 not detected!\n"));
1748     return Status;
1749   }
1750 
1751   //
1752   // Fill information
1753   //
1754   DEBUG ((EFI_D_INFO, "TrEE.ProtocolVersion  - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor));
1755   DEBUG ((EFI_D_INFO, "TrEE.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor));
1756 
1757   Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID);
1758   if (EFI_ERROR (Status)) {
1759     DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n"));
1760   } else {
1761     DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID));
1762   }
1763 
1764   DEBUG_CODE (
1765     UINT32                    FirmwareVersion1;
1766     UINT32                    FirmwareVersion2;
1767 
1768     Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2);
1769     if (EFI_ERROR (Status)) {
1770       DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n"));
1771     } else {
1772       DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2));
1773     }
1774   );
1775 
1776   Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize);
1777   if (EFI_ERROR (Status)) {
1778     DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n"));
1779   } else {
1780     mTcgDxeData.BsCap.MaxCommandSize  = (UINT16)MaxCommandSize;
1781     mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize;
1782     DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize));
1783   }
1784 
1785   Status = Tpm2GetCapabilityPcrs (&Pcrs);
1786   if (EFI_ERROR (Status)) {
1787     DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));
1788     TpmHashAlgorithmBitmap = TREE_BOOT_HASH_ALG_SHA1;
1789   } else {
1790     DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));
1791     TpmHashAlgorithmBitmap = 0;
1792     for (Index = 0; Index < Pcrs.count; Index++) {
1793       DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash));
1794       switch (Pcrs.pcrSelections[Index].hash) {
1795       case TPM_ALG_SHA1:
1796         TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA1;
1797         break;
1798       case TPM_ALG_SHA256:
1799         TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA256;
1800         break;
1801       case TPM_ALG_SHA384:
1802         TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA384;
1803         break;
1804       case TPM_ALG_SHA512:
1805         TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA512;
1806         break;
1807       case TPM_ALG_SM3_256:
1808         // TBD: Spec not define TREE_BOOT_HASH_ALG_SM3_256 yet
1809         break;
1810       }
1811     }
1812   }
1813   DEBUG ((EFI_D_INFO, "TPM.HashAlgorithmBitmap - 0x%08x\n", TpmHashAlgorithmBitmap));
1814 
1815   DEBUG ((EFI_D_INFO, "TrEE.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs));
1816   mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap;
1817   DEBUG ((EFI_D_INFO, "TrEE.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap));
1818 
1819   if (mTcgDxeData.BsCap.TrEEPresentFlag) {
1820     //
1821     // Setup the log area and copy event log from hob list to it
1822     //
1823     Status = SetupEventLog ();
1824     ASSERT_EFI_ERROR (Status);
1825 
1826     //
1827     // Measure handoff tables, Boot#### variables etc.
1828     //
1829     Status = EfiCreateEventReadyToBootEx (
1830                TPL_CALLBACK,
1831                OnReadyToBoot,
1832                NULL,
1833                &Event
1834                );
1835 
1836     Status = gBS->CreateEventEx (
1837                     EVT_NOTIFY_SIGNAL,
1838                     TPL_NOTIFY,
1839                     OnExitBootServices,
1840                     NULL,
1841                     &gEfiEventExitBootServicesGuid,
1842                     &Event
1843                     );
1844 
1845     //
1846     // Measure Exit Boot Service failed
1847     //
1848     Status = gBS->CreateEventEx (
1849                     EVT_NOTIFY_SIGNAL,
1850                     TPL_NOTIFY,
1851                     OnExitBootServicesFailed,
1852                     NULL,
1853                     &gEventExitBootServicesFailedGuid,
1854                     &Event
1855                     );
1856 
1857     //
1858     // Create event callback, because we need access variable on SecureBootPolicyVariable
1859     // We should use VariableWriteArch instead of VariableArch, because Variable driver
1860     // may update SecureBoot value based on last setting.
1861     //
1862     EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);
1863   }
1864 
1865   //
1866   // Install ACPI Table
1867   //
1868   EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);
1869 
1870   //
1871   // Install TrEEProtocol
1872   //
1873   Status = InstallTrEE ();
1874   DEBUG ((EFI_D_INFO, "InstallTrEE - %r\n", Status));
1875 
1876   return Status;
1877 }
1878