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 - 2016, Intel Corporation. All rights reserved.<BR>
12 This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 #include <IndustryStandard/Tpm12.h>
24 #include <IndustryStandard/Acpi.h>
25 #include <IndustryStandard/PeImage.h>
26 #include <IndustryStandard/TcpaAcpi.h>
28 #include <Guid/GlobalVariable.h>
29 #include <Guid/HobList.h>
30 #include <Guid/TcgEventHob.h>
31 #include <Guid/EventGroup.h>
32 #include <Guid/EventExitBootServiceFailed.h>
33 #include <Guid/TpmInstance.h>
35 #include <Protocol/DevicePath.h>
36 #include <Protocol/TcgService.h>
37 #include <Protocol/AcpiTable.h>
38 #include <Protocol/MpService.h>
40 #include <Library/DebugLib.h>
41 #include <Library/BaseMemoryLib.h>
42 #include <Library/UefiRuntimeServicesTableLib.h>
43 #include <Library/UefiDriverEntryPoint.h>
44 #include <Library/HobLib.h>
45 #include <Library/UefiBootServicesTableLib.h>
46 #include <Library/BaseLib.h>
47 #include <Library/MemoryAllocationLib.h>
48 #include <Library/PrintLib.h>
49 #include <Library/Tpm12DeviceLib.h>
50 #include <Library/PcdLib.h>
51 #include <Library/UefiLib.h>
52 #include <Library/ReportStatusCodeLib.h>
53 #include <Library/Tpm12CommandLib.h>
54 #include <Library/BaseCryptLib.h>
56 #define TCG_DXE_DATA_FROM_THIS(this) \
57 BASE_CR (this, TCG_DXE_DATA, TcgProtocol)
59 typedef struct _TCG_DXE_DATA
{
60 EFI_TCG_PROTOCOL TcgProtocol
;
61 TCG_EFI_BOOT_SERVICE_CAPABILITY BsCap
;
62 EFI_TCG_CLIENT_ACPI_TABLE
*TcgClientAcpiTable
;
63 EFI_TCG_SERVER_ACPI_TABLE
*TcgServerAcpiTable
;
70 EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate
= {
72 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
73 sizeof (mTcgClientAcpiTemplate
),
76 // Compiler initializes the remaining bytes to 0
77 // These fields should be filled in in production
80 0, // 0 for PC Client Platform Class
81 0, // Log Area Max Length
82 (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1) // Log Area Start Address
86 // The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
87 // the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,
88 // this _UID can be changed and should match with the _UID setting of the TPM
91 EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate
= {
93 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
94 sizeof (mTcgServerAcpiTemplate
),
97 // Compiler initializes the remaining bytes to 0
98 // These fields should be filled in in production
101 1, // 1 for Server Platform Class
103 0, // Log Area Max Length
104 (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1), // Log Area Start Address
105 0x0100, // TCG Specification revision 1.0
107 0, // Interrupt Flags
109 {0}, // Reserved 3 bytes
110 0, // Global System Interrupt
112 EFI_ACPI_3_0_SYSTEM_MEMORY
,
119 {0}, // Configuration Address
120 0xFF, // ACPI _UID value of the device, can be changed for different platforms
121 0, // ACPI _UID value of the device, can be changed for different platforms
122 0, // ACPI _UID value of the device, can be changed for different platforms
123 0 // ACPI _UID value of the device, can be changed for different platforms
126 UINTN mBootAttempts
= 0;
127 CHAR16 mBootVarName
[] = L
"BootOrder";
130 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
131 Caller is responsible to free LocationBuf.
133 @param[out] LocationBuf Returns Processor Location Buffer.
134 @param[out] Num Returns processor number.
136 @retval EFI_SUCCESS Operation completed successfully.
137 @retval EFI_UNSUPPORTED MpService protocol not found.
141 GetProcessorsCpuLocation (
142 OUT EFI_CPU_PHYSICAL_LOCATION
**LocationBuf
,
147 EFI_MP_SERVICES_PROTOCOL
*MpProtocol
;
149 UINTN EnabledProcessorNum
;
150 EFI_PROCESSOR_INFORMATION ProcessorInfo
;
151 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
154 Status
= gBS
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**) &MpProtocol
);
155 if (EFI_ERROR (Status
)) {
157 // MP protocol is not installed
159 return EFI_UNSUPPORTED
;
162 Status
= MpProtocol
->GetNumberOfProcessors(
167 if (EFI_ERROR(Status
)){
171 Status
= gBS
->AllocatePool(
173 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
174 (VOID
**) &ProcessorLocBuf
176 if (EFI_ERROR(Status
)){
181 // Get each processor Location info
183 for (Index
= 0; Index
< ProcessorNum
; Index
++) {
184 Status
= MpProtocol
->GetProcessorInfo(
189 if (EFI_ERROR(Status
)){
190 FreePool(ProcessorLocBuf
);
195 // Get all Processor Location info & measure
198 &ProcessorLocBuf
[Index
],
199 &ProcessorInfo
.Location
,
200 sizeof(EFI_CPU_PHYSICAL_LOCATION
)
204 *LocationBuf
= ProcessorLocBuf
;
211 This service provides EFI protocol capability information, state information
212 about the TPM, and Event Log state information.
214 @param[in] This Indicates the calling context
215 @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
216 structure and fills in the fields with the EFI protocol
217 capability information and the current TPM state information.
218 @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature
219 flags are currently defined so this parameter
220 MUST be set to 0. However, in the future,
221 feature flags may be defined that, for example,
222 enable hash algorithm agility.
223 @param[out] EventLogLocation This is a pointer to the address of the event log in memory.
224 @param[out] EventLogLastEntry If the Event Log contains more than one entry,
225 this is a pointer to the address of the start of
226 the last entry in the event log in memory.
228 @retval EFI_SUCCESS Operation completed successfully.
229 @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.
235 IN EFI_TCG_PROTOCOL
*This
,
236 OUT TCG_EFI_BOOT_SERVICE_CAPABILITY
*ProtocolCapability
,
237 OUT UINT32
*TCGFeatureFlags
,
238 OUT EFI_PHYSICAL_ADDRESS
*EventLogLocation
,
239 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
242 TCG_DXE_DATA
*TcgData
;
244 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
246 if (ProtocolCapability
!= NULL
) {
247 *ProtocolCapability
= TcgData
->BsCap
;
250 if (TCGFeatureFlags
!= NULL
) {
251 *TCGFeatureFlags
= 0;
254 if (EventLogLocation
!= NULL
) {
255 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
256 *EventLogLocation
= TcgData
->TcgClientAcpiTable
->Lasa
;
258 *EventLogLocation
= TcgData
->TcgServerAcpiTable
->Lasa
;
262 if (EventLogLastEntry
!= NULL
) {
263 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
264 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)0;
266 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TcgData
->LastEvent
;
274 Single function calculates SHA1 digest value for all raw data. It
275 combines Sha1Init(), Sha1Update() and Sha1Final().
277 @param[in] Data Raw data to be digested.
278 @param[in] DataLen Size of the raw data.
279 @param[out] Digest Pointer to a buffer that stores the final digest.
281 @retval EFI_SUCCESS Always successfully calculate the final digest.
286 IN CONST UINT8
*Data
,
288 OUT TPM_DIGEST
*Digest
294 CtxSize
= Sha1GetContextSize ();
295 Sha1Ctx
= AllocatePool (CtxSize
);
296 ASSERT (Sha1Ctx
!= NULL
);
299 Sha1Update (Sha1Ctx
, Data
, DataLen
);
300 Sha1Final (Sha1Ctx
, (UINT8
*)Digest
);
308 This service abstracts the capability to do a hash operation on a data buffer.
310 @param[in] This Indicates the calling context
311 @param[in] HashData Pointer to the data buffer to be hashed
312 @param[in] HashDataLen Length of the data buffer to be hashed
313 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
314 @param[in, out] HashedDataLen Resultant length of the hashed data
315 @param[in, out] HashedDataResult Resultant buffer of the hashed data
317 @retval EFI_SUCCESS Operation completed successfully.
318 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
319 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
320 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
321 @retval EFI_UNSUPPORTED AlgorithmId not supported.
322 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
328 IN EFI_TCG_PROTOCOL
*This
,
330 IN UINT64 HashDataLen
,
331 IN TCG_ALGORITHM_ID AlgorithmId
,
332 IN OUT UINT64
*HashedDataLen
,
333 IN OUT UINT8
**HashedDataResult
336 if (HashedDataLen
== NULL
|| HashedDataResult
== NULL
) {
337 return EFI_INVALID_PARAMETER
;
340 switch (AlgorithmId
) {
342 if (*HashedDataLen
== 0) {
343 *HashedDataLen
= sizeof (TPM_DIGEST
);
344 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
345 if (*HashedDataResult
== NULL
) {
346 return EFI_OUT_OF_RESOURCES
;
350 if (*HashedDataLen
< sizeof (TPM_DIGEST
)) {
351 *HashedDataLen
= sizeof (TPM_DIGEST
);
352 return EFI_BUFFER_TOO_SMALL
;
354 *HashedDataLen
= sizeof (TPM_DIGEST
);
356 if (*HashedDataResult
== NULL
) {
357 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
360 return TpmCommHashAll (
363 (TPM_DIGEST
*)*HashedDataResult
366 return EFI_UNSUPPORTED
;
371 Add a new entry to the Event Log.
373 @param[in, out] EventLogPtr Pointer to the Event Log data.
374 @param[in, out] LogSize Size of the Event Log.
375 @param[in] MaxSize Maximum size of the Event Log.
376 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
377 @param[in] NewEventData Pointer to the new event data.
379 @retval EFI_SUCCESS The new event log entry was added.
380 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
385 IN OUT UINT8
**EventLogPtr
,
386 IN OUT UINTN
*LogSize
,
388 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
389 IN UINT8
*NewEventData
395 // Prevent Event Overflow
397 if (NewEventHdr
->EventSize
> (UINTN
)(~0) - sizeof (*NewEventHdr
)) {
398 return EFI_OUT_OF_RESOURCES
;
401 NewLogSize
= sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
;
402 if (NewLogSize
> MaxSize
- *LogSize
) {
403 return EFI_OUT_OF_RESOURCES
;
406 *EventLogPtr
+= *LogSize
;
407 *LogSize
+= NewLogSize
;
408 CopyMem (*EventLogPtr
, NewEventHdr
, sizeof (*NewEventHdr
));
410 *EventLogPtr
+ sizeof (*NewEventHdr
),
412 NewEventHdr
->EventSize
418 Add a new entry to the Event Log.
420 @param[in] TcgData TCG_DXE_DATA structure.
421 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
422 @param[in] NewEventData Pointer to the new event data.
424 @retval EFI_SUCCESS The new event log entry was added.
425 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
431 IN TCG_DXE_DATA
*TcgData
,
432 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
433 IN UINT8
*NewEventData
436 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
437 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgClientAcpiTable
->Lasa
;
438 return TpmCommLogEvent (
440 &TcgData
->EventLogSize
,
441 (UINTN
)TcgData
->TcgClientAcpiTable
->Laml
,
446 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgServerAcpiTable
->Lasa
;
447 return TpmCommLogEvent (
449 &TcgData
->EventLogSize
,
450 (UINTN
)TcgData
->TcgServerAcpiTable
->Laml
,
458 This service abstracts the capability to add an entry to the Event Log.
460 @param[in] This Indicates the calling context
461 @param[in] TCGLogData Pointer to the start of the data buffer containing
462 the TCG_PCR_EVENT data structure. All fields in
463 this structure are properly filled by the caller.
464 @param[in, out] EventNumber The event number of the event just logged
465 @param[in] Flags Indicate additional flags. Only one flag has been
466 defined at this time, which is 0x01 and means the
467 extend operation should not be performed. All
468 other bits are reserved.
470 @retval EFI_SUCCESS Operation completed successfully.
471 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
477 IN EFI_TCG_PROTOCOL
*This
,
478 IN TCG_PCR_EVENT
*TCGLogData
,
479 IN OUT UINT32
*EventNumber
,
483 TCG_DXE_DATA
*TcgData
;
485 if (TCGLogData
== NULL
){
486 return EFI_INVALID_PARAMETER
;
489 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
491 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
492 return EFI_DEVICE_ERROR
;
494 return TcgDxeLogEventI (
496 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
502 This service is a proxy for commands to the TPM.
504 @param[in] This Indicates the calling context
505 @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block
506 @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block
507 @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block
508 @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block
510 @retval EFI_SUCCESS Operation completed successfully.
511 @retval EFI_INVALID_PARAMETER Invalid ordinal.
512 @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.
513 @retval EFI_TIMEOUT The TIS timed-out.
518 TcgDxePassThroughToTpm (
519 IN EFI_TCG_PROTOCOL
*This
,
520 IN UINT32 TpmInputParameterBlockSize
,
521 IN UINT8
*TpmInputParameterBlock
,
522 IN UINT32 TpmOutputParameterBlockSize
,
523 IN UINT8
*TpmOutputParameterBlock
526 if (TpmInputParameterBlock
== NULL
||
527 TpmOutputParameterBlock
== NULL
||
528 TpmInputParameterBlockSize
== 0 ||
529 TpmOutputParameterBlockSize
== 0) {
530 return EFI_INVALID_PARAMETER
;
533 return Tpm12SubmitCommand (
534 TpmInputParameterBlockSize
,
535 TpmInputParameterBlock
,
536 &TpmOutputParameterBlockSize
,
537 TpmOutputParameterBlock
542 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
543 and add an entry to the Event Log.
545 @param[in] TcgData TCG_DXE_DATA structure.
546 @param[in] HashData Physical address of the start of the data buffer
547 to be hashed, extended, and logged.
548 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
549 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
550 @param[in] NewEventData Pointer to the new event data.
552 @retval EFI_SUCCESS Operation completed successfully.
553 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
554 @retval EFI_DEVICE_ERROR The command was unsuccessful.
559 TcgDxeHashLogExtendEventI (
560 IN TCG_DXE_DATA
*TcgData
,
562 IN UINT64 HashDataLen
,
563 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
564 IN UINT8
*NewEventData
569 if (!TcgData
->BsCap
.TPMPresentFlag
) {
570 return EFI_DEVICE_ERROR
;
573 if (HashDataLen
> 0 || HashData
!= NULL
) {
574 Status
= TpmCommHashAll (
579 if (EFI_ERROR(Status
)) {
580 DEBUG ((DEBUG_ERROR
, "TpmCommHashAll Failed. %x\n", Status
));
585 Status
= Tpm12Extend (
586 &NewEventHdr
->Digest
,
587 NewEventHdr
->PCRIndex
,
590 if (!EFI_ERROR (Status
)) {
591 Status
= TcgDxeLogEventI (TcgData
, NewEventHdr
, NewEventData
);
595 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
596 DEBUG ((EFI_D_ERROR
, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status
));
597 TcgData
->BsCap
.TPMPresentFlag
= FALSE
;
599 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
600 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
602 Status
= EFI_DEVICE_ERROR
;
609 This service abstracts the capability to do a hash operation on a data buffer,
610 extend a specific TPM PCR with the hash result, and add an entry to the Event Log
612 @param[in] This Indicates the calling context
613 @param[in] HashData Physical address of the start of the data buffer
614 to be hashed, extended, and logged.
615 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
616 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
617 @param[in, out] TCGLogData The physical address of the start of the data
618 buffer containing the TCG_PCR_EVENT data structure.
619 @param[in, out] EventNumber The event number of the event just logged.
620 @param[out] EventLogLastEntry Physical address of the first byte of the entry
621 just placed in the Event Log. If the Event Log was
622 empty when this function was called then this physical
623 address will be the same as the physical address of
624 the start of the Event Log.
626 @retval EFI_SUCCESS Operation completed successfully.
627 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
628 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
629 @retval EFI_DEVICE_ERROR The command was unsuccessful.
634 TcgDxeHashLogExtendEvent (
635 IN EFI_TCG_PROTOCOL
*This
,
636 IN EFI_PHYSICAL_ADDRESS HashData
,
637 IN UINT64 HashDataLen
,
638 IN TPM_ALGORITHM_ID AlgorithmId
,
639 IN OUT TCG_PCR_EVENT
*TCGLogData
,
640 IN OUT UINT32
*EventNumber
,
641 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
644 TCG_DXE_DATA
*TcgData
;
647 if (TCGLogData
== NULL
|| EventLogLastEntry
== NULL
){
648 return EFI_INVALID_PARAMETER
;
651 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
653 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
654 return EFI_DEVICE_ERROR
;
657 if (AlgorithmId
!= TPM_ALG_SHA
) {
658 return EFI_UNSUPPORTED
;
661 if (HashData
== 0 && HashDataLen
> 0) {
662 return EFI_INVALID_PARAMETER
;
665 Status
= TcgDxeHashLogExtendEventI (
667 (UINT8
*) (UINTN
) HashData
,
669 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
673 if (!EFI_ERROR(Status
)){
674 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) TcgData
->LastEvent
;
680 TCG_DXE_DATA mTcgDxeData
= {
685 TcgDxePassThroughToTpm
,
686 TcgDxeHashLogExtendEvent
689 sizeof (mTcgDxeData
.BsCap
),
696 &mTcgClientAcpiTemplate
,
697 &mTcgServerAcpiTemplate
,
703 Initialize the Event Log and log events passed from the PEI phase.
705 @retval EFI_SUCCESS Operation completed successfully.
706 @retval EFI_OUT_OF_RESOURCES Out of memory.
716 TCG_PCR_EVENT
*TcgEvent
;
717 EFI_PEI_HOB_POINTERS GuidHob
;
718 EFI_PHYSICAL_ADDRESS Lasa
;
720 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
721 Lasa
= mTcgClientAcpiTemplate
.Lasa
;
723 Status
= gBS
->AllocatePages (
726 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
729 if (EFI_ERROR (Status
)) {
732 mTcgClientAcpiTemplate
.Lasa
= Lasa
;
734 // To initialize them as 0xFF is recommended
735 // because the OS can know the last entry for that.
737 SetMem ((VOID
*)(UINTN
)mTcgClientAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
738 mTcgClientAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
741 Lasa
= mTcgServerAcpiTemplate
.Lasa
;
743 Status
= gBS
->AllocatePages (
746 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
749 if (EFI_ERROR (Status
)) {
752 mTcgServerAcpiTemplate
.Lasa
= Lasa
;
754 // To initialize them as 0xFF is recommended
755 // because the OS can know the last entry for that.
757 SetMem ((VOID
*)(UINTN
)mTcgServerAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
758 mTcgServerAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
761 GuidHob
.Raw
= GetHobList ();
762 while (!EFI_ERROR (Status
) &&
763 (GuidHob
.Raw
= GetNextGuidHob (&gTcgEventEntryHobGuid
, GuidHob
.Raw
)) != NULL
) {
764 TcgEvent
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
765 GuidHob
.Raw
= GET_NEXT_HOB (GuidHob
);
766 Status
= TcgDxeLogEventI (
768 (TCG_PCR_EVENT_HDR
*)TcgEvent
,
777 Measure and log an action string, and extend the measurement result into PCR[5].
779 @param[in] String A specific string that indicates an Action event.
781 @retval EFI_SUCCESS Operation completed successfully.
782 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
791 TCG_PCR_EVENT_HDR TcgEvent
;
793 TcgEvent
.PCRIndex
= 5;
794 TcgEvent
.EventType
= EV_EFI_ACTION
;
795 TcgEvent
.EventSize
= (UINT32
)AsciiStrLen (String
);
796 return TcgDxeHashLogExtendEventI (
806 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
808 @retval EFI_SUCCESS Operation completed successfully.
809 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
814 MeasureHandoffTables (
819 TCG_PCR_EVENT_HDR TcgEvent
;
820 EFI_HANDOFF_TABLE_POINTERS HandoffTables
;
822 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
824 ProcessorLocBuf
= NULL
;
825 Status
= EFI_SUCCESS
;
827 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_SERVER
) {
830 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
832 Status
= GetProcessorsCpuLocation(&ProcessorLocBuf
, &ProcessorNum
);
834 if (!EFI_ERROR(Status
)){
835 TcgEvent
.PCRIndex
= 1;
836 TcgEvent
.EventType
= EV_TABLE_OF_DEVICES
;
837 TcgEvent
.EventSize
= sizeof (HandoffTables
);
839 HandoffTables
.NumberOfTables
= 1;
840 HandoffTables
.TableEntry
[0].VendorGuid
= gEfiMpServiceProtocolGuid
;
841 HandoffTables
.TableEntry
[0].VendorTable
= ProcessorLocBuf
;
843 Status
= TcgDxeHashLogExtendEventI (
845 (UINT8
*)(UINTN
)ProcessorLocBuf
,
846 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
848 (UINT8
*)&HandoffTables
851 FreePool(ProcessorLocBuf
);
859 Measure and log Separator event, and extend the measurement result into a specific PCR.
861 @param[in] PCRIndex PCR index.
863 @retval EFI_SUCCESS Operation completed successfully.
864 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
869 MeasureSeparatorEvent (
870 IN TPM_PCRINDEX PCRIndex
873 TCG_PCR_EVENT_HDR TcgEvent
;
877 TcgEvent
.PCRIndex
= PCRIndex
;
878 TcgEvent
.EventType
= EV_SEPARATOR
;
879 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
880 return TcgDxeHashLogExtendEventI (
890 Read an EFI Variable.
892 This function allocates a buffer to return the contents of the variable. The caller is
893 responsible for freeing the buffer.
895 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
896 @param[in] VendorGuid A unique identifier for the vendor.
897 @param[out] VarSize The size of the variable data.
899 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
906 IN EFI_GUID
*VendorGuid
,
914 Status
= gRT
->GetVariable (
921 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
925 VarData
= AllocatePool (*VarSize
);
926 if (VarData
!= NULL
) {
927 Status
= gRT
->GetVariable (
934 if (EFI_ERROR (Status
)) {
944 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
946 @param[in] PCRIndex PCR Index.
947 @param[in] EventType Event type.
948 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
949 @param[in] VendorGuid A unique identifier for the vendor.
950 @param[in] VarData The content of the variable data.
951 @param[in] VarSize The size of the variable data.
953 @retval EFI_SUCCESS Operation completed successfully.
954 @retval EFI_OUT_OF_RESOURCES Out of memory.
955 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
961 IN TPM_PCRINDEX PCRIndex
,
962 IN TCG_EVENTTYPE EventType
,
964 IN EFI_GUID
*VendorGuid
,
970 TCG_PCR_EVENT_HDR TcgEvent
;
972 EFI_VARIABLE_DATA
*VarLog
;
974 VarNameLength
= StrLen (VarName
);
975 TcgEvent
.PCRIndex
= PCRIndex
;
976 TcgEvent
.EventType
= EventType
;
977 TcgEvent
.EventSize
= (UINT32
)(sizeof (*VarLog
) + VarNameLength
* sizeof (*VarName
) + VarSize
978 - sizeof (VarLog
->UnicodeName
) - sizeof (VarLog
->VariableData
));
980 VarLog
= (EFI_VARIABLE_DATA
*)AllocatePool (TcgEvent
.EventSize
);
981 if (VarLog
== NULL
) {
982 return EFI_OUT_OF_RESOURCES
;
985 VarLog
->VariableName
= *VendorGuid
;
986 VarLog
->UnicodeNameLength
= VarNameLength
;
987 VarLog
->VariableDataLength
= VarSize
;
991 VarNameLength
* sizeof (*VarName
)
994 (CHAR16
*)VarLog
->UnicodeName
+ VarNameLength
,
999 Status
= TcgDxeHashLogExtendEventI (
1011 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
1013 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
1014 @param[in] VendorGuid A unique identifier for the vendor.
1015 @param[out] VarSize The size of the variable data.
1016 @param[out] VarData Pointer to the content of the variable.
1018 @retval EFI_SUCCESS Operation completed successfully.
1019 @retval EFI_OUT_OF_RESOURCES Out of memory.
1020 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1025 ReadAndMeasureBootVariable (
1027 IN EFI_GUID
*VendorGuid
,
1034 *VarData
= ReadVariable (VarName
, VendorGuid
, VarSize
);
1035 if (*VarData
== NULL
) {
1036 return EFI_NOT_FOUND
;
1039 Status
= MeasureVariable (
1041 EV_EFI_VARIABLE_BOOT
,
1051 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
1053 The EFI boot variables are BootOrder and Boot#### variables.
1055 @retval EFI_SUCCESS Operation completed successfully.
1056 @retval EFI_OUT_OF_RESOURCES Out of memory.
1057 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1062 MeasureAllBootVariables (
1073 Status
= ReadAndMeasureBootVariable (
1075 &gEfiGlobalVariableGuid
,
1077 (VOID
**) &BootOrder
1079 if (Status
== EFI_NOT_FOUND
|| BootOrder
== NULL
) {
1083 if (EFI_ERROR (Status
)) {
1085 // BootOrder can't be NULL if status is not EFI_NOT_FOUND
1087 FreePool (BootOrder
);
1091 BootCount
/= sizeof (*BootOrder
);
1092 for (Index
= 0; Index
< BootCount
; Index
++) {
1093 UnicodeSPrint (mBootVarName
, sizeof (mBootVarName
), L
"Boot%04x", BootOrder
[Index
]);
1094 Status
= ReadAndMeasureBootVariable (
1096 &gEfiGlobalVariableGuid
,
1100 if (!EFI_ERROR (Status
)) {
1101 FreePool (BootVarData
);
1105 FreePool (BootOrder
);
1110 Ready to Boot Event notification handler.
1112 Sequence of OS boot events is measured in this event notification handler.
1114 @param[in] Event Event whose notification function is being invoked
1115 @param[in] Context Pointer to the notification function's context
1126 TPM_PCRINDEX PcrIndex
;
1128 if (mBootAttempts
== 0) {
1131 // Measure handoff tables.
1133 Status
= MeasureHandoffTables ();
1134 if (EFI_ERROR (Status
)) {
1135 DEBUG ((EFI_D_ERROR
, "HOBs not Measured. Error!\n"));
1139 // Measure BootOrder & Boot#### variables.
1141 Status
= MeasureAllBootVariables ();
1142 if (EFI_ERROR (Status
)) {
1143 DEBUG ((EFI_D_ERROR
, "Boot Variables not Measured. Error!\n"));
1147 // 1. This is the first boot attempt.
1149 Status
= TcgMeasureAction (
1150 EFI_CALLING_EFI_APPLICATION
1152 if (EFI_ERROR (Status
)) {
1153 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION
));
1157 // 2. Draw a line between pre-boot env and entering post-boot env.
1159 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1160 Status
= MeasureSeparatorEvent (PcrIndex
);
1161 if (EFI_ERROR (Status
)) {
1162 DEBUG ((EFI_D_ERROR
, "Seperator Event not Measured. Error!\n"));
1167 // 3. Measure GPT. It would be done in SAP driver.
1171 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
1175 // 5. Read & Measure variable. BootOrder already measured.
1179 // 6. Not first attempt, meaning a return from last attempt
1181 Status
= TcgMeasureAction (
1182 EFI_RETURNING_FROM_EFI_APPLICATOIN
1184 if (EFI_ERROR (Status
)) {
1185 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN
));
1189 DEBUG ((EFI_D_INFO
, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
1191 // Increase boot attempt counter.
1197 Install TCG ACPI Table when ACPI Table Protocol is available.
1199 A system's firmware uses an ACPI table to identify the system's TCG capabilities
1200 to the Post-Boot environment. The information in this ACPI table is not guaranteed
1201 to be valid until the Host Platform transitions from pre-boot state to post-boot state.
1203 @param[in] Event Event whose notification function is being invoked
1204 @param[in] Context Pointer to the notification function's context
1215 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
1219 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**)&AcpiTable
);
1220 if (EFI_ERROR (Status
)) {
1224 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
1225 CopyMem (mTcgClientAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgClientAcpiTemplate
.Header
.OemId
));
1226 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1227 CopyMem (&mTcgClientAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1228 mTcgClientAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1229 mTcgClientAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1230 mTcgClientAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1232 // The ACPI table must be checksumed before calling the InstallAcpiTable()
1233 // service of the ACPI table protocol to install it.
1235 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgClientAcpiTemplate
, sizeof (mTcgClientAcpiTemplate
));
1236 mTcgClientAcpiTemplate
.Header
.Checksum
= Checksum
;
1238 Status
= AcpiTable
->InstallAcpiTable (
1240 &mTcgClientAcpiTemplate
,
1241 sizeof (mTcgClientAcpiTemplate
),
1245 CopyMem (mTcgServerAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgServerAcpiTemplate
.Header
.OemId
));
1246 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1247 CopyMem (&mTcgServerAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1248 mTcgServerAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1249 mTcgServerAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1250 mTcgServerAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1252 // The ACPI table must be checksumed before calling the InstallAcpiTable()
1253 // service of the ACPI table protocol to install it.
1255 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgServerAcpiTemplate
, sizeof (mTcgServerAcpiTemplate
));
1256 mTcgServerAcpiTemplate
.Header
.Checksum
= Checksum
;
1258 mTcgServerAcpiTemplate
.BaseAddress
.Address
= PcdGet64 (PcdTpmBaseAddress
);
1259 Status
= AcpiTable
->InstallAcpiTable (
1261 &mTcgServerAcpiTemplate
,
1262 sizeof (mTcgServerAcpiTemplate
),
1267 if (EFI_ERROR (Status
)) {
1268 DEBUG((EFI_D_ERROR
, "Tcg Acpi Table installation failure"));
1273 Exit Boot Services Event notification handler.
1275 Measure invocation and success of ExitBootServices.
1277 @param[in] Event Event whose notification function is being invoked
1278 @param[in] Context Pointer to the notification function's context
1283 OnExitBootServices (
1291 // Measure invocation of ExitBootServices,
1293 Status
= TcgMeasureAction (
1294 EFI_EXIT_BOOT_SERVICES_INVOCATION
1296 if (EFI_ERROR (Status
)) {
1297 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION
));
1301 // Measure success of ExitBootServices
1303 Status
= TcgMeasureAction (
1304 EFI_EXIT_BOOT_SERVICES_SUCCEEDED
1306 if (EFI_ERROR (Status
)){
1307 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED
));
1312 Exit Boot Services Failed Event notification handler.
1314 Measure Failure of ExitBootServices.
1316 @param[in] Event Event whose notification function is being invoked
1317 @param[in] Context Pointer to the notification function's context
1322 OnExitBootServicesFailed (
1330 // Measure Failure of ExitBootServices,
1332 Status
= TcgMeasureAction (
1333 EFI_EXIT_BOOT_SERVICES_FAILED
1335 if (EFI_ERROR (Status
)){
1336 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED
));
1341 Get TPM Deactivated state.
1343 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
1345 @retval EFI_SUCCESS Operation completed successfully.
1346 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1351 OUT BOOLEAN
*TPMDeactivatedFlag
1355 TPM_STCLEAR_FLAGS VolatileFlags
;
1357 Status
= Tpm12GetCapabilityFlagVolatile (&VolatileFlags
);
1358 if (!EFI_ERROR (Status
)) {
1359 *TPMDeactivatedFlag
= VolatileFlags
.deactivated
;
1366 The driver's entry point.
1368 It publishes EFI TCG Protocol.
1370 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1371 @param[in] SystemTable A pointer to the EFI System Table.
1373 @retval EFI_SUCCESS The entry point is executed successfully.
1374 @retval other Some error occurs when executing this entry point.
1380 IN EFI_HANDLE ImageHandle
,
1381 IN EFI_SYSTEM_TABLE
*SystemTable
1388 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
1389 DEBUG ((EFI_D_ERROR
, "No TPM12 instance required!\n"));
1390 return EFI_UNSUPPORTED
;
1393 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1394 DEBUG ((EFI_D_ERROR
, "TPM error!\n"));
1395 return EFI_DEVICE_ERROR
;
1398 Status
= Tpm12RequestUseTpm ();
1399 if (EFI_ERROR (Status
)) {
1400 DEBUG ((EFI_D_ERROR
, "TPM not detected!\n"));
1404 Status
= GetTpmStatus (&mTcgDxeData
.BsCap
.TPMDeactivatedFlag
);
1405 if (EFI_ERROR (Status
)) {
1408 "Line %d in file " __FILE__
":\n "
1409 "DriverEntry: TPM not working properly\n",
1415 Status
= gBS
->InstallProtocolInterface (
1417 &gEfiTcgProtocolGuid
,
1418 EFI_NATIVE_INTERFACE
,
1419 &mTcgDxeData
.TcgProtocol
1421 if (!EFI_ERROR (Status
) && (!mTcgDxeData
.BsCap
.TPMDeactivatedFlag
) && mTcgDxeData
.BsCap
.TPMPresentFlag
) {
1423 // Setup the log area and copy event log from hob list to it
1425 Status
= SetupEventLog ();
1426 ASSERT_EFI_ERROR (Status
);
1429 // Measure handoff tables, Boot#### variables etc.
1431 Status
= EfiCreateEventReadyToBootEx (
1438 Status
= gBS
->CreateEventEx (
1443 &gEfiEventExitBootServicesGuid
,
1448 // Measure Exit Boot Service failed
1450 Status
= gBS
->CreateEventEx (
1453 OnExitBootServicesFailed
,
1455 &gEventExitBootServicesFailedGuid
,
1461 // Install ACPI Table
1463 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid
, TPL_CALLBACK
, InstallAcpiTable
, NULL
, &Registration
);