2 This module implements TCG EFI Protocol.
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.
9 TcgDxePassThroughToTpm() will receive untrusted input and do basic validation.
11 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
12 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
13 SPDX-License-Identifier: BSD-2-Clause-Patent
18 #include <IndustryStandard/Tpm12.h>
19 #include <IndustryStandard/Acpi.h>
20 #include <IndustryStandard/PeImage.h>
21 #include <IndustryStandard/TcpaAcpi.h>
23 #include <Guid/GlobalVariable.h>
24 #include <Guid/HobList.h>
25 #include <Guid/TcgEventHob.h>
26 #include <Guid/EventGroup.h>
27 #include <Guid/EventExitBootServiceFailed.h>
28 #include <Guid/TpmInstance.h>
30 #include <Protocol/DevicePath.h>
31 #include <Protocol/TcgService.h>
32 #include <Protocol/AcpiTable.h>
33 #include <Protocol/MpService.h>
35 #include <Library/DebugLib.h>
36 #include <Library/BaseMemoryLib.h>
37 #include <Library/UefiRuntimeServicesTableLib.h>
38 #include <Library/UefiDriverEntryPoint.h>
39 #include <Library/HobLib.h>
40 #include <Library/UefiBootServicesTableLib.h>
41 #include <Library/BaseLib.h>
42 #include <Library/MemoryAllocationLib.h>
43 #include <Library/PrintLib.h>
44 #include <Library/Tpm12DeviceLib.h>
45 #include <Library/PcdLib.h>
46 #include <Library/UefiLib.h>
47 #include <Library/ReportStatusCodeLib.h>
48 #include <Library/Tpm12CommandLib.h>
49 #include <Library/BaseCryptLib.h>
51 #define TCG_DXE_DATA_FROM_THIS(this) \
52 BASE_CR (this, TCG_DXE_DATA, TcgProtocol)
54 typedef struct _TCG_DXE_DATA
{
55 EFI_TCG_PROTOCOL TcgProtocol
;
56 TCG_EFI_BOOT_SERVICE_CAPABILITY BsCap
;
57 EFI_TCG_CLIENT_ACPI_TABLE
*TcgClientAcpiTable
;
58 EFI_TCG_SERVER_ACPI_TABLE
*TcgServerAcpiTable
;
65 EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate
= {
67 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
68 sizeof (mTcgClientAcpiTemplate
),
71 // Compiler initializes the remaining bytes to 0
72 // These fields should be filled in in production
75 0, // 0 for PC Client Platform Class
76 0, // Log Area Max Length
77 (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1) // Log Area Start Address
81 // The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
82 // the TPM device connects to LPC, and also defined the ACPI _UID as 0xFF,
83 // this _UID can be changed and should match with the _UID setting of the TPM
86 EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate
= {
88 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
89 sizeof (mTcgServerAcpiTemplate
),
92 // Compiler initializes the remaining bytes to 0
93 // These fields should be filled in in production
96 1, // 1 for Server Platform Class
98 0, // Log Area Max Length
99 (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1), // Log Area Start Address
100 0x0120, // TCG Specification revision 1.2
102 0, // Interrupt Flags
104 {0}, // Reserved 3 bytes
105 0, // Global System Interrupt
107 EFI_ACPI_3_0_SYSTEM_MEMORY
,
114 {0}, // Configuration Address
115 0xFF, // ACPI _UID value of the device, can be changed for different platforms
116 0, // ACPI _UID value of the device, can be changed for different platforms
117 0, // ACPI _UID value of the device, can be changed for different platforms
118 0 // ACPI _UID value of the device, can be changed for different platforms
121 UINTN mBootAttempts
= 0;
122 CHAR16 mBootVarName
[] = L
"BootOrder";
125 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
126 Caller is responsible to free LocationBuf.
128 @param[out] LocationBuf Returns Processor Location Buffer.
129 @param[out] Num Returns processor number.
131 @retval EFI_SUCCESS Operation completed successfully.
132 @retval EFI_UNSUPPORTED MpService protocol not found.
136 GetProcessorsCpuLocation (
137 OUT EFI_CPU_PHYSICAL_LOCATION
**LocationBuf
,
142 EFI_MP_SERVICES_PROTOCOL
*MpProtocol
;
144 UINTN EnabledProcessorNum
;
145 EFI_PROCESSOR_INFORMATION ProcessorInfo
;
146 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
149 Status
= gBS
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**) &MpProtocol
);
150 if (EFI_ERROR (Status
)) {
152 // MP protocol is not installed
154 return EFI_UNSUPPORTED
;
157 Status
= MpProtocol
->GetNumberOfProcessors(
162 if (EFI_ERROR(Status
)){
166 Status
= gBS
->AllocatePool(
168 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
169 (VOID
**) &ProcessorLocBuf
171 if (EFI_ERROR(Status
)){
176 // Get each processor Location info
178 for (Index
= 0; Index
< ProcessorNum
; Index
++) {
179 Status
= MpProtocol
->GetProcessorInfo(
184 if (EFI_ERROR(Status
)){
185 FreePool(ProcessorLocBuf
);
190 // Get all Processor Location info & measure
193 &ProcessorLocBuf
[Index
],
194 &ProcessorInfo
.Location
,
195 sizeof(EFI_CPU_PHYSICAL_LOCATION
)
199 *LocationBuf
= ProcessorLocBuf
;
206 This service provides EFI protocol capability information, state information
207 about the TPM, and Event Log state information.
209 @param[in] This Indicates the calling context
210 @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
211 structure and fills in the fields with the EFI protocol
212 capability information and the current TPM state information.
213 @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature
214 flags are currently defined so this parameter
215 MUST be set to 0. However, in the future,
216 feature flags may be defined that, for example,
217 enable hash algorithm agility.
218 @param[out] EventLogLocation This is a pointer to the address of the event log in memory.
219 @param[out] EventLogLastEntry If the Event Log contains more than one entry,
220 this is a pointer to the address of the start of
221 the last entry in the event log in memory.
223 @retval EFI_SUCCESS Operation completed successfully.
224 @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.
230 IN EFI_TCG_PROTOCOL
*This
,
231 OUT TCG_EFI_BOOT_SERVICE_CAPABILITY
*ProtocolCapability
,
232 OUT UINT32
*TCGFeatureFlags
,
233 OUT EFI_PHYSICAL_ADDRESS
*EventLogLocation
,
234 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
237 TCG_DXE_DATA
*TcgData
;
239 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
241 if (ProtocolCapability
!= NULL
) {
242 *ProtocolCapability
= TcgData
->BsCap
;
245 if (TCGFeatureFlags
!= NULL
) {
246 *TCGFeatureFlags
= 0;
249 if (EventLogLocation
!= NULL
) {
250 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
251 *EventLogLocation
= TcgData
->TcgClientAcpiTable
->Lasa
;
253 *EventLogLocation
= TcgData
->TcgServerAcpiTable
->Lasa
;
257 if (EventLogLastEntry
!= NULL
) {
258 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
259 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)0;
261 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TcgData
->LastEvent
;
269 Single function calculates SHA1 digest value for all raw data. It
270 combines Sha1Init(), Sha1Update() and Sha1Final().
272 @param[in] Data Raw data to be digested.
273 @param[in] DataLen Size of the raw data.
274 @param[out] Digest Pointer to a buffer that stores the final digest.
276 @retval EFI_SUCCESS Always successfully calculate the final digest.
281 IN CONST UINT8
*Data
,
283 OUT TPM_DIGEST
*Digest
289 CtxSize
= Sha1GetContextSize ();
290 Sha1Ctx
= AllocatePool (CtxSize
);
291 ASSERT (Sha1Ctx
!= NULL
);
294 Sha1Update (Sha1Ctx
, Data
, DataLen
);
295 Sha1Final (Sha1Ctx
, (UINT8
*)Digest
);
303 This service abstracts the capability to do a hash operation on a data buffer.
305 @param[in] This Indicates the calling context
306 @param[in] HashData Pointer to the data buffer to be hashed
307 @param[in] HashDataLen Length of the data buffer to be hashed
308 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
309 @param[in, out] HashedDataLen Resultant length of the hashed data
310 @param[in, out] HashedDataResult Resultant buffer of the hashed data
312 @retval EFI_SUCCESS Operation completed successfully.
313 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
314 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
315 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
316 @retval EFI_UNSUPPORTED AlgorithmId not supported.
317 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
323 IN EFI_TCG_PROTOCOL
*This
,
325 IN UINT64 HashDataLen
,
326 IN TCG_ALGORITHM_ID AlgorithmId
,
327 IN OUT UINT64
*HashedDataLen
,
328 IN OUT UINT8
**HashedDataResult
331 if (HashedDataLen
== NULL
|| HashedDataResult
== NULL
) {
332 return EFI_INVALID_PARAMETER
;
335 switch (AlgorithmId
) {
337 if (*HashedDataLen
== 0) {
338 *HashedDataLen
= sizeof (TPM_DIGEST
);
339 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
340 if (*HashedDataResult
== NULL
) {
341 return EFI_OUT_OF_RESOURCES
;
345 if (*HashedDataLen
< sizeof (TPM_DIGEST
)) {
346 *HashedDataLen
= sizeof (TPM_DIGEST
);
347 return EFI_BUFFER_TOO_SMALL
;
349 *HashedDataLen
= sizeof (TPM_DIGEST
);
351 if (*HashedDataResult
== NULL
) {
352 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
355 return TpmCommHashAll (
358 (TPM_DIGEST
*)*HashedDataResult
361 return EFI_UNSUPPORTED
;
366 Add a new entry to the Event Log.
368 @param[in, out] EventLogPtr Pointer to the Event Log data.
369 @param[in, out] LogSize Size of the Event Log.
370 @param[in] MaxSize Maximum size of the Event Log.
371 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
372 @param[in] NewEventData Pointer to the new event data.
374 @retval EFI_SUCCESS The new event log entry was added.
375 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
380 IN OUT UINT8
**EventLogPtr
,
381 IN OUT UINTN
*LogSize
,
383 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
384 IN UINT8
*NewEventData
390 // Prevent Event Overflow
392 if ((UINTN
) NewEventHdr
->EventSize
> MAX_UINTN
- sizeof (*NewEventHdr
)) {
393 return EFI_OUT_OF_RESOURCES
;
396 NewLogSize
= sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
;
397 if (NewLogSize
> MaxSize
- *LogSize
) {
398 return EFI_OUT_OF_RESOURCES
;
401 *EventLogPtr
+= *LogSize
;
402 *LogSize
+= NewLogSize
;
403 CopyMem (*EventLogPtr
, NewEventHdr
, sizeof (*NewEventHdr
));
405 *EventLogPtr
+ sizeof (*NewEventHdr
),
407 NewEventHdr
->EventSize
413 Add a new entry to the Event Log.
415 @param[in] TcgData TCG_DXE_DATA structure.
416 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
417 @param[in] NewEventData Pointer to the new event data.
419 @retval EFI_SUCCESS The new event log entry was added.
420 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
426 IN TCG_DXE_DATA
*TcgData
,
427 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
428 IN UINT8
*NewEventData
431 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
432 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgClientAcpiTable
->Lasa
;
433 return TpmCommLogEvent (
435 &TcgData
->EventLogSize
,
436 (UINTN
)TcgData
->TcgClientAcpiTable
->Laml
,
441 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgServerAcpiTable
->Lasa
;
442 return TpmCommLogEvent (
444 &TcgData
->EventLogSize
,
445 (UINTN
)TcgData
->TcgServerAcpiTable
->Laml
,
453 This service abstracts the capability to add an entry to the Event Log.
455 @param[in] This Indicates the calling context
456 @param[in] TCGLogData Pointer to the start of the data buffer containing
457 the TCG_PCR_EVENT data structure. All fields in
458 this structure are properly filled by the caller.
459 @param[in, out] EventNumber The event number of the event just logged
460 @param[in] Flags Indicate additional flags. Only one flag has been
461 defined at this time, which is 0x01 and means the
462 extend operation should not be performed. All
463 other bits are reserved.
465 @retval EFI_SUCCESS Operation completed successfully.
466 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
472 IN EFI_TCG_PROTOCOL
*This
,
473 IN TCG_PCR_EVENT
*TCGLogData
,
474 IN OUT UINT32
*EventNumber
,
478 TCG_DXE_DATA
*TcgData
;
480 if (TCGLogData
== NULL
){
481 return EFI_INVALID_PARAMETER
;
484 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
486 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
487 return EFI_DEVICE_ERROR
;
489 return TcgDxeLogEventI (
491 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
497 This service is a proxy for commands to the TPM.
499 @param[in] This Indicates the calling context
500 @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block
501 @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block
502 @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block
503 @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block
505 @retval EFI_SUCCESS Operation completed successfully.
506 @retval EFI_INVALID_PARAMETER Invalid ordinal.
507 @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.
508 @retval EFI_TIMEOUT The TIS timed-out.
513 TcgDxePassThroughToTpm (
514 IN EFI_TCG_PROTOCOL
*This
,
515 IN UINT32 TpmInputParameterBlockSize
,
516 IN UINT8
*TpmInputParameterBlock
,
517 IN UINT32 TpmOutputParameterBlockSize
,
518 IN UINT8
*TpmOutputParameterBlock
521 if (TpmInputParameterBlock
== NULL
||
522 TpmOutputParameterBlock
== NULL
||
523 TpmInputParameterBlockSize
== 0 ||
524 TpmOutputParameterBlockSize
== 0) {
525 return EFI_INVALID_PARAMETER
;
528 return Tpm12SubmitCommand (
529 TpmInputParameterBlockSize
,
530 TpmInputParameterBlock
,
531 &TpmOutputParameterBlockSize
,
532 TpmOutputParameterBlock
537 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
538 and add an entry to the Event Log.
540 @param[in] TcgData TCG_DXE_DATA structure.
541 @param[in] HashData Physical address of the start of the data buffer
542 to be hashed, extended, and logged.
543 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
544 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
545 @param[in] NewEventData Pointer to the new event data.
547 @retval EFI_SUCCESS Operation completed successfully.
548 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
549 @retval EFI_DEVICE_ERROR The command was unsuccessful.
554 TcgDxeHashLogExtendEventI (
555 IN TCG_DXE_DATA
*TcgData
,
557 IN UINT64 HashDataLen
,
558 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
559 IN UINT8
*NewEventData
564 if (!TcgData
->BsCap
.TPMPresentFlag
) {
565 return EFI_DEVICE_ERROR
;
568 if (HashDataLen
> 0 || HashData
!= NULL
) {
569 Status
= TpmCommHashAll (
574 if (EFI_ERROR(Status
)) {
575 DEBUG ((DEBUG_ERROR
, "TpmCommHashAll Failed. %x\n", Status
));
580 Status
= Tpm12Extend (
581 &NewEventHdr
->Digest
,
582 NewEventHdr
->PCRIndex
,
585 if (!EFI_ERROR (Status
)) {
586 Status
= TcgDxeLogEventI (TcgData
, NewEventHdr
, NewEventData
);
590 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
591 DEBUG ((EFI_D_ERROR
, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status
));
592 TcgData
->BsCap
.TPMPresentFlag
= FALSE
;
594 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
595 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
597 Status
= EFI_DEVICE_ERROR
;
604 This service abstracts the capability to do a hash operation on a data buffer,
605 extend a specific TPM PCR with the hash result, and add an entry to the Event Log
607 @param[in] This Indicates the calling context
608 @param[in] HashData Physical address of the start of the data buffer
609 to be hashed, extended, and logged.
610 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
611 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
612 @param[in, out] TCGLogData The physical address of the start of the data
613 buffer containing the TCG_PCR_EVENT data structure.
614 @param[in, out] EventNumber The event number of the event just logged.
615 @param[out] EventLogLastEntry Physical address of the first byte of the entry
616 just placed in the Event Log. If the Event Log was
617 empty when this function was called then this physical
618 address will be the same as the physical address of
619 the start of the Event Log.
621 @retval EFI_SUCCESS Operation completed successfully.
622 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
623 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
624 @retval EFI_DEVICE_ERROR The command was unsuccessful.
629 TcgDxeHashLogExtendEvent (
630 IN EFI_TCG_PROTOCOL
*This
,
631 IN EFI_PHYSICAL_ADDRESS HashData
,
632 IN UINT64 HashDataLen
,
633 IN TPM_ALGORITHM_ID AlgorithmId
,
634 IN OUT TCG_PCR_EVENT
*TCGLogData
,
635 IN OUT UINT32
*EventNumber
,
636 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
639 TCG_DXE_DATA
*TcgData
;
642 if (TCGLogData
== NULL
|| EventLogLastEntry
== NULL
){
643 return EFI_INVALID_PARAMETER
;
646 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
648 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
649 return EFI_DEVICE_ERROR
;
652 if (AlgorithmId
!= TPM_ALG_SHA
) {
653 return EFI_UNSUPPORTED
;
656 if (HashData
== 0 && HashDataLen
> 0) {
657 return EFI_INVALID_PARAMETER
;
660 Status
= TcgDxeHashLogExtendEventI (
662 (UINT8
*) (UINTN
) HashData
,
664 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
668 if (!EFI_ERROR(Status
)){
669 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) TcgData
->LastEvent
;
675 TCG_DXE_DATA mTcgDxeData
= {
680 TcgDxePassThroughToTpm
,
681 TcgDxeHashLogExtendEvent
684 sizeof (mTcgDxeData
.BsCap
),
691 &mTcgClientAcpiTemplate
,
692 &mTcgServerAcpiTemplate
,
698 Initialize the Event Log and log events passed from the PEI phase.
700 @retval EFI_SUCCESS Operation completed successfully.
701 @retval EFI_OUT_OF_RESOURCES Out of memory.
711 TCG_PCR_EVENT
*TcgEvent
;
712 EFI_PEI_HOB_POINTERS GuidHob
;
713 EFI_PHYSICAL_ADDRESS Lasa
;
715 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
716 Lasa
= mTcgClientAcpiTemplate
.Lasa
;
718 Status
= gBS
->AllocatePages (
721 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
724 if (EFI_ERROR (Status
)) {
727 mTcgClientAcpiTemplate
.Lasa
= Lasa
;
729 // To initialize them as 0xFF is recommended
730 // because the OS can know the last entry for that.
732 SetMem ((VOID
*)(UINTN
)mTcgClientAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
733 mTcgClientAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
736 Lasa
= mTcgServerAcpiTemplate
.Lasa
;
738 Status
= gBS
->AllocatePages (
741 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
744 if (EFI_ERROR (Status
)) {
747 mTcgServerAcpiTemplate
.Lasa
= Lasa
;
749 // To initialize them as 0xFF is recommended
750 // because the OS can know the last entry for that.
752 SetMem ((VOID
*)(UINTN
)mTcgServerAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
753 mTcgServerAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
756 GuidHob
.Raw
= GetHobList ();
757 while (!EFI_ERROR (Status
) &&
758 (GuidHob
.Raw
= GetNextGuidHob (&gTcgEventEntryHobGuid
, GuidHob
.Raw
)) != NULL
) {
759 TcgEvent
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
760 GuidHob
.Raw
= GET_NEXT_HOB (GuidHob
);
761 Status
= TcgDxeLogEventI (
763 (TCG_PCR_EVENT_HDR
*)TcgEvent
,
772 Measure and log an action string, and extend the measurement result into PCR[5].
774 @param[in] String A specific string that indicates an Action event.
776 @retval EFI_SUCCESS Operation completed successfully.
777 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
786 TCG_PCR_EVENT_HDR TcgEvent
;
788 TcgEvent
.PCRIndex
= 5;
789 TcgEvent
.EventType
= EV_EFI_ACTION
;
790 TcgEvent
.EventSize
= (UINT32
)AsciiStrLen (String
);
791 return TcgDxeHashLogExtendEventI (
801 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
803 @retval EFI_SUCCESS Operation completed successfully.
804 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
809 MeasureHandoffTables (
814 TCG_PCR_EVENT_HDR TcgEvent
;
815 EFI_HANDOFF_TABLE_POINTERS HandoffTables
;
817 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
819 ProcessorLocBuf
= NULL
;
820 Status
= EFI_SUCCESS
;
822 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_SERVER
) {
825 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
827 Status
= GetProcessorsCpuLocation(&ProcessorLocBuf
, &ProcessorNum
);
829 if (!EFI_ERROR(Status
)){
830 TcgEvent
.PCRIndex
= 1;
831 TcgEvent
.EventType
= EV_TABLE_OF_DEVICES
;
832 TcgEvent
.EventSize
= sizeof (HandoffTables
);
834 HandoffTables
.NumberOfTables
= 1;
835 HandoffTables
.TableEntry
[0].VendorGuid
= gEfiMpServiceProtocolGuid
;
836 HandoffTables
.TableEntry
[0].VendorTable
= ProcessorLocBuf
;
838 Status
= TcgDxeHashLogExtendEventI (
840 (UINT8
*)(UINTN
)ProcessorLocBuf
,
841 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
843 (UINT8
*)&HandoffTables
846 FreePool(ProcessorLocBuf
);
854 Measure and log Separator event, and extend the measurement result into a specific PCR.
856 @param[in] PCRIndex PCR index.
858 @retval EFI_SUCCESS Operation completed successfully.
859 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
864 MeasureSeparatorEvent (
865 IN TPM_PCRINDEX PCRIndex
868 TCG_PCR_EVENT_HDR TcgEvent
;
872 TcgEvent
.PCRIndex
= PCRIndex
;
873 TcgEvent
.EventType
= EV_SEPARATOR
;
874 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
875 return TcgDxeHashLogExtendEventI (
885 Read an EFI Variable.
887 This function allocates a buffer to return the contents of the variable. The caller is
888 responsible for freeing the buffer.
890 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
891 @param[in] VendorGuid A unique identifier for the vendor.
892 @param[out] VarSize The size of the variable data.
894 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
901 IN EFI_GUID
*VendorGuid
,
909 Status
= gRT
->GetVariable (
916 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
920 VarData
= AllocatePool (*VarSize
);
921 if (VarData
!= NULL
) {
922 Status
= gRT
->GetVariable (
929 if (EFI_ERROR (Status
)) {
939 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
941 @param[in] PCRIndex PCR Index.
942 @param[in] EventType Event type.
943 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
944 @param[in] VendorGuid A unique identifier for the vendor.
945 @param[in] VarData The content of the variable data.
946 @param[in] VarSize The size of the variable data.
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.
956 IN TPM_PCRINDEX PCRIndex
,
957 IN TCG_EVENTTYPE EventType
,
959 IN EFI_GUID
*VendorGuid
,
965 TCG_PCR_EVENT_HDR TcgEvent
;
967 EFI_VARIABLE_DATA
*VarLog
;
969 VarNameLength
= StrLen (VarName
);
970 TcgEvent
.PCRIndex
= PCRIndex
;
971 TcgEvent
.EventType
= EventType
;
972 TcgEvent
.EventSize
= (UINT32
)(sizeof (*VarLog
) + VarNameLength
* sizeof (*VarName
) + VarSize
973 - sizeof (VarLog
->UnicodeName
) - sizeof (VarLog
->VariableData
));
975 VarLog
= (EFI_VARIABLE_DATA
*)AllocatePool (TcgEvent
.EventSize
);
976 if (VarLog
== NULL
) {
977 return EFI_OUT_OF_RESOURCES
;
980 VarLog
->VariableName
= *VendorGuid
;
981 VarLog
->UnicodeNameLength
= VarNameLength
;
982 VarLog
->VariableDataLength
= VarSize
;
986 VarNameLength
* sizeof (*VarName
)
989 (CHAR16
*)VarLog
->UnicodeName
+ VarNameLength
,
994 Status
= TcgDxeHashLogExtendEventI (
1006 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
1008 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
1009 @param[in] VendorGuid A unique identifier for the vendor.
1010 @param[out] VarSize The size of the variable data.
1011 @param[out] VarData Pointer to the content of the variable.
1013 @retval EFI_SUCCESS Operation completed successfully.
1014 @retval EFI_OUT_OF_RESOURCES Out of memory.
1015 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1020 ReadAndMeasureBootVariable (
1022 IN EFI_GUID
*VendorGuid
,
1029 *VarData
= ReadVariable (VarName
, VendorGuid
, VarSize
);
1030 if (*VarData
== NULL
) {
1031 return EFI_NOT_FOUND
;
1034 Status
= MeasureVariable (
1036 EV_EFI_VARIABLE_BOOT
,
1046 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
1048 The EFI boot variables are BootOrder and Boot#### variables.
1050 @retval EFI_SUCCESS Operation completed successfully.
1051 @retval EFI_OUT_OF_RESOURCES Out of memory.
1052 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1057 MeasureAllBootVariables (
1068 Status
= ReadAndMeasureBootVariable (
1070 &gEfiGlobalVariableGuid
,
1072 (VOID
**) &BootOrder
1074 if (Status
== EFI_NOT_FOUND
|| BootOrder
== NULL
) {
1078 if (EFI_ERROR (Status
)) {
1080 // BootOrder can't be NULL if status is not EFI_NOT_FOUND
1082 FreePool (BootOrder
);
1086 BootCount
/= sizeof (*BootOrder
);
1087 for (Index
= 0; Index
< BootCount
; Index
++) {
1088 UnicodeSPrint (mBootVarName
, sizeof (mBootVarName
), L
"Boot%04x", BootOrder
[Index
]);
1089 Status
= ReadAndMeasureBootVariable (
1091 &gEfiGlobalVariableGuid
,
1095 if (!EFI_ERROR (Status
)) {
1096 FreePool (BootVarData
);
1100 FreePool (BootOrder
);
1105 Ready to Boot Event notification handler.
1107 Sequence of OS boot events is measured in this event notification handler.
1109 @param[in] Event Event whose notification function is being invoked
1110 @param[in] Context Pointer to the notification function's context
1121 TPM_PCRINDEX PcrIndex
;
1123 if (mBootAttempts
== 0) {
1126 // Measure handoff tables.
1128 Status
= MeasureHandoffTables ();
1129 if (EFI_ERROR (Status
)) {
1130 DEBUG ((EFI_D_ERROR
, "HOBs not Measured. Error!\n"));
1134 // Measure BootOrder & Boot#### variables.
1136 Status
= MeasureAllBootVariables ();
1137 if (EFI_ERROR (Status
)) {
1138 DEBUG ((EFI_D_ERROR
, "Boot Variables not Measured. Error!\n"));
1142 // 1. This is the first boot attempt.
1144 Status
= TcgMeasureAction (
1145 EFI_CALLING_EFI_APPLICATION
1147 if (EFI_ERROR (Status
)) {
1148 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION
));
1152 // 2. Draw a line between pre-boot env and entering post-boot env.
1154 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1155 Status
= MeasureSeparatorEvent (PcrIndex
);
1156 if (EFI_ERROR (Status
)) {
1157 DEBUG ((DEBUG_ERROR
, "Separator Event not Measured. Error!\n"));
1162 // 3. Measure GPT. It would be done in SAP driver.
1166 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
1170 // 5. Read & Measure variable. BootOrder already measured.
1174 // 6. Not first attempt, meaning a return from last attempt
1176 Status
= TcgMeasureAction (
1177 EFI_RETURNING_FROM_EFI_APPLICATION
1179 if (EFI_ERROR (Status
)) {
1180 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION
));
1184 DEBUG ((EFI_D_INFO
, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
1186 // Increase boot attempt counter.
1192 Install TCG ACPI Table when ACPI Table Protocol is available.
1194 A system's firmware uses an ACPI table to identify the system's TCG capabilities
1195 to the Post-Boot environment. The information in this ACPI table is not guaranteed
1196 to be valid until the Host Platform transitions from pre-boot state to post-boot state.
1198 @param[in] Event Event whose notification function is being invoked
1199 @param[in] Context Pointer to the notification function's context
1210 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
1214 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**)&AcpiTable
);
1215 if (EFI_ERROR (Status
)) {
1219 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
1220 CopyMem (mTcgClientAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgClientAcpiTemplate
.Header
.OemId
));
1221 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1222 CopyMem (&mTcgClientAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1223 mTcgClientAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1224 mTcgClientAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1225 mTcgClientAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1227 // The ACPI table must be checksummed before calling the InstallAcpiTable()
1228 // service of the ACPI table protocol to install it.
1230 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgClientAcpiTemplate
, sizeof (mTcgClientAcpiTemplate
));
1231 mTcgClientAcpiTemplate
.Header
.Checksum
= Checksum
;
1233 Status
= AcpiTable
->InstallAcpiTable (
1235 &mTcgClientAcpiTemplate
,
1236 sizeof (mTcgClientAcpiTemplate
),
1240 CopyMem (mTcgServerAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgServerAcpiTemplate
.Header
.OemId
));
1241 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1242 CopyMem (&mTcgServerAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1243 mTcgServerAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1244 mTcgServerAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1245 mTcgServerAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1247 // The ACPI table must be checksummed before calling the InstallAcpiTable()
1248 // service of the ACPI table protocol to install it.
1250 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgServerAcpiTemplate
, sizeof (mTcgServerAcpiTemplate
));
1251 mTcgServerAcpiTemplate
.Header
.Checksum
= Checksum
;
1253 mTcgServerAcpiTemplate
.BaseAddress
.Address
= PcdGet64 (PcdTpmBaseAddress
);
1254 Status
= AcpiTable
->InstallAcpiTable (
1256 &mTcgServerAcpiTemplate
,
1257 sizeof (mTcgServerAcpiTemplate
),
1262 if (EFI_ERROR (Status
)) {
1263 DEBUG((EFI_D_ERROR
, "Tcg Acpi Table installation failure"));
1268 Exit Boot Services Event notification handler.
1270 Measure invocation and success of ExitBootServices.
1272 @param[in] Event Event whose notification function is being invoked
1273 @param[in] Context Pointer to the notification function's context
1278 OnExitBootServices (
1286 // Measure invocation of ExitBootServices,
1288 Status
= TcgMeasureAction (
1289 EFI_EXIT_BOOT_SERVICES_INVOCATION
1291 if (EFI_ERROR (Status
)) {
1292 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION
));
1296 // Measure success of ExitBootServices
1298 Status
= TcgMeasureAction (
1299 EFI_EXIT_BOOT_SERVICES_SUCCEEDED
1301 if (EFI_ERROR (Status
)){
1302 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED
));
1307 Exit Boot Services Failed Event notification handler.
1309 Measure Failure of ExitBootServices.
1311 @param[in] Event Event whose notification function is being invoked
1312 @param[in] Context Pointer to the notification function's context
1317 OnExitBootServicesFailed (
1325 // Measure Failure of ExitBootServices,
1327 Status
= TcgMeasureAction (
1328 EFI_EXIT_BOOT_SERVICES_FAILED
1330 if (EFI_ERROR (Status
)){
1331 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED
));
1336 Get TPM Deactivated state.
1338 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
1340 @retval EFI_SUCCESS Operation completed successfully.
1341 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1346 OUT BOOLEAN
*TPMDeactivatedFlag
1350 TPM_STCLEAR_FLAGS VolatileFlags
;
1352 Status
= Tpm12GetCapabilityFlagVolatile (&VolatileFlags
);
1353 if (!EFI_ERROR (Status
)) {
1354 *TPMDeactivatedFlag
= VolatileFlags
.deactivated
;
1361 The driver's entry point.
1363 It publishes EFI TCG Protocol.
1365 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1366 @param[in] SystemTable A pointer to the EFI System Table.
1368 @retval EFI_SUCCESS The entry point is executed successfully.
1369 @retval other Some error occurs when executing this entry point.
1375 IN EFI_HANDLE ImageHandle
,
1376 IN EFI_SYSTEM_TABLE
*SystemTable
1383 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
1384 DEBUG ((EFI_D_ERROR
, "No TPM12 instance required!\n"));
1385 return EFI_UNSUPPORTED
;
1388 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1389 DEBUG ((EFI_D_ERROR
, "TPM error!\n"));
1390 return EFI_DEVICE_ERROR
;
1393 Status
= Tpm12RequestUseTpm ();
1394 if (EFI_ERROR (Status
)) {
1395 DEBUG ((EFI_D_ERROR
, "TPM not detected!\n"));
1399 Status
= GetTpmStatus (&mTcgDxeData
.BsCap
.TPMDeactivatedFlag
);
1400 if (EFI_ERROR (Status
)) {
1403 "DriverEntry: TPM not working properly\n"
1408 Status
= gBS
->InstallProtocolInterface (
1410 &gEfiTcgProtocolGuid
,
1411 EFI_NATIVE_INTERFACE
,
1412 &mTcgDxeData
.TcgProtocol
1414 if (!EFI_ERROR (Status
) && (!mTcgDxeData
.BsCap
.TPMDeactivatedFlag
) && mTcgDxeData
.BsCap
.TPMPresentFlag
) {
1416 // Setup the log area and copy event log from hob list to it
1418 Status
= SetupEventLog ();
1419 ASSERT_EFI_ERROR (Status
);
1422 // Measure handoff tables, Boot#### variables etc.
1424 Status
= EfiCreateEventReadyToBootEx (
1431 Status
= gBS
->CreateEventEx (
1436 &gEfiEventExitBootServicesGuid
,
1441 // Measure Exit Boot Service failed
1443 Status
= gBS
->CreateEventEx (
1446 OnExitBootServicesFailed
,
1448 &gEventExitBootServicesFailedGuid
,
1454 // Install ACPI Table
1456 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid
, TPL_CALLBACK
, InstallAcpiTable
, NULL
, &Registration
);