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
;
63 EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate
= {
65 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
66 sizeof (mTcgClientAcpiTemplate
),
69 // Compiler initializes the remaining bytes to 0
70 // These fields should be filled in in production
73 0, // 0 for PC Client Platform Class
74 0, // Log Area Max Length
75 (EFI_PHYSICAL_ADDRESS
)(SIZE_4GB
- 1) // Log Area Start Address
79 // The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
80 // the TPM device connects to LPC, and also defined the ACPI _UID as 0xFF,
81 // this _UID can be changed and should match with the _UID setting of the TPM
84 EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate
= {
86 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
87 sizeof (mTcgServerAcpiTemplate
),
90 // Compiler initializes the remaining bytes to 0
91 // These fields should be filled in in production
94 1, // 1 for Server Platform Class
96 0, // Log Area Max Length
97 (EFI_PHYSICAL_ADDRESS
)(SIZE_4GB
- 1), // Log Area Start Address
98 0x0120, // TCG Specification revision 1.2
100 0, // Interrupt Flags
102 { 0 }, // Reserved 3 bytes
103 0, // Global System Interrupt
105 EFI_ACPI_3_0_SYSTEM_MEMORY
,
112 { 0 }, // Configuration Address
113 0xFF, // ACPI _UID value of the device, can be changed for different platforms
114 0, // ACPI _UID value of the device, can be changed for different platforms
115 0, // 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
119 UINTN mBootAttempts
= 0;
120 CHAR16 mBootVarName
[] = L
"BootOrder";
123 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
124 Caller is responsible to free LocationBuf.
126 @param[out] LocationBuf Returns Processor Location Buffer.
127 @param[out] Num Returns processor number.
129 @retval EFI_SUCCESS Operation completed successfully.
130 @retval EFI_UNSUPPORTED MpService protocol not found.
134 GetProcessorsCpuLocation (
135 OUT EFI_CPU_PHYSICAL_LOCATION
**LocationBuf
,
140 EFI_MP_SERVICES_PROTOCOL
*MpProtocol
;
142 UINTN EnabledProcessorNum
;
143 EFI_PROCESSOR_INFORMATION ProcessorInfo
;
144 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
147 Status
= gBS
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**)&MpProtocol
);
148 if (EFI_ERROR (Status
)) {
150 // MP protocol is not installed
152 return EFI_UNSUPPORTED
;
155 Status
= MpProtocol
->GetNumberOfProcessors (
160 if (EFI_ERROR (Status
)) {
164 Status
= gBS
->AllocatePool (
166 sizeof (EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
167 (VOID
**)&ProcessorLocBuf
169 if (EFI_ERROR (Status
)) {
174 // Get each processor Location info
176 for (Index
= 0; Index
< ProcessorNum
; Index
++) {
177 Status
= MpProtocol
->GetProcessorInfo (
182 if (EFI_ERROR (Status
)) {
183 FreePool (ProcessorLocBuf
);
188 // Get all Processor Location info & measure
191 &ProcessorLocBuf
[Index
],
192 &ProcessorInfo
.Location
,
193 sizeof (EFI_CPU_PHYSICAL_LOCATION
)
197 *LocationBuf
= ProcessorLocBuf
;
204 This service provides EFI protocol capability information, state information
205 about the TPM, and Event Log state information.
207 @param[in] This Indicates the calling context
208 @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
209 structure and fills in the fields with the EFI protocol
210 capability information and the current TPM state information.
211 @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature
212 flags are currently defined so this parameter
213 MUST be set to 0. However, in the future,
214 feature flags may be defined that, for example,
215 enable hash algorithm agility.
216 @param[out] EventLogLocation This is a pointer to the address of the event log in memory.
217 @param[out] EventLogLastEntry If the Event Log contains more than one entry,
218 this is a pointer to the address of the start of
219 the last entry in the event log in memory.
221 @retval EFI_SUCCESS Operation completed successfully.
222 @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.
228 IN EFI_TCG_PROTOCOL
*This
,
229 OUT TCG_EFI_BOOT_SERVICE_CAPABILITY
*ProtocolCapability
,
230 OUT UINT32
*TCGFeatureFlags
,
231 OUT EFI_PHYSICAL_ADDRESS
*EventLogLocation
,
232 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
235 TCG_DXE_DATA
*TcgData
;
237 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
239 if (ProtocolCapability
!= NULL
) {
240 *ProtocolCapability
= TcgData
->BsCap
;
243 if (TCGFeatureFlags
!= NULL
) {
244 *TCGFeatureFlags
= 0;
247 if (EventLogLocation
!= NULL
) {
248 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
249 *EventLogLocation
= TcgData
->TcgClientAcpiTable
->Lasa
;
251 *EventLogLocation
= TcgData
->TcgServerAcpiTable
->Lasa
;
255 if (EventLogLastEntry
!= NULL
) {
256 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
257 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)0;
259 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TcgData
->LastEvent
;
267 Single function calculates SHA1 digest value for all raw data. It
268 combines Sha1Init(), Sha1Update() and Sha1Final().
270 @param[in] Data Raw data to be digested.
271 @param[in] DataLen Size of the raw data.
272 @param[out] Digest Pointer to a buffer that stores the final digest.
274 @retval EFI_SUCCESS Always successfully calculate the final digest.
279 IN CONST UINT8
*Data
,
281 OUT TPM_DIGEST
*Digest
287 CtxSize
= Sha1GetContextSize ();
288 Sha1Ctx
= AllocatePool (CtxSize
);
289 ASSERT (Sha1Ctx
!= NULL
);
292 Sha1Update (Sha1Ctx
, Data
, DataLen
);
293 Sha1Final (Sha1Ctx
, (UINT8
*)Digest
);
301 This service abstracts the capability to do a hash operation on a data buffer.
303 @param[in] This Indicates the calling context
304 @param[in] HashData Pointer to the data buffer to be hashed
305 @param[in] HashDataLen Length of the data buffer to be hashed
306 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
307 @param[in, out] HashedDataLen Resultant length of the hashed data
308 @param[in, out] HashedDataResult Resultant buffer of the hashed data
310 @retval EFI_SUCCESS Operation completed successfully.
311 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
312 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
313 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
314 @retval EFI_UNSUPPORTED AlgorithmId not supported.
315 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
321 IN EFI_TCG_PROTOCOL
*This
,
323 IN UINT64 HashDataLen
,
324 IN TCG_ALGORITHM_ID AlgorithmId
,
325 IN OUT UINT64
*HashedDataLen
,
326 IN OUT UINT8
**HashedDataResult
329 if ((HashedDataLen
== NULL
) || (HashedDataResult
== NULL
)) {
330 return EFI_INVALID_PARAMETER
;
333 switch (AlgorithmId
) {
335 if (*HashedDataLen
== 0) {
336 *HashedDataLen
= sizeof (TPM_DIGEST
);
337 *HashedDataResult
= AllocatePool ((UINTN
)*HashedDataLen
);
338 if (*HashedDataResult
== NULL
) {
339 return EFI_OUT_OF_RESOURCES
;
343 if (*HashedDataLen
< sizeof (TPM_DIGEST
)) {
344 *HashedDataLen
= sizeof (TPM_DIGEST
);
345 return EFI_BUFFER_TOO_SMALL
;
348 *HashedDataLen
= sizeof (TPM_DIGEST
);
350 if (*HashedDataResult
== NULL
) {
351 *HashedDataResult
= AllocatePool ((UINTN
)*HashedDataLen
);
354 return TpmCommHashAll (
357 (TPM_DIGEST
*)*HashedDataResult
360 return EFI_UNSUPPORTED
;
365 Add a new entry to the Event Log.
367 @param[in, out] EventLogPtr Pointer to the Event Log data.
368 @param[in, out] LogSize Size of the Event Log.
369 @param[in] MaxSize Maximum size of the Event Log.
370 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
371 @param[in] NewEventData Pointer to the new event data.
373 @retval EFI_SUCCESS The new event log entry was added.
374 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
379 IN OUT UINT8
**EventLogPtr
,
380 IN OUT UINTN
*LogSize
,
382 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
383 IN UINT8
*NewEventData
389 // Prevent Event Overflow
391 if ((UINTN
)NewEventHdr
->EventSize
> MAX_UINTN
- sizeof (*NewEventHdr
)) {
392 return EFI_OUT_OF_RESOURCES
;
395 NewLogSize
= sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
;
396 if (NewLogSize
> MaxSize
- *LogSize
) {
397 return EFI_OUT_OF_RESOURCES
;
400 *EventLogPtr
+= *LogSize
;
401 *LogSize
+= NewLogSize
;
402 CopyMem (*EventLogPtr
, NewEventHdr
, sizeof (*NewEventHdr
));
404 *EventLogPtr
+ sizeof (*NewEventHdr
),
406 NewEventHdr
->EventSize
412 Add a new entry to the Event Log.
414 @param[in] TcgData TCG_DXE_DATA structure.
415 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
416 @param[in] NewEventData Pointer to the new event data.
418 @retval EFI_SUCCESS The new event log entry was added.
419 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
425 IN TCG_DXE_DATA
*TcgData
,
426 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
427 IN UINT8
*NewEventData
430 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
431 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgClientAcpiTable
->Lasa
;
432 return TpmCommLogEvent (
434 &TcgData
->EventLogSize
,
435 (UINTN
)TcgData
->TcgClientAcpiTable
->Laml
,
440 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgServerAcpiTable
->Lasa
;
441 return TpmCommLogEvent (
443 &TcgData
->EventLogSize
,
444 (UINTN
)TcgData
->TcgServerAcpiTable
->Laml
,
452 This service abstracts the capability to add an entry to the Event Log.
454 @param[in] This Indicates the calling context
455 @param[in] TCGLogData Pointer to the start of the data buffer containing
456 the TCG_PCR_EVENT data structure. All fields in
457 this structure are properly filled by the caller.
458 @param[in, out] EventNumber The event number of the event just logged
459 @param[in] Flags Indicate additional flags. Only one flag has been
460 defined at this time, which is 0x01 and means the
461 extend operation should not be performed. All
462 other bits are reserved.
464 @retval EFI_SUCCESS Operation completed successfully.
465 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
471 IN EFI_TCG_PROTOCOL
*This
,
472 IN TCG_PCR_EVENT
*TCGLogData
,
473 IN OUT UINT32
*EventNumber
,
477 TCG_DXE_DATA
*TcgData
;
479 if (TCGLogData
== NULL
) {
480 return EFI_INVALID_PARAMETER
;
483 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
485 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
486 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))
526 return EFI_INVALID_PARAMETER
;
529 return Tpm12SubmitCommand (
530 TpmInputParameterBlockSize
,
531 TpmInputParameterBlock
,
532 &TpmOutputParameterBlockSize
,
533 TpmOutputParameterBlock
538 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
539 and add an entry to the Event Log.
541 @param[in] TcgData TCG_DXE_DATA structure.
542 @param[in] HashData Physical address of the start of the data buffer
543 to be hashed, extended, and logged.
544 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
545 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
546 @param[in] NewEventData Pointer to the new event data.
548 @retval EFI_SUCCESS Operation completed successfully.
549 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
550 @retval EFI_DEVICE_ERROR The command was unsuccessful.
555 TcgDxeHashLogExtendEventI (
556 IN TCG_DXE_DATA
*TcgData
,
558 IN UINT64 HashDataLen
,
559 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
560 IN UINT8
*NewEventData
565 if (!TcgData
->BsCap
.TPMPresentFlag
) {
566 return EFI_DEVICE_ERROR
;
569 if ((HashDataLen
> 0) || (HashData
!= NULL
)) {
570 Status
= TpmCommHashAll (
575 if (EFI_ERROR (Status
)) {
576 DEBUG ((DEBUG_ERROR
, "TpmCommHashAll Failed. %x\n", Status
));
581 Status
= Tpm12Extend (
582 &NewEventHdr
->Digest
,
583 NewEventHdr
->PCRIndex
,
586 if (!EFI_ERROR (Status
)) {
587 Status
= TcgDxeLogEventI (TcgData
, NewEventHdr
, NewEventData
);
591 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
592 DEBUG ((DEBUG_ERROR
, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status
));
593 TcgData
->BsCap
.TPMPresentFlag
= FALSE
;
595 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
596 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
598 Status
= EFI_DEVICE_ERROR
;
605 This service abstracts the capability to do a hash operation on a data buffer,
606 extend a specific TPM PCR with the hash result, and add an entry to the Event Log
608 @param[in] This Indicates the calling context
609 @param[in] HashData Physical address of the start of the data buffer
610 to be hashed, extended, and logged.
611 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
612 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
613 @param[in, out] TCGLogData The physical address of the start of the data
614 buffer containing the TCG_PCR_EVENT data structure.
615 @param[in, out] EventNumber The event number of the event just logged.
616 @param[out] EventLogLastEntry Physical address of the first byte of the entry
617 just placed in the Event Log. If the Event Log was
618 empty when this function was called then this physical
619 address will be the same as the physical address of
620 the start of the Event Log.
622 @retval EFI_SUCCESS Operation completed successfully.
623 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
624 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
625 @retval EFI_DEVICE_ERROR The command was unsuccessful.
630 TcgDxeHashLogExtendEvent (
631 IN EFI_TCG_PROTOCOL
*This
,
632 IN EFI_PHYSICAL_ADDRESS HashData
,
633 IN UINT64 HashDataLen
,
634 IN TPM_ALGORITHM_ID AlgorithmId
,
635 IN OUT TCG_PCR_EVENT
*TCGLogData
,
636 IN OUT UINT32
*EventNumber
,
637 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
640 TCG_DXE_DATA
*TcgData
;
643 if ((TCGLogData
== NULL
) || (EventLogLastEntry
== NULL
)) {
644 return EFI_INVALID_PARAMETER
;
647 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
649 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
650 return EFI_DEVICE_ERROR
;
653 if (AlgorithmId
!= TPM_ALG_SHA
) {
654 return EFI_UNSUPPORTED
;
657 if ((HashData
== 0) && (HashDataLen
> 0)) {
658 return EFI_INVALID_PARAMETER
;
661 Status
= TcgDxeHashLogExtendEventI (
663 (UINT8
*)(UINTN
)HashData
,
665 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
669 if (!EFI_ERROR (Status
)) {
670 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TcgData
->LastEvent
;
676 TCG_DXE_DATA mTcgDxeData
= {
681 TcgDxePassThroughToTpm
,
682 TcgDxeHashLogExtendEvent
685 sizeof (mTcgDxeData
.BsCap
),
692 &mTcgClientAcpiTemplate
,
693 &mTcgServerAcpiTemplate
,
699 Initialize the Event Log and log events passed from the PEI phase.
701 @retval EFI_SUCCESS Operation completed successfully.
702 @retval EFI_OUT_OF_RESOURCES Out of memory.
712 TCG_PCR_EVENT
*TcgEvent
;
713 EFI_PEI_HOB_POINTERS GuidHob
;
714 EFI_PHYSICAL_ADDRESS Lasa
;
716 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
717 Lasa
= mTcgClientAcpiTemplate
.Lasa
;
719 Status
= gBS
->AllocatePages (
722 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
725 if (EFI_ERROR (Status
)) {
729 mTcgClientAcpiTemplate
.Lasa
= Lasa
;
731 // To initialize them as 0xFF is recommended
732 // because the OS can know the last entry for that.
734 SetMem ((VOID
*)(UINTN
)mTcgClientAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
735 mTcgClientAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
737 Lasa
= mTcgServerAcpiTemplate
.Lasa
;
739 Status
= gBS
->AllocatePages (
742 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
745 if (EFI_ERROR (Status
)) {
749 mTcgServerAcpiTemplate
.Lasa
= Lasa
;
751 // To initialize them as 0xFF is recommended
752 // because the OS can know the last entry for that.
754 SetMem ((VOID
*)(UINTN
)mTcgServerAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
755 mTcgServerAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
758 GuidHob
.Raw
= GetHobList ();
759 while (!EFI_ERROR (Status
) &&
760 (GuidHob
.Raw
= GetNextGuidHob (&gTcgEventEntryHobGuid
, GuidHob
.Raw
)) != NULL
)
762 TcgEvent
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
763 GuidHob
.Raw
= GET_NEXT_HOB (GuidHob
);
764 Status
= TcgDxeLogEventI (
766 (TCG_PCR_EVENT_HDR
*)TcgEvent
,
775 Measure and log an action string, and extend the measurement result into PCR[5].
777 @param[in] String A specific string that indicates an Action event.
779 @retval EFI_SUCCESS Operation completed successfully.
780 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
789 TCG_PCR_EVENT_HDR TcgEvent
;
791 TcgEvent
.PCRIndex
= 5;
792 TcgEvent
.EventType
= EV_EFI_ACTION
;
793 TcgEvent
.EventSize
= (UINT32
)AsciiStrLen (String
);
794 return TcgDxeHashLogExtendEventI (
804 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
806 @retval EFI_SUCCESS Operation completed successfully.
807 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
812 MeasureHandoffTables (
817 TCG_PCR_EVENT_HDR TcgEvent
;
818 EFI_HANDOFF_TABLE_POINTERS HandoffTables
;
820 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
822 ProcessorLocBuf
= NULL
;
823 Status
= EFI_SUCCESS
;
825 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_SERVER
) {
828 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
830 Status
= GetProcessorsCpuLocation (&ProcessorLocBuf
, &ProcessorNum
);
832 if (!EFI_ERROR (Status
)) {
833 TcgEvent
.PCRIndex
= 1;
834 TcgEvent
.EventType
= EV_TABLE_OF_DEVICES
;
835 TcgEvent
.EventSize
= sizeof (HandoffTables
);
837 HandoffTables
.NumberOfTables
= 1;
838 HandoffTables
.TableEntry
[0].VendorGuid
= gEfiMpServiceProtocolGuid
;
839 HandoffTables
.TableEntry
[0].VendorTable
= ProcessorLocBuf
;
841 Status
= TcgDxeHashLogExtendEventI (
843 (UINT8
*)(UINTN
)ProcessorLocBuf
,
844 sizeof (EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
846 (UINT8
*)&HandoffTables
849 FreePool (ProcessorLocBuf
);
857 Measure and log Separator event, and extend the measurement result into a specific PCR.
859 @param[in] PCRIndex PCR index.
861 @retval EFI_SUCCESS Operation completed successfully.
862 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
867 MeasureSeparatorEvent (
868 IN TPM_PCRINDEX PCRIndex
871 TCG_PCR_EVENT_HDR TcgEvent
;
875 TcgEvent
.PCRIndex
= PCRIndex
;
876 TcgEvent
.EventType
= EV_SEPARATOR
;
877 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
878 return TcgDxeHashLogExtendEventI (
888 Read an EFI Variable.
890 This function allocates a buffer to return the contents of the variable. The caller is
891 responsible for freeing the buffer.
893 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
894 @param[in] VendorGuid A unique identifier for the vendor.
895 @param[out] VarSize The size of the variable data.
897 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
904 IN EFI_GUID
*VendorGuid
,
912 Status
= gRT
->GetVariable (
919 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
923 VarData
= AllocatePool (*VarSize
);
924 if (VarData
!= NULL
) {
925 Status
= gRT
->GetVariable (
932 if (EFI_ERROR (Status
)) {
943 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
945 @param[in] PCRIndex PCR Index.
946 @param[in] EventType Event type.
947 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
948 @param[in] VendorGuid A unique identifier for the vendor.
949 @param[in] VarData The content of the variable data.
950 @param[in] VarSize The size of the variable data.
952 @retval EFI_SUCCESS Operation completed successfully.
953 @retval EFI_OUT_OF_RESOURCES Out of memory.
954 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
960 IN TPM_PCRINDEX PCRIndex
,
961 IN TCG_EVENTTYPE EventType
,
963 IN EFI_GUID
*VendorGuid
,
969 TCG_PCR_EVENT_HDR TcgEvent
;
971 EFI_VARIABLE_DATA
*VarLog
;
973 VarNameLength
= StrLen (VarName
);
974 TcgEvent
.PCRIndex
= PCRIndex
;
975 TcgEvent
.EventType
= EventType
;
976 TcgEvent
.EventSize
= (UINT32
)(sizeof (*VarLog
) + VarNameLength
* sizeof (*VarName
) + VarSize
977 - sizeof (VarLog
->UnicodeName
) - sizeof (VarLog
->VariableData
));
979 VarLog
= (EFI_VARIABLE_DATA
*)AllocatePool (TcgEvent
.EventSize
);
980 if (VarLog
== NULL
) {
981 return EFI_OUT_OF_RESOURCES
;
984 VarLog
->VariableName
= *VendorGuid
;
985 VarLog
->UnicodeNameLength
= VarNameLength
;
986 VarLog
->VariableDataLength
= VarSize
;
990 VarNameLength
* sizeof (*VarName
)
993 (CHAR16
*)VarLog
->UnicodeName
+ VarNameLength
,
998 Status
= TcgDxeHashLogExtendEventI (
1010 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
1012 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
1013 @param[in] VendorGuid A unique identifier for the vendor.
1014 @param[out] VarSize The size of the variable data.
1015 @param[out] VarData Pointer to the content of the variable.
1017 @retval EFI_SUCCESS Operation completed successfully.
1018 @retval EFI_OUT_OF_RESOURCES Out of memory.
1019 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1024 ReadAndMeasureBootVariable (
1026 IN EFI_GUID
*VendorGuid
,
1033 *VarData
= ReadVariable (VarName
, VendorGuid
, VarSize
);
1034 if (*VarData
== NULL
) {
1035 return EFI_NOT_FOUND
;
1038 Status
= MeasureVariable (
1040 EV_EFI_VARIABLE_BOOT
,
1050 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
1052 The EFI boot variables are BootOrder and Boot#### variables.
1054 @retval EFI_SUCCESS Operation completed successfully.
1055 @retval EFI_OUT_OF_RESOURCES Out of memory.
1056 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1061 MeasureAllBootVariables (
1072 Status
= ReadAndMeasureBootVariable (
1074 &gEfiGlobalVariableGuid
,
1078 if ((Status
== EFI_NOT_FOUND
) || (BootOrder
== NULL
)) {
1082 if (EFI_ERROR (Status
)) {
1084 // BootOrder can't be NULL if status is not EFI_NOT_FOUND
1086 FreePool (BootOrder
);
1090 BootCount
/= sizeof (*BootOrder
);
1091 for (Index
= 0; Index
< BootCount
; Index
++) {
1092 UnicodeSPrint (mBootVarName
, sizeof (mBootVarName
), L
"Boot%04x", BootOrder
[Index
]);
1093 Status
= ReadAndMeasureBootVariable (
1095 &gEfiGlobalVariableGuid
,
1099 if (!EFI_ERROR (Status
)) {
1100 FreePool (BootVarData
);
1104 FreePool (BootOrder
);
1109 Ready to Boot Event notification handler.
1111 Sequence of OS boot events is measured in this event notification handler.
1113 @param[in] Event Event whose notification function is being invoked
1114 @param[in] Context Pointer to the notification function's context
1125 TPM_PCRINDEX PcrIndex
;
1127 if (mBootAttempts
== 0) {
1129 // Measure handoff tables.
1131 Status
= MeasureHandoffTables ();
1132 if (EFI_ERROR (Status
)) {
1133 DEBUG ((DEBUG_ERROR
, "HOBs not Measured. Error!\n"));
1137 // Measure BootOrder & Boot#### variables.
1139 Status
= MeasureAllBootVariables ();
1140 if (EFI_ERROR (Status
)) {
1141 DEBUG ((DEBUG_ERROR
, "Boot Variables not Measured. Error!\n"));
1145 // 1. This is the first boot attempt.
1147 Status
= TcgMeasureAction (
1148 EFI_CALLING_EFI_APPLICATION
1150 if (EFI_ERROR (Status
)) {
1151 DEBUG ((DEBUG_ERROR
, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION
));
1155 // 2. Draw a line between pre-boot env and entering post-boot env.
1157 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1158 Status
= MeasureSeparatorEvent (PcrIndex
);
1159 if (EFI_ERROR (Status
)) {
1160 DEBUG ((DEBUG_ERROR
, "Separator Event not Measured. Error!\n"));
1165 // 3. Measure GPT. It would be done in SAP driver.
1169 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
1173 // 5. Read & Measure variable. BootOrder already measured.
1177 // 6. Not first attempt, meaning a return from last attempt
1179 Status
= TcgMeasureAction (
1180 EFI_RETURNING_FROM_EFI_APPLICATION
1182 if (EFI_ERROR (Status
)) {
1183 DEBUG ((DEBUG_ERROR
, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION
));
1187 DEBUG ((DEBUG_INFO
, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
1189 // Increase boot attempt counter.
1195 Install TCG ACPI Table when ACPI Table Protocol is available.
1197 A system's firmware uses an ACPI table to identify the system's TCG capabilities
1198 to the Post-Boot environment. The information in this ACPI table is not guaranteed
1199 to be valid until the Host Platform transitions from pre-boot state to post-boot state.
1201 @param[in] Event Event whose notification function is being invoked
1202 @param[in] Context Pointer to the notification function's context
1213 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
1217 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**)&AcpiTable
);
1218 if (EFI_ERROR (Status
)) {
1222 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
1223 CopyMem (mTcgClientAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgClientAcpiTemplate
.Header
.OemId
));
1224 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1225 CopyMem (&mTcgClientAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1226 mTcgClientAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1227 mTcgClientAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1228 mTcgClientAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1230 // The ACPI table must be checksummed before calling the InstallAcpiTable()
1231 // service of the ACPI table protocol to install it.
1233 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgClientAcpiTemplate
, sizeof (mTcgClientAcpiTemplate
));
1234 mTcgClientAcpiTemplate
.Header
.Checksum
= Checksum
;
1236 Status
= AcpiTable
->InstallAcpiTable (
1238 &mTcgClientAcpiTemplate
,
1239 sizeof (mTcgClientAcpiTemplate
),
1243 CopyMem (mTcgServerAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgServerAcpiTemplate
.Header
.OemId
));
1244 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1245 CopyMem (&mTcgServerAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1246 mTcgServerAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1247 mTcgServerAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1248 mTcgServerAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1250 // The ACPI table must be checksummed before calling the InstallAcpiTable()
1251 // service of the ACPI table protocol to install it.
1253 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgServerAcpiTemplate
, sizeof (mTcgServerAcpiTemplate
));
1254 mTcgServerAcpiTemplate
.Header
.Checksum
= Checksum
;
1256 mTcgServerAcpiTemplate
.BaseAddress
.Address
= PcdGet64 (PcdTpmBaseAddress
);
1257 Status
= AcpiTable
->InstallAcpiTable (
1259 &mTcgServerAcpiTemplate
,
1260 sizeof (mTcgServerAcpiTemplate
),
1265 if (EFI_ERROR (Status
)) {
1266 DEBUG ((DEBUG_ERROR
, "Tcg Acpi Table installation failure"));
1271 Exit Boot Services Event notification handler.
1273 Measure invocation and success of ExitBootServices.
1275 @param[in] Event Event whose notification function is being invoked
1276 @param[in] Context Pointer to the notification function's context
1281 OnExitBootServices (
1289 // Measure invocation of ExitBootServices,
1291 Status
= TcgMeasureAction (
1292 EFI_EXIT_BOOT_SERVICES_INVOCATION
1294 if (EFI_ERROR (Status
)) {
1295 DEBUG ((DEBUG_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION
));
1299 // Measure success of ExitBootServices
1301 Status
= TcgMeasureAction (
1302 EFI_EXIT_BOOT_SERVICES_SUCCEEDED
1304 if (EFI_ERROR (Status
)) {
1305 DEBUG ((DEBUG_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED
));
1310 Exit Boot Services Failed Event notification handler.
1312 Measure Failure of ExitBootServices.
1314 @param[in] Event Event whose notification function is being invoked
1315 @param[in] Context Pointer to the notification function's context
1320 OnExitBootServicesFailed (
1328 // Measure Failure of ExitBootServices,
1330 Status
= TcgMeasureAction (
1331 EFI_EXIT_BOOT_SERVICES_FAILED
1333 if (EFI_ERROR (Status
)) {
1334 DEBUG ((DEBUG_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED
));
1339 Get TPM Deactivated state.
1341 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
1343 @retval EFI_SUCCESS Operation completed successfully.
1344 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1349 OUT BOOLEAN
*TPMDeactivatedFlag
1353 TPM_STCLEAR_FLAGS VolatileFlags
;
1355 Status
= Tpm12GetCapabilityFlagVolatile (&VolatileFlags
);
1356 if (!EFI_ERROR (Status
)) {
1357 *TPMDeactivatedFlag
= VolatileFlags
.deactivated
;
1364 The driver's entry point.
1366 It publishes EFI TCG Protocol.
1368 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1369 @param[in] SystemTable A pointer to the EFI System Table.
1371 @retval EFI_SUCCESS The entry point is executed successfully.
1372 @retval other Some error occurs when executing this entry point.
1378 IN EFI_HANDLE ImageHandle
,
1379 IN EFI_SYSTEM_TABLE
*SystemTable
1386 if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)) {
1387 DEBUG ((DEBUG_ERROR
, "No TPM12 instance required!\n"));
1388 return EFI_UNSUPPORTED
;
1391 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1392 DEBUG ((DEBUG_ERROR
, "TPM error!\n"));
1393 return EFI_DEVICE_ERROR
;
1396 Status
= Tpm12RequestUseTpm ();
1397 if (EFI_ERROR (Status
)) {
1398 DEBUG ((DEBUG_ERROR
, "TPM not detected!\n"));
1402 Status
= GetTpmStatus (&mTcgDxeData
.BsCap
.TPMDeactivatedFlag
);
1403 if (EFI_ERROR (Status
)) {
1406 "DriverEntry: TPM not working properly\n"
1411 Status
= gBS
->InstallProtocolInterface (
1413 &gEfiTcgProtocolGuid
,
1414 EFI_NATIVE_INTERFACE
,
1415 &mTcgDxeData
.TcgProtocol
1417 if (!EFI_ERROR (Status
) && (!mTcgDxeData
.BsCap
.TPMDeactivatedFlag
) && mTcgDxeData
.BsCap
.TPMPresentFlag
) {
1419 // Setup the log area and copy event log from hob list to it
1421 Status
= SetupEventLog ();
1422 ASSERT_EFI_ERROR (Status
);
1425 // Measure handoff tables, Boot#### variables etc.
1427 Status
= EfiCreateEventReadyToBootEx (
1434 Status
= gBS
->CreateEventEx (
1439 &gEfiEventExitBootServicesGuid
,
1444 // Measure Exit Boot Service failed
1446 Status
= gBS
->CreateEventEx (
1449 OnExitBootServicesFailed
,
1451 &gEventExitBootServicesFailedGuid
,
1457 // Install ACPI Table
1459 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid
, TPL_CALLBACK
, InstallAcpiTable
, NULL
, &Registration
);