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 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
13 This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution. The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 #include <IndustryStandard/Tpm12.h>
25 #include <IndustryStandard/Acpi.h>
26 #include <IndustryStandard/PeImage.h>
27 #include <IndustryStandard/TcpaAcpi.h>
29 #include <Guid/GlobalVariable.h>
30 #include <Guid/HobList.h>
31 #include <Guid/TcgEventHob.h>
32 #include <Guid/EventGroup.h>
33 #include <Guid/EventExitBootServiceFailed.h>
34 #include <Guid/TpmInstance.h>
36 #include <Protocol/DevicePath.h>
37 #include <Protocol/TcgService.h>
38 #include <Protocol/AcpiTable.h>
39 #include <Protocol/MpService.h>
41 #include <Library/DebugLib.h>
42 #include <Library/BaseMemoryLib.h>
43 #include <Library/UefiRuntimeServicesTableLib.h>
44 #include <Library/UefiDriverEntryPoint.h>
45 #include <Library/HobLib.h>
46 #include <Library/UefiBootServicesTableLib.h>
47 #include <Library/BaseLib.h>
48 #include <Library/MemoryAllocationLib.h>
49 #include <Library/PrintLib.h>
50 #include <Library/Tpm12DeviceLib.h>
51 #include <Library/PcdLib.h>
52 #include <Library/UefiLib.h>
53 #include <Library/ReportStatusCodeLib.h>
54 #include <Library/Tpm12CommandLib.h>
55 #include <Library/BaseCryptLib.h>
57 #define TCG_DXE_DATA_FROM_THIS(this) \
58 BASE_CR (this, TCG_DXE_DATA, TcgProtocol)
60 typedef struct _TCG_DXE_DATA
{
61 EFI_TCG_PROTOCOL TcgProtocol
;
62 TCG_EFI_BOOT_SERVICE_CAPABILITY BsCap
;
63 EFI_TCG_CLIENT_ACPI_TABLE
*TcgClientAcpiTable
;
64 EFI_TCG_SERVER_ACPI_TABLE
*TcgServerAcpiTable
;
71 EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate
= {
73 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
74 sizeof (mTcgClientAcpiTemplate
),
77 // Compiler initializes the remaining bytes to 0
78 // These fields should be filled in in production
81 0, // 0 for PC Client Platform Class
82 0, // Log Area Max Length
83 (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1) // Log Area Start Address
87 // The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,
88 // the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,
89 // this _UID can be changed and should match with the _UID setting of the TPM
92 EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate
= {
94 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE
,
95 sizeof (mTcgServerAcpiTemplate
),
98 // Compiler initializes the remaining bytes to 0
99 // These fields should be filled in in production
102 1, // 1 for Server Platform Class
104 0, // Log Area Max Length
105 (EFI_PHYSICAL_ADDRESS
) (SIZE_4GB
- 1), // Log Area Start Address
106 0x0120, // TCG Specification revision 1.2
108 0, // Interrupt Flags
110 {0}, // Reserved 3 bytes
111 0, // Global System Interrupt
113 EFI_ACPI_3_0_SYSTEM_MEMORY
,
120 {0}, // Configuration Address
121 0xFF, // 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
124 0 // ACPI _UID value of the device, can be changed for different platforms
127 UINTN mBootAttempts
= 0;
128 CHAR16 mBootVarName
[] = L
"BootOrder";
131 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function
132 Caller is responsible to free LocationBuf.
134 @param[out] LocationBuf Returns Processor Location Buffer.
135 @param[out] Num Returns processor number.
137 @retval EFI_SUCCESS Operation completed successfully.
138 @retval EFI_UNSUPPORTED MpService protocol not found.
142 GetProcessorsCpuLocation (
143 OUT EFI_CPU_PHYSICAL_LOCATION
**LocationBuf
,
148 EFI_MP_SERVICES_PROTOCOL
*MpProtocol
;
150 UINTN EnabledProcessorNum
;
151 EFI_PROCESSOR_INFORMATION ProcessorInfo
;
152 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
155 Status
= gBS
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**) &MpProtocol
);
156 if (EFI_ERROR (Status
)) {
158 // MP protocol is not installed
160 return EFI_UNSUPPORTED
;
163 Status
= MpProtocol
->GetNumberOfProcessors(
168 if (EFI_ERROR(Status
)){
172 Status
= gBS
->AllocatePool(
174 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
175 (VOID
**) &ProcessorLocBuf
177 if (EFI_ERROR(Status
)){
182 // Get each processor Location info
184 for (Index
= 0; Index
< ProcessorNum
; Index
++) {
185 Status
= MpProtocol
->GetProcessorInfo(
190 if (EFI_ERROR(Status
)){
191 FreePool(ProcessorLocBuf
);
196 // Get all Processor Location info & measure
199 &ProcessorLocBuf
[Index
],
200 &ProcessorInfo
.Location
,
201 sizeof(EFI_CPU_PHYSICAL_LOCATION
)
205 *LocationBuf
= ProcessorLocBuf
;
212 This service provides EFI protocol capability information, state information
213 about the TPM, and Event Log state information.
215 @param[in] This Indicates the calling context
216 @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY
217 structure and fills in the fields with the EFI protocol
218 capability information and the current TPM state information.
219 @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature
220 flags are currently defined so this parameter
221 MUST be set to 0. However, in the future,
222 feature flags may be defined that, for example,
223 enable hash algorithm agility.
224 @param[out] EventLogLocation This is a pointer to the address of the event log in memory.
225 @param[out] EventLogLastEntry If the Event Log contains more than one entry,
226 this is a pointer to the address of the start of
227 the last entry in the event log in memory.
229 @retval EFI_SUCCESS Operation completed successfully.
230 @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.
236 IN EFI_TCG_PROTOCOL
*This
,
237 OUT TCG_EFI_BOOT_SERVICE_CAPABILITY
*ProtocolCapability
,
238 OUT UINT32
*TCGFeatureFlags
,
239 OUT EFI_PHYSICAL_ADDRESS
*EventLogLocation
,
240 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
243 TCG_DXE_DATA
*TcgData
;
245 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
247 if (ProtocolCapability
!= NULL
) {
248 *ProtocolCapability
= TcgData
->BsCap
;
251 if (TCGFeatureFlags
!= NULL
) {
252 *TCGFeatureFlags
= 0;
255 if (EventLogLocation
!= NULL
) {
256 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
257 *EventLogLocation
= TcgData
->TcgClientAcpiTable
->Lasa
;
259 *EventLogLocation
= TcgData
->TcgServerAcpiTable
->Lasa
;
263 if (EventLogLastEntry
!= NULL
) {
264 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
265 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)0;
267 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)TcgData
->LastEvent
;
275 Single function calculates SHA1 digest value for all raw data. It
276 combines Sha1Init(), Sha1Update() and Sha1Final().
278 @param[in] Data Raw data to be digested.
279 @param[in] DataLen Size of the raw data.
280 @param[out] Digest Pointer to a buffer that stores the final digest.
282 @retval EFI_SUCCESS Always successfully calculate the final digest.
287 IN CONST UINT8
*Data
,
289 OUT TPM_DIGEST
*Digest
295 CtxSize
= Sha1GetContextSize ();
296 Sha1Ctx
= AllocatePool (CtxSize
);
297 ASSERT (Sha1Ctx
!= NULL
);
300 Sha1Update (Sha1Ctx
, Data
, DataLen
);
301 Sha1Final (Sha1Ctx
, (UINT8
*)Digest
);
309 This service abstracts the capability to do a hash operation on a data buffer.
311 @param[in] This Indicates the calling context
312 @param[in] HashData Pointer to the data buffer to be hashed
313 @param[in] HashDataLen Length of the data buffer to be hashed
314 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
315 @param[in, out] HashedDataLen Resultant length of the hashed data
316 @param[in, out] HashedDataResult Resultant buffer of the hashed data
318 @retval EFI_SUCCESS Operation completed successfully.
319 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
320 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
321 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
322 @retval EFI_UNSUPPORTED AlgorithmId not supported.
323 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
329 IN EFI_TCG_PROTOCOL
*This
,
331 IN UINT64 HashDataLen
,
332 IN TCG_ALGORITHM_ID AlgorithmId
,
333 IN OUT UINT64
*HashedDataLen
,
334 IN OUT UINT8
**HashedDataResult
337 if (HashedDataLen
== NULL
|| HashedDataResult
== NULL
) {
338 return EFI_INVALID_PARAMETER
;
341 switch (AlgorithmId
) {
343 if (*HashedDataLen
== 0) {
344 *HashedDataLen
= sizeof (TPM_DIGEST
);
345 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
346 if (*HashedDataResult
== NULL
) {
347 return EFI_OUT_OF_RESOURCES
;
351 if (*HashedDataLen
< sizeof (TPM_DIGEST
)) {
352 *HashedDataLen
= sizeof (TPM_DIGEST
);
353 return EFI_BUFFER_TOO_SMALL
;
355 *HashedDataLen
= sizeof (TPM_DIGEST
);
357 if (*HashedDataResult
== NULL
) {
358 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
361 return TpmCommHashAll (
364 (TPM_DIGEST
*)*HashedDataResult
367 return EFI_UNSUPPORTED
;
372 Add a new entry to the Event Log.
374 @param[in, out] EventLogPtr Pointer to the Event Log data.
375 @param[in, out] LogSize Size of the Event Log.
376 @param[in] MaxSize Maximum size of the Event Log.
377 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
378 @param[in] NewEventData Pointer to the new event data.
380 @retval EFI_SUCCESS The new event log entry was added.
381 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
386 IN OUT UINT8
**EventLogPtr
,
387 IN OUT UINTN
*LogSize
,
389 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
390 IN UINT8
*NewEventData
396 // Prevent Event Overflow
398 if (NewEventHdr
->EventSize
> (UINTN
)(~0) - sizeof (*NewEventHdr
)) {
399 return EFI_OUT_OF_RESOURCES
;
402 NewLogSize
= sizeof (*NewEventHdr
) + NewEventHdr
->EventSize
;
403 if (NewLogSize
> MaxSize
- *LogSize
) {
404 return EFI_OUT_OF_RESOURCES
;
407 *EventLogPtr
+= *LogSize
;
408 *LogSize
+= NewLogSize
;
409 CopyMem (*EventLogPtr
, NewEventHdr
, sizeof (*NewEventHdr
));
411 *EventLogPtr
+ sizeof (*NewEventHdr
),
413 NewEventHdr
->EventSize
419 Add a new entry to the Event Log.
421 @param[in] TcgData TCG_DXE_DATA structure.
422 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
423 @param[in] NewEventData Pointer to the new event data.
425 @retval EFI_SUCCESS The new event log entry was added.
426 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
432 IN TCG_DXE_DATA
*TcgData
,
433 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
434 IN UINT8
*NewEventData
437 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
438 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgClientAcpiTable
->Lasa
;
439 return TpmCommLogEvent (
441 &TcgData
->EventLogSize
,
442 (UINTN
)TcgData
->TcgClientAcpiTable
->Laml
,
447 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgServerAcpiTable
->Lasa
;
448 return TpmCommLogEvent (
450 &TcgData
->EventLogSize
,
451 (UINTN
)TcgData
->TcgServerAcpiTable
->Laml
,
459 This service abstracts the capability to add an entry to the Event Log.
461 @param[in] This Indicates the calling context
462 @param[in] TCGLogData Pointer to the start of the data buffer containing
463 the TCG_PCR_EVENT data structure. All fields in
464 this structure are properly filled by the caller.
465 @param[in, out] EventNumber The event number of the event just logged
466 @param[in] Flags Indicate additional flags. Only one flag has been
467 defined at this time, which is 0x01 and means the
468 extend operation should not be performed. All
469 other bits are reserved.
471 @retval EFI_SUCCESS Operation completed successfully.
472 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
478 IN EFI_TCG_PROTOCOL
*This
,
479 IN TCG_PCR_EVENT
*TCGLogData
,
480 IN OUT UINT32
*EventNumber
,
484 TCG_DXE_DATA
*TcgData
;
486 if (TCGLogData
== NULL
){
487 return EFI_INVALID_PARAMETER
;
490 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
492 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
493 return EFI_DEVICE_ERROR
;
495 return TcgDxeLogEventI (
497 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
503 This service is a proxy for commands to the TPM.
505 @param[in] This Indicates the calling context
506 @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block
507 @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block
508 @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block
509 @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block
511 @retval EFI_SUCCESS Operation completed successfully.
512 @retval EFI_INVALID_PARAMETER Invalid ordinal.
513 @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.
514 @retval EFI_TIMEOUT The TIS timed-out.
519 TcgDxePassThroughToTpm (
520 IN EFI_TCG_PROTOCOL
*This
,
521 IN UINT32 TpmInputParameterBlockSize
,
522 IN UINT8
*TpmInputParameterBlock
,
523 IN UINT32 TpmOutputParameterBlockSize
,
524 IN UINT8
*TpmOutputParameterBlock
527 if (TpmInputParameterBlock
== NULL
||
528 TpmOutputParameterBlock
== NULL
||
529 TpmInputParameterBlockSize
== 0 ||
530 TpmOutputParameterBlockSize
== 0) {
531 return EFI_INVALID_PARAMETER
;
534 return Tpm12SubmitCommand (
535 TpmInputParameterBlockSize
,
536 TpmInputParameterBlock
,
537 &TpmOutputParameterBlockSize
,
538 TpmOutputParameterBlock
543 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
544 and add an entry to the Event Log.
546 @param[in] TcgData TCG_DXE_DATA structure.
547 @param[in] HashData Physical address of the start of the data buffer
548 to be hashed, extended, and logged.
549 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
550 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
551 @param[in] NewEventData Pointer to the new event data.
553 @retval EFI_SUCCESS Operation completed successfully.
554 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
555 @retval EFI_DEVICE_ERROR The command was unsuccessful.
560 TcgDxeHashLogExtendEventI (
561 IN TCG_DXE_DATA
*TcgData
,
563 IN UINT64 HashDataLen
,
564 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
565 IN UINT8
*NewEventData
570 if (!TcgData
->BsCap
.TPMPresentFlag
) {
571 return EFI_DEVICE_ERROR
;
574 if (HashDataLen
> 0 || HashData
!= NULL
) {
575 Status
= TpmCommHashAll (
580 if (EFI_ERROR(Status
)) {
581 DEBUG ((DEBUG_ERROR
, "TpmCommHashAll Failed. %x\n", Status
));
586 Status
= Tpm12Extend (
587 &NewEventHdr
->Digest
,
588 NewEventHdr
->PCRIndex
,
591 if (!EFI_ERROR (Status
)) {
592 Status
= TcgDxeLogEventI (TcgData
, NewEventHdr
, NewEventData
);
596 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
597 DEBUG ((EFI_D_ERROR
, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status
));
598 TcgData
->BsCap
.TPMPresentFlag
= FALSE
;
600 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
601 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
603 Status
= EFI_DEVICE_ERROR
;
610 This service abstracts the capability to do a hash operation on a data buffer,
611 extend a specific TPM PCR with the hash result, and add an entry to the Event Log
613 @param[in] This Indicates the calling context
614 @param[in] HashData Physical address of the start of the data buffer
615 to be hashed, extended, and logged.
616 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
617 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
618 @param[in, out] TCGLogData The physical address of the start of the data
619 buffer containing the TCG_PCR_EVENT data structure.
620 @param[in, out] EventNumber The event number of the event just logged.
621 @param[out] EventLogLastEntry Physical address of the first byte of the entry
622 just placed in the Event Log. If the Event Log was
623 empty when this function was called then this physical
624 address will be the same as the physical address of
625 the start of the Event Log.
627 @retval EFI_SUCCESS Operation completed successfully.
628 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
629 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
630 @retval EFI_DEVICE_ERROR The command was unsuccessful.
635 TcgDxeHashLogExtendEvent (
636 IN EFI_TCG_PROTOCOL
*This
,
637 IN EFI_PHYSICAL_ADDRESS HashData
,
638 IN UINT64 HashDataLen
,
639 IN TPM_ALGORITHM_ID AlgorithmId
,
640 IN OUT TCG_PCR_EVENT
*TCGLogData
,
641 IN OUT UINT32
*EventNumber
,
642 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
645 TCG_DXE_DATA
*TcgData
;
648 if (TCGLogData
== NULL
|| EventLogLastEntry
== NULL
){
649 return EFI_INVALID_PARAMETER
;
652 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
654 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
655 return EFI_DEVICE_ERROR
;
658 if (AlgorithmId
!= TPM_ALG_SHA
) {
659 return EFI_UNSUPPORTED
;
662 if (HashData
== 0 && HashDataLen
> 0) {
663 return EFI_INVALID_PARAMETER
;
666 Status
= TcgDxeHashLogExtendEventI (
668 (UINT8
*) (UINTN
) HashData
,
670 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
674 if (!EFI_ERROR(Status
)){
675 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) TcgData
->LastEvent
;
681 TCG_DXE_DATA mTcgDxeData
= {
686 TcgDxePassThroughToTpm
,
687 TcgDxeHashLogExtendEvent
690 sizeof (mTcgDxeData
.BsCap
),
697 &mTcgClientAcpiTemplate
,
698 &mTcgServerAcpiTemplate
,
704 Initialize the Event Log and log events passed from the PEI phase.
706 @retval EFI_SUCCESS Operation completed successfully.
707 @retval EFI_OUT_OF_RESOURCES Out of memory.
717 TCG_PCR_EVENT
*TcgEvent
;
718 EFI_PEI_HOB_POINTERS GuidHob
;
719 EFI_PHYSICAL_ADDRESS Lasa
;
721 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
722 Lasa
= mTcgClientAcpiTemplate
.Lasa
;
724 Status
= gBS
->AllocatePages (
727 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
730 if (EFI_ERROR (Status
)) {
733 mTcgClientAcpiTemplate
.Lasa
= Lasa
;
735 // To initialize them as 0xFF is recommended
736 // because the OS can know the last entry for that.
738 SetMem ((VOID
*)(UINTN
)mTcgClientAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
739 mTcgClientAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
742 Lasa
= mTcgServerAcpiTemplate
.Lasa
;
744 Status
= gBS
->AllocatePages (
747 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
750 if (EFI_ERROR (Status
)) {
753 mTcgServerAcpiTemplate
.Lasa
= Lasa
;
755 // To initialize them as 0xFF is recommended
756 // because the OS can know the last entry for that.
758 SetMem ((VOID
*)(UINTN
)mTcgServerAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
759 mTcgServerAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
762 GuidHob
.Raw
= GetHobList ();
763 while (!EFI_ERROR (Status
) &&
764 (GuidHob
.Raw
= GetNextGuidHob (&gTcgEventEntryHobGuid
, GuidHob
.Raw
)) != NULL
) {
765 TcgEvent
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
766 GuidHob
.Raw
= GET_NEXT_HOB (GuidHob
);
767 Status
= TcgDxeLogEventI (
769 (TCG_PCR_EVENT_HDR
*)TcgEvent
,
778 Measure and log an action string, and extend the measurement result into PCR[5].
780 @param[in] String A specific string that indicates an Action event.
782 @retval EFI_SUCCESS Operation completed successfully.
783 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
792 TCG_PCR_EVENT_HDR TcgEvent
;
794 TcgEvent
.PCRIndex
= 5;
795 TcgEvent
.EventType
= EV_EFI_ACTION
;
796 TcgEvent
.EventSize
= (UINT32
)AsciiStrLen (String
);
797 return TcgDxeHashLogExtendEventI (
807 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
809 @retval EFI_SUCCESS Operation completed successfully.
810 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
815 MeasureHandoffTables (
820 TCG_PCR_EVENT_HDR TcgEvent
;
821 EFI_HANDOFF_TABLE_POINTERS HandoffTables
;
823 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
825 ProcessorLocBuf
= NULL
;
826 Status
= EFI_SUCCESS
;
828 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_SERVER
) {
831 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
833 Status
= GetProcessorsCpuLocation(&ProcessorLocBuf
, &ProcessorNum
);
835 if (!EFI_ERROR(Status
)){
836 TcgEvent
.PCRIndex
= 1;
837 TcgEvent
.EventType
= EV_TABLE_OF_DEVICES
;
838 TcgEvent
.EventSize
= sizeof (HandoffTables
);
840 HandoffTables
.NumberOfTables
= 1;
841 HandoffTables
.TableEntry
[0].VendorGuid
= gEfiMpServiceProtocolGuid
;
842 HandoffTables
.TableEntry
[0].VendorTable
= ProcessorLocBuf
;
844 Status
= TcgDxeHashLogExtendEventI (
846 (UINT8
*)(UINTN
)ProcessorLocBuf
,
847 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
849 (UINT8
*)&HandoffTables
852 FreePool(ProcessorLocBuf
);
860 Measure and log Separator event, and extend the measurement result into a specific PCR.
862 @param[in] PCRIndex PCR index.
864 @retval EFI_SUCCESS Operation completed successfully.
865 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
870 MeasureSeparatorEvent (
871 IN TPM_PCRINDEX PCRIndex
874 TCG_PCR_EVENT_HDR TcgEvent
;
878 TcgEvent
.PCRIndex
= PCRIndex
;
879 TcgEvent
.EventType
= EV_SEPARATOR
;
880 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
881 return TcgDxeHashLogExtendEventI (
891 Read an EFI Variable.
893 This function allocates a buffer to return the contents of the variable. The caller is
894 responsible for freeing the buffer.
896 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
897 @param[in] VendorGuid A unique identifier for the vendor.
898 @param[out] VarSize The size of the variable data.
900 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
907 IN EFI_GUID
*VendorGuid
,
915 Status
= gRT
->GetVariable (
922 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
926 VarData
= AllocatePool (*VarSize
);
927 if (VarData
!= NULL
) {
928 Status
= gRT
->GetVariable (
935 if (EFI_ERROR (Status
)) {
945 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
947 @param[in] PCRIndex PCR Index.
948 @param[in] EventType Event type.
949 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
950 @param[in] VendorGuid A unique identifier for the vendor.
951 @param[in] VarData The content of the variable data.
952 @param[in] VarSize The size of the variable data.
954 @retval EFI_SUCCESS Operation completed successfully.
955 @retval EFI_OUT_OF_RESOURCES Out of memory.
956 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
962 IN TPM_PCRINDEX PCRIndex
,
963 IN TCG_EVENTTYPE EventType
,
965 IN EFI_GUID
*VendorGuid
,
971 TCG_PCR_EVENT_HDR TcgEvent
;
973 EFI_VARIABLE_DATA
*VarLog
;
975 VarNameLength
= StrLen (VarName
);
976 TcgEvent
.PCRIndex
= PCRIndex
;
977 TcgEvent
.EventType
= EventType
;
978 TcgEvent
.EventSize
= (UINT32
)(sizeof (*VarLog
) + VarNameLength
* sizeof (*VarName
) + VarSize
979 - sizeof (VarLog
->UnicodeName
) - sizeof (VarLog
->VariableData
));
981 VarLog
= (EFI_VARIABLE_DATA
*)AllocatePool (TcgEvent
.EventSize
);
982 if (VarLog
== NULL
) {
983 return EFI_OUT_OF_RESOURCES
;
986 VarLog
->VariableName
= *VendorGuid
;
987 VarLog
->UnicodeNameLength
= VarNameLength
;
988 VarLog
->VariableDataLength
= VarSize
;
992 VarNameLength
* sizeof (*VarName
)
995 (CHAR16
*)VarLog
->UnicodeName
+ VarNameLength
,
1000 Status
= TcgDxeHashLogExtendEventI (
1012 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
1014 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
1015 @param[in] VendorGuid A unique identifier for the vendor.
1016 @param[out] VarSize The size of the variable data.
1017 @param[out] VarData Pointer to the content of the variable.
1019 @retval EFI_SUCCESS Operation completed successfully.
1020 @retval EFI_OUT_OF_RESOURCES Out of memory.
1021 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1026 ReadAndMeasureBootVariable (
1028 IN EFI_GUID
*VendorGuid
,
1035 *VarData
= ReadVariable (VarName
, VendorGuid
, VarSize
);
1036 if (*VarData
== NULL
) {
1037 return EFI_NOT_FOUND
;
1040 Status
= MeasureVariable (
1042 EV_EFI_VARIABLE_BOOT
,
1052 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
1054 The EFI boot variables are BootOrder and Boot#### variables.
1056 @retval EFI_SUCCESS Operation completed successfully.
1057 @retval EFI_OUT_OF_RESOURCES Out of memory.
1058 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1063 MeasureAllBootVariables (
1074 Status
= ReadAndMeasureBootVariable (
1076 &gEfiGlobalVariableGuid
,
1078 (VOID
**) &BootOrder
1080 if (Status
== EFI_NOT_FOUND
|| BootOrder
== NULL
) {
1084 if (EFI_ERROR (Status
)) {
1086 // BootOrder can't be NULL if status is not EFI_NOT_FOUND
1088 FreePool (BootOrder
);
1092 BootCount
/= sizeof (*BootOrder
);
1093 for (Index
= 0; Index
< BootCount
; Index
++) {
1094 UnicodeSPrint (mBootVarName
, sizeof (mBootVarName
), L
"Boot%04x", BootOrder
[Index
]);
1095 Status
= ReadAndMeasureBootVariable (
1097 &gEfiGlobalVariableGuid
,
1101 if (!EFI_ERROR (Status
)) {
1102 FreePool (BootVarData
);
1106 FreePool (BootOrder
);
1111 Ready to Boot Event notification handler.
1113 Sequence of OS boot events is measured in this event notification handler.
1115 @param[in] Event Event whose notification function is being invoked
1116 @param[in] Context Pointer to the notification function's context
1127 TPM_PCRINDEX PcrIndex
;
1129 if (mBootAttempts
== 0) {
1132 // Measure handoff tables.
1134 Status
= MeasureHandoffTables ();
1135 if (EFI_ERROR (Status
)) {
1136 DEBUG ((EFI_D_ERROR
, "HOBs not Measured. Error!\n"));
1140 // Measure BootOrder & Boot#### variables.
1142 Status
= MeasureAllBootVariables ();
1143 if (EFI_ERROR (Status
)) {
1144 DEBUG ((EFI_D_ERROR
, "Boot Variables not Measured. Error!\n"));
1148 // 1. This is the first boot attempt.
1150 Status
= TcgMeasureAction (
1151 EFI_CALLING_EFI_APPLICATION
1153 if (EFI_ERROR (Status
)) {
1154 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION
));
1158 // 2. Draw a line between pre-boot env and entering post-boot env.
1160 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1161 Status
= MeasureSeparatorEvent (PcrIndex
);
1162 if (EFI_ERROR (Status
)) {
1163 DEBUG ((EFI_D_ERROR
, "Seperator Event not Measured. Error!\n"));
1168 // 3. Measure GPT. It would be done in SAP driver.
1172 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
1176 // 5. Read & Measure variable. BootOrder already measured.
1180 // 6. Not first attempt, meaning a return from last attempt
1182 Status
= TcgMeasureAction (
1183 EFI_RETURNING_FROM_EFI_APPLICATOIN
1185 if (EFI_ERROR (Status
)) {
1186 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN
));
1190 DEBUG ((EFI_D_INFO
, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
1192 // Increase boot attempt counter.
1198 Install TCG ACPI Table when ACPI Table Protocol is available.
1200 A system's firmware uses an ACPI table to identify the system's TCG capabilities
1201 to the Post-Boot environment. The information in this ACPI table is not guaranteed
1202 to be valid until the Host Platform transitions from pre-boot state to post-boot state.
1204 @param[in] Event Event whose notification function is being invoked
1205 @param[in] Context Pointer to the notification function's context
1216 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
1220 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**)&AcpiTable
);
1221 if (EFI_ERROR (Status
)) {
1225 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
1226 CopyMem (mTcgClientAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgClientAcpiTemplate
.Header
.OemId
));
1227 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1228 CopyMem (&mTcgClientAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1229 mTcgClientAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1230 mTcgClientAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1231 mTcgClientAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1233 // The ACPI table must be checksumed before calling the InstallAcpiTable()
1234 // service of the ACPI table protocol to install it.
1236 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgClientAcpiTemplate
, sizeof (mTcgClientAcpiTemplate
));
1237 mTcgClientAcpiTemplate
.Header
.Checksum
= Checksum
;
1239 Status
= AcpiTable
->InstallAcpiTable (
1241 &mTcgClientAcpiTemplate
,
1242 sizeof (mTcgClientAcpiTemplate
),
1246 CopyMem (mTcgServerAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgServerAcpiTemplate
.Header
.OemId
));
1247 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1248 CopyMem (&mTcgServerAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1249 mTcgServerAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1250 mTcgServerAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1251 mTcgServerAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1253 // The ACPI table must be checksumed before calling the InstallAcpiTable()
1254 // service of the ACPI table protocol to install it.
1256 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgServerAcpiTemplate
, sizeof (mTcgServerAcpiTemplate
));
1257 mTcgServerAcpiTemplate
.Header
.Checksum
= Checksum
;
1259 mTcgServerAcpiTemplate
.BaseAddress
.Address
= PcdGet64 (PcdTpmBaseAddress
);
1260 Status
= AcpiTable
->InstallAcpiTable (
1262 &mTcgServerAcpiTemplate
,
1263 sizeof (mTcgServerAcpiTemplate
),
1268 if (EFI_ERROR (Status
)) {
1269 DEBUG((EFI_D_ERROR
, "Tcg Acpi Table installation failure"));
1274 Exit Boot Services Event notification handler.
1276 Measure invocation and success of ExitBootServices.
1278 @param[in] Event Event whose notification function is being invoked
1279 @param[in] Context Pointer to the notification function's context
1284 OnExitBootServices (
1292 // Measure invocation of ExitBootServices,
1294 Status
= TcgMeasureAction (
1295 EFI_EXIT_BOOT_SERVICES_INVOCATION
1297 if (EFI_ERROR (Status
)) {
1298 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION
));
1302 // Measure success of ExitBootServices
1304 Status
= TcgMeasureAction (
1305 EFI_EXIT_BOOT_SERVICES_SUCCEEDED
1307 if (EFI_ERROR (Status
)){
1308 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED
));
1313 Exit Boot Services Failed Event notification handler.
1315 Measure Failure of ExitBootServices.
1317 @param[in] Event Event whose notification function is being invoked
1318 @param[in] Context Pointer to the notification function's context
1323 OnExitBootServicesFailed (
1331 // Measure Failure of ExitBootServices,
1333 Status
= TcgMeasureAction (
1334 EFI_EXIT_BOOT_SERVICES_FAILED
1336 if (EFI_ERROR (Status
)){
1337 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED
));
1342 Get TPM Deactivated state.
1344 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
1346 @retval EFI_SUCCESS Operation completed successfully.
1347 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1352 OUT BOOLEAN
*TPMDeactivatedFlag
1356 TPM_STCLEAR_FLAGS VolatileFlags
;
1358 Status
= Tpm12GetCapabilityFlagVolatile (&VolatileFlags
);
1359 if (!EFI_ERROR (Status
)) {
1360 *TPMDeactivatedFlag
= VolatileFlags
.deactivated
;
1367 The driver's entry point.
1369 It publishes EFI TCG Protocol.
1371 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1372 @param[in] SystemTable A pointer to the EFI System Table.
1374 @retval EFI_SUCCESS The entry point is executed successfully.
1375 @retval other Some error occurs when executing this entry point.
1381 IN EFI_HANDLE ImageHandle
,
1382 IN EFI_SYSTEM_TABLE
*SystemTable
1389 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
1390 DEBUG ((EFI_D_ERROR
, "No TPM12 instance required!\n"));
1391 return EFI_UNSUPPORTED
;
1394 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1395 DEBUG ((EFI_D_ERROR
, "TPM error!\n"));
1396 return EFI_DEVICE_ERROR
;
1399 Status
= Tpm12RequestUseTpm ();
1400 if (EFI_ERROR (Status
)) {
1401 DEBUG ((EFI_D_ERROR
, "TPM not detected!\n"));
1405 Status
= GetTpmStatus (&mTcgDxeData
.BsCap
.TPMDeactivatedFlag
);
1406 if (EFI_ERROR (Status
)) {
1409 "Line %d in file " __FILE__
":\n "
1410 "DriverEntry: TPM not working properly\n",
1416 Status
= gBS
->InstallProtocolInterface (
1418 &gEfiTcgProtocolGuid
,
1419 EFI_NATIVE_INTERFACE
,
1420 &mTcgDxeData
.TcgProtocol
1422 if (!EFI_ERROR (Status
) && (!mTcgDxeData
.BsCap
.TPMDeactivatedFlag
) && mTcgDxeData
.BsCap
.TPMPresentFlag
) {
1424 // Setup the log area and copy event log from hob list to it
1426 Status
= SetupEventLog ();
1427 ASSERT_EFI_ERROR (Status
);
1430 // Measure handoff tables, Boot#### variables etc.
1432 Status
= EfiCreateEventReadyToBootEx (
1439 Status
= gBS
->CreateEventEx (
1444 &gEfiEventExitBootServicesGuid
,
1449 // Measure Exit Boot Service failed
1451 Status
= gBS
->CreateEventEx (
1454 OnExitBootServicesFailed
,
1456 &gEventExitBootServicesFailedGuid
,
1462 // Install ACPI Table
1464 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid
, TPL_CALLBACK
, InstallAcpiTable
, NULL
, &Registration
);