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/TpmCommLib.h>
50 #include <Library/PcdLib.h>
51 #include <Library/UefiLib.h>
52 #include <Library/ReportStatusCodeLib.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
;
66 TIS_TPM_HANDLE TpmHandle
;
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 0x0100, // TCG Specification revision 1.0
108 0, // Interrupt Flags
110 {0}, // Reserved 3 bytes
111 0, // Global System Interrupt
113 EFI_ACPI_3_0_SYSTEM_MEMORY
,
117 TPM_BASE_ADDRESS
// Base Address
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 This service abstracts the capability to do a hash operation on a data buffer.
277 @param[in] This Indicates the calling context
278 @param[in] HashData Pointer to the data buffer to be hashed
279 @param[in] HashDataLen Length of the data buffer to be hashed
280 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
281 @param[in, out] HashedDataLen Resultant length of the hashed data
282 @param[in, out] HashedDataResult Resultant buffer of the hashed data
284 @retval EFI_SUCCESS Operation completed successfully.
285 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.
286 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.
287 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.
288 @retval EFI_UNSUPPORTED AlgorithmId not supported.
289 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).
295 IN EFI_TCG_PROTOCOL
*This
,
297 IN UINT64 HashDataLen
,
298 IN TCG_ALGORITHM_ID AlgorithmId
,
299 IN OUT UINT64
*HashedDataLen
,
300 IN OUT UINT8
**HashedDataResult
303 if (HashedDataLen
== NULL
|| HashedDataResult
== NULL
) {
304 return EFI_INVALID_PARAMETER
;
307 switch (AlgorithmId
) {
309 if (*HashedDataLen
== 0) {
310 *HashedDataLen
= sizeof (TPM_DIGEST
);
311 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
312 if (*HashedDataResult
== NULL
) {
313 return EFI_OUT_OF_RESOURCES
;
317 if (*HashedDataLen
< sizeof (TPM_DIGEST
)) {
318 *HashedDataLen
= sizeof (TPM_DIGEST
);
319 return EFI_BUFFER_TOO_SMALL
;
321 *HashedDataLen
= sizeof (TPM_DIGEST
);
323 if (*HashedDataResult
== NULL
) {
324 *HashedDataResult
= AllocatePool ((UINTN
) *HashedDataLen
);
327 return TpmCommHashAll (
330 (TPM_DIGEST
*)*HashedDataResult
333 return EFI_UNSUPPORTED
;
338 Add a new entry to the Event Log.
340 @param[in] TcgData TCG_DXE_DATA structure.
341 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
342 @param[in] NewEventData Pointer to the new event data.
344 @retval EFI_SUCCESS The new event log entry was added.
345 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
351 IN TCG_DXE_DATA
*TcgData
,
352 IN TCG_PCR_EVENT_HDR
*NewEventHdr
,
353 IN UINT8
*NewEventData
356 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
357 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgClientAcpiTable
->Lasa
;
358 return TpmCommLogEvent (
360 &TcgData
->EventLogSize
,
361 (UINTN
)TcgData
->TcgClientAcpiTable
->Laml
,
366 TcgData
->LastEvent
= (UINT8
*)(UINTN
)TcgData
->TcgServerAcpiTable
->Lasa
;
367 return TpmCommLogEvent (
369 &TcgData
->EventLogSize
,
370 (UINTN
)TcgData
->TcgServerAcpiTable
->Laml
,
378 This service abstracts the capability to add an entry to the Event Log.
380 @param[in] This Indicates the calling context
381 @param[in] TCGLogData Pointer to the start of the data buffer containing
382 the TCG_PCR_EVENT data structure. All fields in
383 this structure are properly filled by the caller.
384 @param[in, out] EventNumber The event number of the event just logged
385 @param[in] Flags Indicate additional flags. Only one flag has been
386 defined at this time, which is 0x01 and means the
387 extend operation should not be performed. All
388 other bits are reserved.
390 @retval EFI_SUCCESS Operation completed successfully.
391 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.
397 IN EFI_TCG_PROTOCOL
*This
,
398 IN TCG_PCR_EVENT
*TCGLogData
,
399 IN OUT UINT32
*EventNumber
,
403 TCG_DXE_DATA
*TcgData
;
405 if (TCGLogData
== NULL
){
406 return EFI_INVALID_PARAMETER
;
409 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
411 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
412 return EFI_DEVICE_ERROR
;
414 return TcgDxeLogEventI (
416 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
422 This service is a proxy for commands to the TPM.
424 @param[in] This Indicates the calling context
425 @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block
426 @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block
427 @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block
428 @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block
430 @retval EFI_SUCCESS Operation completed successfully.
431 @retval EFI_INVALID_PARAMETER Invalid ordinal.
432 @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.
433 @retval EFI_TIMEOUT The TIS timed-out.
438 TcgDxePassThroughToTpm (
439 IN EFI_TCG_PROTOCOL
*This
,
440 IN UINT32 TpmInputParameterBlockSize
,
441 IN UINT8
*TpmInputParameterBlock
,
442 IN UINT32 TpmOutputParameterBlockSize
,
443 IN UINT8
*TpmOutputParameterBlock
446 TCG_DXE_DATA
*TcgData
;
448 if (TpmInputParameterBlock
== NULL
||
449 TpmOutputParameterBlock
== NULL
||
450 TpmInputParameterBlockSize
== 0 ||
451 TpmOutputParameterBlockSize
== 0) {
452 return EFI_INVALID_PARAMETER
;
455 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
457 return TisPcExecute (
460 TpmInputParameterBlock
,
461 (UINTN
) TpmInputParameterBlockSize
,
462 TpmOutputParameterBlock
,
463 (UINTN
) TpmOutputParameterBlockSize
468 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
469 and add an entry to the Event Log.
471 @param[in] TcgData TCG_DXE_DATA structure.
472 @param[in] HashData Physical address of the start of the data buffer
473 to be hashed, extended, and logged.
474 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
475 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
476 @param[in] NewEventData Pointer to the new event data.
478 @retval EFI_SUCCESS Operation completed successfully.
479 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
480 @retval EFI_DEVICE_ERROR The command was unsuccessful.
485 TcgDxeHashLogExtendEventI (
486 IN TCG_DXE_DATA
*TcgData
,
488 IN UINT64 HashDataLen
,
489 IN OUT TCG_PCR_EVENT_HDR
*NewEventHdr
,
490 IN UINT8
*NewEventData
495 if (!TcgData
->BsCap
.TPMPresentFlag
) {
496 return EFI_DEVICE_ERROR
;
499 if (HashDataLen
> 0 || HashData
!= NULL
) {
500 Status
= TpmCommHashAll (
505 if (EFI_ERROR(Status
)) {
506 DEBUG ((DEBUG_ERROR
, "TpmCommHashAll Failed. %x\n", Status
));
511 Status
= TpmCommExtend (
513 &NewEventHdr
->Digest
,
514 NewEventHdr
->PCRIndex
,
517 if (!EFI_ERROR (Status
)) {
518 Status
= TcgDxeLogEventI (TcgData
, NewEventHdr
, NewEventData
);
522 if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_TIMEOUT
)) {
523 DEBUG ((EFI_D_ERROR
, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status
));
524 TcgData
->BsCap
.TPMPresentFlag
= FALSE
;
526 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
527 (PcdGet32 (PcdStatusCodeSubClassTpmDevice
) | EFI_P_EC_INTERFACE_ERROR
)
529 Status
= EFI_DEVICE_ERROR
;
536 This service abstracts the capability to do a hash operation on a data buffer,
537 extend a specific TPM PCR with the hash result, and add an entry to the Event Log
539 @param[in] This Indicates the calling context
540 @param[in] HashData Physical address of the start of the data buffer
541 to be hashed, extended, and logged.
542 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
543 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation
544 @param[in, out] TCGLogData The physical address of the start of the data
545 buffer containing the TCG_PCR_EVENT data structure.
546 @param[in, out] EventNumber The event number of the event just logged.
547 @param[out] EventLogLastEntry Physical address of the first byte of the entry
548 just placed in the Event Log. If the Event Log was
549 empty when this function was called then this physical
550 address will be the same as the physical address of
551 the start of the Event Log.
553 @retval EFI_SUCCESS Operation completed successfully.
554 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.
555 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.
556 @retval EFI_DEVICE_ERROR The command was unsuccessful.
561 TcgDxeHashLogExtendEvent (
562 IN EFI_TCG_PROTOCOL
*This
,
563 IN EFI_PHYSICAL_ADDRESS HashData
,
564 IN UINT64 HashDataLen
,
565 IN TPM_ALGORITHM_ID AlgorithmId
,
566 IN OUT TCG_PCR_EVENT
*TCGLogData
,
567 IN OUT UINT32
*EventNumber
,
568 OUT EFI_PHYSICAL_ADDRESS
*EventLogLastEntry
571 TCG_DXE_DATA
*TcgData
;
574 if (TCGLogData
== NULL
|| EventLogLastEntry
== NULL
){
575 return EFI_INVALID_PARAMETER
;
578 TcgData
= TCG_DXE_DATA_FROM_THIS (This
);
580 if (TcgData
->BsCap
.TPMDeactivatedFlag
|| (!TcgData
->BsCap
.TPMPresentFlag
)) {
581 return EFI_DEVICE_ERROR
;
584 if (AlgorithmId
!= TPM_ALG_SHA
) {
585 return EFI_UNSUPPORTED
;
588 if (HashData
== 0 && HashDataLen
> 0) {
589 return EFI_INVALID_PARAMETER
;
592 Status
= TcgDxeHashLogExtendEventI (
594 (UINT8
*) (UINTN
) HashData
,
596 (TCG_PCR_EVENT_HDR
*)TCGLogData
,
600 if (!EFI_ERROR(Status
)){
601 *EventLogLastEntry
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) TcgData
->LastEvent
;
607 TCG_DXE_DATA mTcgDxeData
= {
612 TcgDxePassThroughToTpm
,
613 TcgDxeHashLogExtendEvent
616 sizeof (mTcgDxeData
.BsCap
),
623 &mTcgClientAcpiTemplate
,
624 &mTcgServerAcpiTemplate
,
631 Initialize the Event Log and log events passed from the PEI phase.
633 @retval EFI_SUCCESS Operation completed successfully.
634 @retval EFI_OUT_OF_RESOURCES Out of memory.
644 TCG_PCR_EVENT
*TcgEvent
;
645 EFI_PEI_HOB_POINTERS GuidHob
;
646 EFI_PHYSICAL_ADDRESS Lasa
;
648 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
649 Lasa
= mTcgClientAcpiTemplate
.Lasa
;
651 Status
= gBS
->AllocatePages (
654 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
657 if (EFI_ERROR (Status
)) {
660 mTcgClientAcpiTemplate
.Lasa
= Lasa
;
662 // To initialize them as 0xFF is recommended
663 // because the OS can know the last entry for that.
665 SetMem ((VOID
*)(UINTN
)mTcgClientAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
666 mTcgClientAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
669 Lasa
= mTcgServerAcpiTemplate
.Lasa
;
671 Status
= gBS
->AllocatePages (
674 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen
)),
677 if (EFI_ERROR (Status
)) {
680 mTcgServerAcpiTemplate
.Lasa
= Lasa
;
682 // To initialize them as 0xFF is recommended
683 // because the OS can know the last entry for that.
685 SetMem ((VOID
*)(UINTN
)mTcgServerAcpiTemplate
.Lasa
, PcdGet32 (PcdTcgLogAreaMinLen
), 0xFF);
686 mTcgServerAcpiTemplate
.Laml
= PcdGet32 (PcdTcgLogAreaMinLen
);
689 GuidHob
.Raw
= GetHobList ();
690 while (!EFI_ERROR (Status
) &&
691 (GuidHob
.Raw
= GetNextGuidHob (&gTcgEventEntryHobGuid
, GuidHob
.Raw
)) != NULL
) {
692 TcgEvent
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
693 GuidHob
.Raw
= GET_NEXT_HOB (GuidHob
);
694 Status
= TcgDxeLogEventI (
696 (TCG_PCR_EVENT_HDR
*)TcgEvent
,
705 Measure and log an action string, and extend the measurement result into PCR[5].
707 @param[in] String A specific string that indicates an Action event.
709 @retval EFI_SUCCESS Operation completed successfully.
710 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
719 TCG_PCR_EVENT_HDR TcgEvent
;
721 TcgEvent
.PCRIndex
= 5;
722 TcgEvent
.EventType
= EV_EFI_ACTION
;
723 TcgEvent
.EventSize
= (UINT32
)AsciiStrLen (String
);
724 return TcgDxeHashLogExtendEventI (
734 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].
736 @retval EFI_SUCCESS Operation completed successfully.
737 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
742 MeasureHandoffTables (
747 TCG_PCR_EVENT_HDR TcgEvent
;
748 EFI_HANDOFF_TABLE_POINTERS HandoffTables
;
750 EFI_CPU_PHYSICAL_LOCATION
*ProcessorLocBuf
;
752 ProcessorLocBuf
= NULL
;
753 Status
= EFI_SUCCESS
;
755 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_SERVER
) {
758 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]
760 Status
= GetProcessorsCpuLocation(&ProcessorLocBuf
, &ProcessorNum
);
762 if (!EFI_ERROR(Status
)){
763 TcgEvent
.PCRIndex
= 1;
764 TcgEvent
.EventType
= EV_TABLE_OF_DEVICES
;
765 TcgEvent
.EventSize
= sizeof (HandoffTables
);
767 HandoffTables
.NumberOfTables
= 1;
768 HandoffTables
.TableEntry
[0].VendorGuid
= gEfiMpServiceProtocolGuid
;
769 HandoffTables
.TableEntry
[0].VendorTable
= ProcessorLocBuf
;
771 Status
= TcgDxeHashLogExtendEventI (
773 (UINT8
*)(UINTN
)ProcessorLocBuf
,
774 sizeof(EFI_CPU_PHYSICAL_LOCATION
) * ProcessorNum
,
776 (UINT8
*)&HandoffTables
779 FreePool(ProcessorLocBuf
);
787 Measure and log Separator event, and extend the measurement result into a specific PCR.
789 @param[in] PCRIndex PCR index.
791 @retval EFI_SUCCESS Operation completed successfully.
792 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
797 MeasureSeparatorEvent (
798 IN TPM_PCRINDEX PCRIndex
801 TCG_PCR_EVENT_HDR TcgEvent
;
805 TcgEvent
.PCRIndex
= PCRIndex
;
806 TcgEvent
.EventType
= EV_SEPARATOR
;
807 TcgEvent
.EventSize
= (UINT32
)sizeof (EventData
);
808 return TcgDxeHashLogExtendEventI (
818 Read an EFI Variable.
820 This function allocates a buffer to return the contents of the variable. The caller is
821 responsible for freeing the buffer.
823 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
824 @param[in] VendorGuid A unique identifier for the vendor.
825 @param[out] VarSize The size of the variable data.
827 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.
834 IN EFI_GUID
*VendorGuid
,
842 Status
= gRT
->GetVariable (
849 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
853 VarData
= AllocatePool (*VarSize
);
854 if (VarData
!= NULL
) {
855 Status
= gRT
->GetVariable (
862 if (EFI_ERROR (Status
)) {
872 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
874 @param[in] PCRIndex PCR Index.
875 @param[in] EventType Event type.
876 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
877 @param[in] VendorGuid A unique identifier for the vendor.
878 @param[in] VarData The content of the variable data.
879 @param[in] VarSize The size of the variable data.
881 @retval EFI_SUCCESS Operation completed successfully.
882 @retval EFI_OUT_OF_RESOURCES Out of memory.
883 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
889 IN TPM_PCRINDEX PCRIndex
,
890 IN TCG_EVENTTYPE EventType
,
892 IN EFI_GUID
*VendorGuid
,
898 TCG_PCR_EVENT_HDR TcgEvent
;
900 EFI_VARIABLE_DATA
*VarLog
;
902 VarNameLength
= StrLen (VarName
);
903 TcgEvent
.PCRIndex
= PCRIndex
;
904 TcgEvent
.EventType
= EventType
;
905 TcgEvent
.EventSize
= (UINT32
)(sizeof (*VarLog
) + VarNameLength
* sizeof (*VarName
) + VarSize
906 - sizeof (VarLog
->UnicodeName
) - sizeof (VarLog
->VariableData
));
908 VarLog
= (EFI_VARIABLE_DATA
*)AllocatePool (TcgEvent
.EventSize
);
909 if (VarLog
== NULL
) {
910 return EFI_OUT_OF_RESOURCES
;
913 VarLog
->VariableName
= *VendorGuid
;
914 VarLog
->UnicodeNameLength
= VarNameLength
;
915 VarLog
->VariableDataLength
= VarSize
;
919 VarNameLength
* sizeof (*VarName
)
922 (CHAR16
*)VarLog
->UnicodeName
+ VarNameLength
,
927 Status
= TcgDxeHashLogExtendEventI (
939 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].
941 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
942 @param[in] VendorGuid A unique identifier for the vendor.
943 @param[out] VarSize The size of the variable data.
944 @param[out] VarData Pointer to the content of the variable.
946 @retval EFI_SUCCESS Operation completed successfully.
947 @retval EFI_OUT_OF_RESOURCES Out of memory.
948 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
953 ReadAndMeasureBootVariable (
955 IN EFI_GUID
*VendorGuid
,
962 *VarData
= ReadVariable (VarName
, VendorGuid
, VarSize
);
963 if (*VarData
== NULL
) {
964 return EFI_NOT_FOUND
;
967 Status
= MeasureVariable (
969 EV_EFI_VARIABLE_BOOT
,
979 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.
981 The EFI boot variables are BootOrder and Boot#### variables.
983 @retval EFI_SUCCESS Operation completed successfully.
984 @retval EFI_OUT_OF_RESOURCES Out of memory.
985 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
990 MeasureAllBootVariables (
1001 Status
= ReadAndMeasureBootVariable (
1003 &gEfiGlobalVariableGuid
,
1005 (VOID
**) &BootOrder
1007 if (Status
== EFI_NOT_FOUND
|| BootOrder
== NULL
) {
1011 if (EFI_ERROR (Status
)) {
1013 // BootOrder can't be NULL if status is not EFI_NOT_FOUND
1015 FreePool (BootOrder
);
1019 BootCount
/= sizeof (*BootOrder
);
1020 for (Index
= 0; Index
< BootCount
; Index
++) {
1021 UnicodeSPrint (mBootVarName
, sizeof (mBootVarName
), L
"Boot%04x", BootOrder
[Index
]);
1022 Status
= ReadAndMeasureBootVariable (
1024 &gEfiGlobalVariableGuid
,
1028 if (!EFI_ERROR (Status
)) {
1029 FreePool (BootVarData
);
1033 FreePool (BootOrder
);
1038 Ready to Boot Event notification handler.
1040 Sequence of OS boot events is measured in this event notification handler.
1042 @param[in] Event Event whose notification function is being invoked
1043 @param[in] Context Pointer to the notification function's context
1054 TPM_PCRINDEX PcrIndex
;
1056 if (mBootAttempts
== 0) {
1059 // Measure handoff tables.
1061 Status
= MeasureHandoffTables ();
1062 if (EFI_ERROR (Status
)) {
1063 DEBUG ((EFI_D_ERROR
, "HOBs not Measured. Error!\n"));
1067 // Measure BootOrder & Boot#### variables.
1069 Status
= MeasureAllBootVariables ();
1070 if (EFI_ERROR (Status
)) {
1071 DEBUG ((EFI_D_ERROR
, "Boot Variables not Measured. Error!\n"));
1075 // 1. This is the first boot attempt.
1077 Status
= TcgMeasureAction (
1078 EFI_CALLING_EFI_APPLICATION
1080 if (EFI_ERROR (Status
)) {
1081 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION
));
1085 // 2. Draw a line between pre-boot env and entering post-boot env.
1087 for (PcrIndex
= 0; PcrIndex
< 8; PcrIndex
++) {
1088 Status
= MeasureSeparatorEvent (PcrIndex
);
1089 if (EFI_ERROR (Status
)) {
1090 DEBUG ((EFI_D_ERROR
, "Seperator Event not Measured. Error!\n"));
1095 // 3. Measure GPT. It would be done in SAP driver.
1099 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.
1103 // 5. Read & Measure variable. BootOrder already measured.
1107 // 6. Not first attempt, meaning a return from last attempt
1109 Status
= TcgMeasureAction (
1110 EFI_RETURNING_FROM_EFI_APPLICATOIN
1112 if (EFI_ERROR (Status
)) {
1113 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN
));
1117 DEBUG ((EFI_D_INFO
, "TPM TcgDxe Measure Data when ReadyToBoot\n"));
1119 // Increase boot attempt counter.
1125 Install TCG ACPI Table when ACPI Table Protocol is available.
1127 A system's firmware uses an ACPI table to identify the system's TCG capabilities
1128 to the Post-Boot environment. The information in this ACPI table is not guaranteed
1129 to be valid until the Host Platform transitions from pre-boot state to post-boot state.
1131 @param[in] Event Event whose notification function is being invoked
1132 @param[in] Context Pointer to the notification function's context
1143 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
1147 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**)&AcpiTable
);
1148 if (EFI_ERROR (Status
)) {
1152 if (PcdGet8 (PcdTpmPlatformClass
) == TCG_PLATFORM_TYPE_CLIENT
) {
1153 CopyMem (mTcgClientAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgClientAcpiTemplate
.Header
.OemId
));
1154 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1155 CopyMem (&mTcgClientAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1156 mTcgClientAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1157 mTcgClientAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1158 mTcgClientAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1160 // The ACPI table must be checksumed before calling the InstallAcpiTable()
1161 // service of the ACPI table protocol to install it.
1163 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgClientAcpiTemplate
, sizeof (mTcgClientAcpiTemplate
));
1164 mTcgClientAcpiTemplate
.Header
.Checksum
= Checksum
;
1166 Status
= AcpiTable
->InstallAcpiTable (
1168 &mTcgClientAcpiTemplate
,
1169 sizeof (mTcgClientAcpiTemplate
),
1173 CopyMem (mTcgServerAcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTcgServerAcpiTemplate
.Header
.OemId
));
1174 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
1175 CopyMem (&mTcgServerAcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
1176 mTcgServerAcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
1177 mTcgServerAcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
1178 mTcgServerAcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
1180 // The ACPI table must be checksumed before calling the InstallAcpiTable()
1181 // service of the ACPI table protocol to install it.
1183 Checksum
= CalculateCheckSum8 ((UINT8
*)&mTcgServerAcpiTemplate
, sizeof (mTcgServerAcpiTemplate
));
1184 mTcgServerAcpiTemplate
.Header
.Checksum
= Checksum
;
1186 Status
= AcpiTable
->InstallAcpiTable (
1188 &mTcgServerAcpiTemplate
,
1189 sizeof (mTcgServerAcpiTemplate
),
1194 if (EFI_ERROR (Status
)) {
1195 DEBUG((EFI_D_ERROR
, "Tcg Acpi Table installation failure"));
1200 Exit Boot Services Event notification handler.
1202 Measure invocation and success of ExitBootServices.
1204 @param[in] Event Event whose notification function is being invoked
1205 @param[in] Context Pointer to the notification function's context
1210 OnExitBootServices (
1218 // Measure invocation of ExitBootServices,
1220 Status
= TcgMeasureAction (
1221 EFI_EXIT_BOOT_SERVICES_INVOCATION
1223 if (EFI_ERROR (Status
)) {
1224 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION
));
1228 // Measure success of ExitBootServices
1230 Status
= TcgMeasureAction (
1231 EFI_EXIT_BOOT_SERVICES_SUCCEEDED
1233 if (EFI_ERROR (Status
)){
1234 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED
));
1239 Exit Boot Services Failed Event notification handler.
1241 Measure Failure of ExitBootServices.
1243 @param[in] Event Event whose notification function is being invoked
1244 @param[in] Context Pointer to the notification function's context
1249 OnExitBootServicesFailed (
1257 // Measure Failure of ExitBootServices,
1259 Status
= TcgMeasureAction (
1260 EFI_EXIT_BOOT_SERVICES_FAILED
1262 if (EFI_ERROR (Status
)){
1263 DEBUG ((EFI_D_ERROR
, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED
));
1268 Get TPM Deactivated state.
1270 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.
1272 @retval EFI_SUCCESS Operation completed successfully.
1273 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
1278 OUT BOOLEAN
*TPMDeactivatedFlag
1282 TPM_STCLEAR_FLAGS VFlags
;
1284 Status
= TpmCommGetFlags (
1285 mTcgDxeData
.TpmHandle
,
1286 TPM_CAP_FLAG_VOLATILE
,
1290 if (!EFI_ERROR (Status
)) {
1291 *TPMDeactivatedFlag
= VFlags
.deactivated
;
1298 The driver's entry point.
1300 It publishes EFI TCG Protocol.
1302 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1303 @param[in] SystemTable A pointer to the EFI System Table.
1305 @retval EFI_SUCCESS The entry point is executed successfully.
1306 @retval other Some error occurs when executing this entry point.
1312 IN EFI_HANDLE ImageHandle
,
1313 IN EFI_SYSTEM_TABLE
*SystemTable
1320 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm12Guid
)){
1321 DEBUG ((EFI_D_ERROR
, "No TPM12 instance required!\n"));
1322 return EFI_UNSUPPORTED
;
1325 if (GetFirstGuidHob (&gTpmErrorHobGuid
) != NULL
) {
1326 DEBUG ((EFI_D_ERROR
, "TPM error!\n"));
1327 return EFI_DEVICE_ERROR
;
1330 mTcgDxeData
.TpmHandle
= (TIS_TPM_HANDLE
)(UINTN
)TPM_BASE_ADDRESS
;
1331 Status
= TisPcRequestUseTpm (mTcgDxeData
.TpmHandle
);
1332 if (EFI_ERROR (Status
)) {
1333 DEBUG ((EFI_D_ERROR
, "TPM not detected!\n"));
1337 Status
= GetTpmStatus (&mTcgDxeData
.BsCap
.TPMDeactivatedFlag
);
1338 if (EFI_ERROR (Status
)) {
1341 "Line %d in file " __FILE__
":\n "
1342 "DriverEntry: TPM not working properly\n",
1348 Status
= gBS
->InstallProtocolInterface (
1350 &gEfiTcgProtocolGuid
,
1351 EFI_NATIVE_INTERFACE
,
1352 &mTcgDxeData
.TcgProtocol
1354 if (!EFI_ERROR (Status
) && (!mTcgDxeData
.BsCap
.TPMDeactivatedFlag
) && mTcgDxeData
.BsCap
.TPMPresentFlag
) {
1356 // Setup the log area and copy event log from hob list to it
1358 Status
= SetupEventLog ();
1359 ASSERT_EFI_ERROR (Status
);
1362 // Measure handoff tables, Boot#### variables etc.
1364 Status
= EfiCreateEventReadyToBootEx (
1371 Status
= gBS
->CreateEventEx (
1376 &gEfiEventExitBootServicesGuid
,
1381 // Measure Exit Boot Service failed
1383 Status
= gBS
->CreateEventEx (
1386 OnExitBootServicesFailed
,
1388 &gEventExitBootServicesFailedGuid
,
1394 // Install ACPI Table
1396 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid
, TPL_CALLBACK
, InstallAcpiTable
, NULL
, &Registration
);