2 It updates TPM2 items in ACPI table and registers SMI2 callback
3 functions for Tcg2 physical presence, ClearMemory, and sample
6 Caution: This module requires additional review when modified.
7 This driver will have external input - variable and ACPINvs data in SMM mode.
8 This external input must be validated carefully to avoid security issue.
10 PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
12 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
13 SPDX-License-Identifier: BSD-2-Clause-Patent
20 EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate
= {
22 EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE
,
23 sizeof (mTpm2AcpiTemplate
),
24 EFI_TPM2_ACPI_TABLE_REVISION
,
26 // Compiler initializes the remaining bytes to 0
27 // These fields should be filled in in production
30 0, // BIT0~15: PlatformClass
33 EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
, // StartMethod
36 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
;
40 Software SMI callback for TPM physical presence which is called from ACPI method.
42 Caution: This function may receive untrusted input.
43 Variable and ACPINvs are external input, so this function will validate
44 its data structure to be valid value.
46 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
47 @param[in] Context Points to an optional handler context which was specified when the
48 handler was registered.
49 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
50 be conveyed from a non-SMM environment into an SMM environment.
51 @param[in, out] CommBufferSize The size of the CommBuffer.
53 @retval EFI_SUCCESS The interrupt was handled successfully.
58 PhysicalPresenceCallback (
59 IN EFI_HANDLE DispatchHandle
,
60 IN CONST VOID
*Context
,
61 IN OUT VOID
*CommBuffer
,
62 IN OUT UINTN
*CommBufferSize
65 UINT32 MostRecentRequest
;
67 UINT32 OperationRequest
;
68 UINT32 RequestParameter
;
71 if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS
) {
72 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
76 mTcgNvs
->PhysicalPresence
.LastRequest
= MostRecentRequest
;
77 mTcgNvs
->PhysicalPresence
.Response
= Response
;
79 } else if ((mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS
)
80 || (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2
)) {
82 OperationRequest
= mTcgNvs
->PhysicalPresence
.Request
;
83 RequestParameter
= mTcgNvs
->PhysicalPresence
.RequestParameter
;
84 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
88 mTcgNvs
->PhysicalPresence
.Request
= OperationRequest
;
89 mTcgNvs
->PhysicalPresence
.RequestParameter
= RequestParameter
;
90 } else if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST
) {
91 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs
->PPRequestUserConfirm
);
99 Software SMI callback for MemoryClear which is called from ACPI method.
101 Caution: This function may receive untrusted input.
102 Variable and ACPINvs are external input, so this function will validate
103 its data structure to be valid value.
105 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
106 @param[in] Context Points to an optional handler context which was specified when the
107 handler was registered.
108 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
109 be conveyed from a non-SMM environment into an SMM environment.
110 @param[in, out] CommBufferSize The size of the CommBuffer.
112 @retval EFI_SUCCESS The interrupt was handled successfully.
117 MemoryClearCallback (
118 IN EFI_HANDLE DispatchHandle
,
119 IN CONST VOID
*Context
,
120 IN OUT VOID
*CommBuffer
,
121 IN OUT UINTN
*CommBufferSize
128 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_SUCCESS
;
129 if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE
) {
130 MorControl
= (UINT8
) mTcgNvs
->MemoryClear
.Request
;
131 } else if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_PTS_CLEAR_MOR_BIT
) {
132 DataSize
= sizeof (UINT8
);
133 Status
= mSmmVariable
->SmmGetVariable (
134 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
135 &gEfiMemoryOverwriteControlDataGuid
,
140 if (EFI_ERROR (Status
)) {
141 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
142 DEBUG ((EFI_D_ERROR
, "[TPM] Get MOR variable failure! Status = %r\n", Status
));
146 if (MOR_CLEAR_MEMORY_VALUE (MorControl
) == 0x0) {
149 MorControl
&= ~MOR_CLEAR_MEMORY_BIT_MASK
;
151 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
152 DEBUG ((EFI_D_ERROR
, "[TPM] MOR Parameter error! Parameter = %x\n", mTcgNvs
->MemoryClear
.Parameter
));
156 DataSize
= sizeof (UINT8
);
157 Status
= mSmmVariable
->SmmSetVariable (
158 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
159 &gEfiMemoryOverwriteControlDataGuid
,
160 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
164 if (EFI_ERROR (Status
)) {
165 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
166 DEBUG ((EFI_D_ERROR
, "[TPM] Set MOR variable failure! Status = %r\n", Status
));
173 Find the operation region in TCG ACPI table by given Name and Size,
174 and initialize it if the region is found.
176 @param[in, out] Table The TPM item in ACPI table.
177 @param[in] Name The name string to find in TPM table.
178 @param[in] Size The size of the region to find.
180 @return The allocated address for the found region.
185 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
191 AML_OP_REGION_32_8
*OpRegion
;
192 EFI_PHYSICAL_ADDRESS MemoryAddress
;
194 MemoryAddress
= SIZE_4GB
- 1;
197 // Patch some pointers for the ASL code before loading the SSDT.
199 for (OpRegion
= (AML_OP_REGION_32_8
*) (Table
+ 1);
200 OpRegion
<= (AML_OP_REGION_32_8
*) ((UINT8
*) Table
+ Table
->Length
);
201 OpRegion
= (AML_OP_REGION_32_8
*) ((UINT8
*) OpRegion
+ 1)) {
202 if ((OpRegion
->OpRegionOp
== AML_EXT_REGION_OP
) &&
203 (OpRegion
->NameString
== Name
) &&
204 (OpRegion
->DWordPrefix
== AML_DWORD_PREFIX
) &&
205 (OpRegion
->BytePrefix
== AML_BYTE_PREFIX
)) {
207 Status
= gBS
->AllocatePages(AllocateMaxAddress
, EfiACPIMemoryNVS
, EFI_SIZE_TO_PAGES (Size
), &MemoryAddress
);
208 ASSERT_EFI_ERROR (Status
);
209 ZeroMem ((VOID
*)(UINTN
)MemoryAddress
, Size
);
210 OpRegion
->RegionOffset
= (UINT32
) (UINTN
) MemoryAddress
;
211 OpRegion
->RegionLen
= (UINT8
) Size
;
216 return (VOID
*) (UINTN
) MemoryAddress
;
220 Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
223 @param[in, out] Table The TPM item in ACPI table.
224 @param[in] PPVer Version string of Physical Presence interface supported by platform.
226 @return The allocated address for the found region.
231 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
239 // Patch some pointers for the ASL code before loading the SSDT.
241 for (DataPtr
= (UINT8
*)(Table
+ 1);
242 DataPtr
<= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- PHYSICAL_PRESENCE_VERSION_SIZE
);
244 if (AsciiStrCmp((CHAR8
*)DataPtr
, PHYSICAL_PRESENCE_VERSION_TAG
) == 0) {
245 Status
= AsciiStrCpyS((CHAR8
*)DataPtr
, PHYSICAL_PRESENCE_VERSION_SIZE
, PPVer
);
246 DEBUG((EFI_D_INFO
, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status
));
251 return EFI_NOT_FOUND
;
255 Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input
256 interrupt buffer size. BufferSize, PkgLength and interrupt descirptor in ByteList need to be patched
258 @param[in, out] Table The TPM item in ACPI table.
259 @param[in] IrqBuffer Input new IRQ buffer.
260 @param[in] IrqBuffserSize Input new IRQ buffer size.
261 @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).
263 @return patch status.
267 UpdatePossibleResource (
268 IN OUT EFI_ACPI_DESCRIPTION_HEADER
*Table
,
269 IN UINT32
*IrqBuffer
,
270 IN UINT32 IrqBuffserSize
,
271 OUT BOOLEAN
*IsShortFormPkgLength
277 UINT32 OrignalPkgLength
;
280 OrignalPkgLength
= 0;
285 // 6.4.3 Extend Interrupt Descriptor.
286 // 19.3.3 ASL Resource Template
287 // 20 AML specification
288 // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
290 // AML data is organized by following rule.
291 // Code need to patch BufferSize and PkgLength and interrupt descirptor in ByteList
293 // ============= Buffer ====================
294 // DefBuffer := BufferOp PkgLength BufferSize ByteList
297 // ==============PkgLength==================
298 // PkgLength := PkgLeadByte |
299 // <PkgLeadByte ByteData> |
300 // <PkgLeadByte ByteData ByteData> |
301 // <PkgLeadByte ByteData ByteData ByteData>
303 // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
304 // <bit 5-4: Only used if PkgLength <= 63 >
305 // <bit 3-0: Least significant package length nybble>
307 //==============BufferSize==================
308 // BufferSize := Integar
309 // Integar := ByteConst|WordConst|DwordConst....
311 // ByteConst := BytePrefix ByteData
313 //==============ByteList===================
314 // ByteList := ByteData ByteList
316 //=========================================
319 // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
321 for (DataPtr
= (UINT8
*)(Table
+ 1);
322 DataPtr
< (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- (TPM_PRS_RES_NAME_SIZE
+ TPM_POS_RES_TEMPLATE_MIN_SIZE
));
324 if (CompareMem(DataPtr
, TPM_PRS_RESS
, TPM_PRS_RES_NAME_SIZE
) == 0) {
326 // Jump over object name & BufferOp
328 DataPtr
+= TPM_PRS_RES_NAME_SIZE
+ 1;
330 if ((*DataPtr
& (BIT7
|BIT6
)) == 0) {
331 OrignalPkgLength
= (UINT32
)*DataPtr
;
332 DataEndPtr
= DataPtr
+ OrignalPkgLength
;
335 // Jump over PkgLength = PkgLeadByte only
340 // Jump over BufferSize
342 if (*(DataPtr
+ 1) == AML_BYTE_PREFIX
) {
344 } else if (*(DataPtr
+ 1) == AML_WORD_PREFIX
) {
346 } else if (*(DataPtr
+ 1) == AML_DWORD_PREFIX
) {
350 return EFI_UNSUPPORTED
;
354 return EFI_UNSUPPORTED
;
358 // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
360 NewPkgLength
+= 19 + IrqBuffserSize
;
361 if (NewPkgLength
> 63) {
365 if (NewPkgLength
> OrignalPkgLength
) {
367 return EFI_INVALID_PARAMETER
;
371 // 1.1 Patch PkgLength
373 *DataPtr
= (UINT8
)NewPkgLength
;
376 // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
377 // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
379 *(DataPtr
+ 2) = (UINT8
)(IrqBuffserSize
+ 19);
382 // Notify _PRS to report short formed ResourceTemplate
384 *IsShortFormPkgLength
= TRUE
;
391 // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
393 if (NewPkgLength
> 63) {
395 OrignalPkgLength
= 0;
396 for (DataPtr
= (UINT8
*)(Table
+ 1);
397 DataPtr
< (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- (TPM_PRS_RES_NAME_SIZE
+ TPM_POS_RES_TEMPLATE_MIN_SIZE
));
399 if (CompareMem(DataPtr
, TPM_PRS_RESL
, TPM_PRS_RES_NAME_SIZE
) == 0) {
401 // Jump over object name & BufferOp
403 DataPtr
+= TPM_PRS_RES_NAME_SIZE
+ 1;
405 if ((*DataPtr
& (BIT7
|BIT6
)) != 0) {
406 OrignalPkgLength
= (UINT32
)(*(DataPtr
+ 1) << 4) + (*DataPtr
& 0x0F);
407 DataEndPtr
= DataPtr
+ OrignalPkgLength
;
409 // Jump over PkgLength = PkgLeadByte + ByteData length
411 NewPkgLength
+= 1 + ((*DataPtr
& (BIT7
|BIT6
)) >> 6);
414 // Jump over BufferSize
416 if (*(DataPtr
+ NewPkgLength
) == AML_BYTE_PREFIX
) {
418 } else if (*(DataPtr
+ NewPkgLength
) == AML_WORD_PREFIX
) {
420 } else if (*(DataPtr
+ NewPkgLength
) == AML_DWORD_PREFIX
) {
424 return EFI_UNSUPPORTED
;
428 return EFI_UNSUPPORTED
;
432 // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
434 NewPkgLength
+= 19 + IrqBuffserSize
;
436 if (NewPkgLength
> OrignalPkgLength
) {
438 return EFI_INVALID_PARAMETER
;
442 // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
444 *DataPtr
= (UINT8
)((*DataPtr
) & 0xF0) | (NewPkgLength
& 0x0F);
445 *(DataPtr
+ 1) = (UINT8
)((NewPkgLength
& 0xFF0) >> 4);
448 // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
449 // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
451 *(DataPtr
+ 2 + ((*DataPtr
& (BIT7
|BIT6
)) >> 6)) = (UINT8
)(IrqBuffserSize
+ 19);
454 // Notify _PRS to report long formed ResourceTemplate
456 *IsShortFormPkgLength
= FALSE
;
462 if (DataPtr
>= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- (TPM_PRS_RES_NAME_SIZE
+ TPM_POS_RES_TEMPLATE_MIN_SIZE
))) {
463 return EFI_NOT_FOUND
;
467 // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
468 // 5 bytes for interrupt descriptor header, 2 bytes for End Tag
470 DataPtr
+= NewPkgLength
- (5 + IrqBuffserSize
+ 2);
472 // 3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt descriptor
474 *(DataPtr
+ 1) = (UINT8
)(2 + IrqBuffserSize
);
476 // 3.2 Patch Interrupt Table Length
478 *(DataPtr
+ 4) = (UINT8
)(IrqBuffserSize
/ sizeof(UINT32
));
480 // 3.3 Copy patched InterruptNumBuffer
482 CopyMem(DataPtr
+ 5, IrqBuffer
, IrqBuffserSize
);
485 // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field to 0
487 DataPtr
+= 5 + IrqBuffserSize
;
488 *DataPtr
= ACPI_END_TAG_DESCRIPTOR
;
492 // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
495 if (DataPtr
< DataEndPtr
) {
496 SetMem(DataPtr
, (UINTN
)DataEndPtr
- (UINTN
)DataPtr
, AML_NOOP_OP
);
503 Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".
505 @param[in, out] Table The TPM2 SSDT ACPI table.
507 @return HID Update status.
512 EFI_ACPI_DESCRIPTION_HEADER
*Table
517 CHAR8 Hid
[TPM_HID_ACPI_SIZE
];
518 UINT32 ManufacturerID
;
519 UINT32 FirmwareVersion1
;
520 UINT32 FirmwareVersion2
;
526 // Initialize HID with Default PNP string
528 ZeroMem(Hid
, TPM_HID_ACPI_SIZE
);
531 // Get Manufacturer ID
533 Status
= Tpm2GetCapabilityManufactureID(&ManufacturerID
);
534 if (!EFI_ERROR(Status
)) {
535 DEBUG((EFI_D_INFO
, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID
));
537 // ManufacturerID defined in TCG Vendor ID Registry
538 // may tailed with 0x00 or 0x20
540 if ((ManufacturerID
>> 24) == 0x00 || ((ManufacturerID
>> 24) == 0x20)) {
542 // HID containing PNP ID "NNN####"
543 // NNN is uppercase letter for Vendor ID specified by manufacturer
545 CopyMem(Hid
, &ManufacturerID
, 3);
548 // HID containing ACP ID "NNNN####"
549 // NNNN is uppercase letter for Vendor ID specified by manufacturer
551 CopyMem(Hid
, &ManufacturerID
, 4);
555 DEBUG ((EFI_D_ERROR
, "Get TPM_PT_MANUFACTURER failed %x!\n", Status
));
560 Status
= Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1
, &FirmwareVersion2
);
561 if (!EFI_ERROR(Status
)) {
562 DEBUG((EFI_D_INFO
, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1
));
563 DEBUG((EFI_D_INFO
, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2
));
565 // #### is Firmware Version 1
568 AsciiSPrint(Hid
+ 3, TPM_HID_PNP_SIZE
- 3, "%02d%02d", ((FirmwareVersion1
& 0xFFFF0000) >> 16), (FirmwareVersion1
& 0x0000FFFF));
570 AsciiSPrint(Hid
+ 4, TPM_HID_ACPI_SIZE
- 4, "%02d%02d", ((FirmwareVersion1
& 0xFFFF0000) >> 16), (FirmwareVersion1
& 0x0000FFFF));
574 DEBUG ((EFI_D_ERROR
, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status
));
580 // Patch HID in ASL code before loading the SSDT.
582 for (DataPtr
= (UINT8
*)(Table
+ 1);
583 DataPtr
<= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- TPM_HID_PNP_SIZE
);
585 if (AsciiStrCmp((CHAR8
*)DataPtr
, TPM_HID_TAG
) == 0) {
587 CopyMem(DataPtr
, Hid
, TPM_HID_PNP_SIZE
);
589 // if HID is PNP ID, patch the last byte in HID TAG to Noop
591 *(DataPtr
+ TPM_HID_PNP_SIZE
) = AML_NOOP_OP
;
594 CopyMem(DataPtr
, Hid
, TPM_HID_ACPI_SIZE
);
596 DEBUG((DEBUG_INFO
, "TPM2 ACPI _HID is patched to %a\n", DataPtr
));
602 DEBUG((EFI_D_ERROR
, "TPM2 ACPI HID TAG for patch not found!\n"));
603 return EFI_NOT_FOUND
;
607 Initialize and publish TPM items in ACPI table.
609 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
610 @retval Others The TCG ACPI table is not published.
619 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
621 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
623 UINT32
*PossibleIrqNumBuf
;
624 UINT32 PossibleIrqNumBufSize
;
625 BOOLEAN IsShortFormPkgLength
;
627 IsShortFormPkgLength
= FALSE
;
629 Status
= GetSectionFromFv (
636 ASSERT_EFI_ERROR (Status
);
639 // Update Table version before measuring it to PCR
641 Status
= UpdatePPVersion(Table
, (CHAR8
*)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer
));
642 ASSERT_EFI_ERROR (Status
);
646 "Current physical presence interface version - %a\n",
647 (CHAR8
*) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer
)
651 // Update TPM2 HID before measuring it to PCR
653 Status
= UpdateHID(Table
);
654 if (EFI_ERROR(Status
)) {
658 if (PcdGet32(PcdTpm2CurrentIrqNum
) != 0) {
660 // Patch _PRS interrupt resource only when TPM interrupt is supported
662 PossibleIrqNumBuf
= (UINT32
*)PcdGetPtr(PcdTpm2PossibleIrqNumBuf
);
663 PossibleIrqNumBufSize
= (UINT32
)PcdGetSize(PcdTpm2PossibleIrqNumBuf
);
665 if (PossibleIrqNumBufSize
<= MAX_PRS_INT_BUF_SIZE
&& (PossibleIrqNumBufSize
% sizeof(UINT32
)) == 0) {
666 Status
= UpdatePossibleResource(Table
, PossibleIrqNumBuf
, PossibleIrqNumBufSize
, &IsShortFormPkgLength
);
669 "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",
675 "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",
676 PossibleIrqNumBufSize
682 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
684 TpmMeasureAndLogData(
687 EV_POSTCODE_INFO_ACPI_DATA
,
694 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
695 CopyMem (Table
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (Table
->OemId
) );
696 mTcgNvs
= AssignOpRegion (Table
, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16
) sizeof (TCG_NVS
));
697 ASSERT (mTcgNvs
!= NULL
);
698 mTcgNvs
->TpmIrqNum
= PcdGet32(PcdTpm2CurrentIrqNum
);
699 mTcgNvs
->IsShortFormPkgLength
= IsShortFormPkgLength
;
702 // Publish the TPM ACPI table. Table is re-checksumed.
704 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
705 ASSERT_EFI_ERROR (Status
);
708 Status
= AcpiTable
->InstallAcpiTable (
714 ASSERT_EFI_ERROR (Status
);
720 Publish TPM2 ACPI table
722 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
723 @retval Others The TPM2 ACPI table is not published.
732 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
735 EFI_TPM2_ACPI_CONTROL_AREA
*ControlArea
;
736 TPM2_PTP_INTERFACE_TYPE InterfaceType
;
738 mTpm2AcpiTemplate
.Header
.Revision
= PcdGet8(PcdTpm2AcpiTableRev
);
739 DEBUG((DEBUG_INFO
, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate
.Header
.Revision
));
742 // PlatformClass is only valid for version 4 and above
743 // BIT0~15: PlatformClass
744 // BIT16~31: Reserved
746 if (mTpm2AcpiTemplate
.Header
.Revision
>= EFI_TPM2_ACPI_TABLE_REVISION_4
) {
747 mTpm2AcpiTemplate
.Flags
= (mTpm2AcpiTemplate
.Flags
& 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass
);
748 DEBUG((DEBUG_INFO
, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate
.Flags
& 0x0000FFFF)));
752 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
754 TpmMeasureAndLogData(
757 EV_POSTCODE_INFO_ACPI_DATA
,
760 sizeof(mTpm2AcpiTemplate
)
763 InterfaceType
= PcdGet8(PcdActiveTpmInterfaceType
);
764 switch (InterfaceType
) {
765 case Tpm2PtpInterfaceCrb
:
766 mTpm2AcpiTemplate
.StartMethod
= EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE
;
767 mTpm2AcpiTemplate
.AddressOfControlArea
= PcdGet64 (PcdTpmBaseAddress
) + 0x40;
768 ControlArea
= (EFI_TPM2_ACPI_CONTROL_AREA
*)(UINTN
)mTpm2AcpiTemplate
.AddressOfControlArea
;
769 ControlArea
->CommandSize
= 0xF80;
770 ControlArea
->ResponseSize
= 0xF80;
771 ControlArea
->Command
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
772 ControlArea
->Response
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
774 case Tpm2PtpInterfaceFifo
:
775 case Tpm2PtpInterfaceTis
:
778 DEBUG((EFI_D_ERROR
, "TPM2 InterfaceType get error! %d\n", InterfaceType
));
782 CopyMem (mTpm2AcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTpm2AcpiTemplate
.Header
.OemId
));
783 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
784 CopyMem (&mTpm2AcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
785 mTpm2AcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
786 mTpm2AcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
787 mTpm2AcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
790 // Construct ACPI table
792 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
793 ASSERT_EFI_ERROR (Status
);
795 Status
= AcpiTable
->InstallAcpiTable (
798 sizeof(mTpm2AcpiTemplate
),
801 ASSERT_EFI_ERROR (Status
);
807 The driver's entry point.
809 It install callbacks for TPM physical presence and MemoryClear, and locate
810 SMM variable to be used in the callback function.
812 @param[in] ImageHandle The firmware allocated handle for the EFI image.
813 @param[in] SystemTable A pointer to the EFI System Table.
815 @retval EFI_SUCCESS The entry point is executed successfully.
816 @retval Others Some error occurs when executing this entry point.
822 IN EFI_HANDLE ImageHandle
,
823 IN EFI_SYSTEM_TABLE
*SystemTable
827 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
828 EFI_SMM_SW_REGISTER_CONTEXT SwContext
;
831 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm20DtpmGuid
)){
832 DEBUG ((EFI_D_ERROR
, "No TPM2 DTPM instance required!\n"));
833 return EFI_UNSUPPORTED
;
836 Status
= PublishAcpiTable ();
837 ASSERT_EFI_ERROR (Status
);
840 // Get the Sw dispatch protocol and register SMI callback functions.
842 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid
, NULL
, (VOID
**)&SwDispatch
);
843 ASSERT_EFI_ERROR (Status
);
844 SwContext
.SwSmiInputValue
= (UINTN
) -1;
845 Status
= SwDispatch
->Register (SwDispatch
, PhysicalPresenceCallback
, &SwContext
, &SwHandle
);
846 ASSERT_EFI_ERROR (Status
);
847 if (EFI_ERROR (Status
)) {
850 mTcgNvs
->PhysicalPresence
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
852 SwContext
.SwSmiInputValue
= (UINTN
) -1;
853 Status
= SwDispatch
->Register (SwDispatch
, MemoryClearCallback
, &SwContext
, &SwHandle
);
854 ASSERT_EFI_ERROR (Status
);
855 if (EFI_ERROR (Status
)) {
858 mTcgNvs
->MemoryClear
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
861 // Locate SmmVariableProtocol.
863 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
864 ASSERT_EFI_ERROR (Status
);
867 // Set TPM2 ACPI table
869 Status
= PublishTpm2 ();
870 ASSERT_EFI_ERROR (Status
);