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 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.
26 EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate
= {
28 EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE
,
29 sizeof (mTpm2AcpiTemplate
),
30 EFI_TPM2_ACPI_TABLE_REVISION
,
32 // Compiler initializes the remaining bytes to 0
33 // These fields should be filled in in production
36 0, // BIT0~15: PlatformClass
39 EFI_TPM2_ACPI_TABLE_START_METHOD_TIS
, // StartMethod
42 EFI_SMM_VARIABLE_PROTOCOL
*mSmmVariable
;
46 Software SMI callback for TPM physical presence which is called from ACPI method.
48 Caution: This function may receive untrusted input.
49 Variable and ACPINvs are external input, so this function will validate
50 its data structure to be valid value.
52 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
53 @param[in] Context Points to an optional handler context which was specified when the
54 handler was registered.
55 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
56 be conveyed from a non-SMM environment into an SMM environment.
57 @param[in, out] CommBufferSize The size of the CommBuffer.
59 @retval EFI_SUCCESS The interrupt was handled successfully.
64 PhysicalPresenceCallback (
65 IN EFI_HANDLE DispatchHandle
,
66 IN CONST VOID
*Context
,
67 IN OUT VOID
*CommBuffer
,
68 IN OUT UINTN
*CommBufferSize
71 UINT32 MostRecentRequest
;
73 UINT32 OperationRequest
;
74 UINT32 RequestParameter
;
77 if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS
) {
78 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
82 mTcgNvs
->PhysicalPresence
.LastRequest
= MostRecentRequest
;
83 mTcgNvs
->PhysicalPresence
.Response
= Response
;
85 } else if ((mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS
)
86 || (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2
)) {
88 OperationRequest
= mTcgNvs
->PhysicalPresence
.Request
;
89 RequestParameter
= mTcgNvs
->PhysicalPresence
.RequestParameter
;
90 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
94 mTcgNvs
->PhysicalPresence
.Request
= OperationRequest
;
95 mTcgNvs
->PhysicalPresence
.RequestParameter
= RequestParameter
;
96 } else if (mTcgNvs
->PhysicalPresence
.Parameter
== TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST
) {
97 mTcgNvs
->PhysicalPresence
.ReturnCode
= Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs
->PPRequestUserConfirm
);
105 Software SMI callback for MemoryClear which is called from ACPI method.
107 Caution: This function may receive untrusted input.
108 Variable and ACPINvs are external input, so this function will validate
109 its data structure to be valid value.
111 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
112 @param[in] Context Points to an optional handler context which was specified when the
113 handler was registered.
114 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
115 be conveyed from a non-SMM environment into an SMM environment.
116 @param[in, out] CommBufferSize The size of the CommBuffer.
118 @retval EFI_SUCCESS The interrupt was handled successfully.
123 MemoryClearCallback (
124 IN EFI_HANDLE DispatchHandle
,
125 IN CONST VOID
*Context
,
126 IN OUT VOID
*CommBuffer
,
127 IN OUT UINTN
*CommBufferSize
134 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_SUCCESS
;
135 if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE
) {
136 MorControl
= (UINT8
) mTcgNvs
->MemoryClear
.Request
;
137 } else if (mTcgNvs
->MemoryClear
.Parameter
== ACPI_FUNCTION_PTS_CLEAR_MOR_BIT
) {
138 DataSize
= sizeof (UINT8
);
139 Status
= mSmmVariable
->SmmGetVariable (
140 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
141 &gEfiMemoryOverwriteControlDataGuid
,
146 if (EFI_ERROR (Status
)) {
147 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
148 DEBUG ((EFI_D_ERROR
, "[TPM] Get MOR variable failure! Status = %r\n", Status
));
152 if (MOR_CLEAR_MEMORY_VALUE (MorControl
) == 0x0) {
155 MorControl
&= ~MOR_CLEAR_MEMORY_BIT_MASK
;
158 DataSize
= sizeof (UINT8
);
159 Status
= mSmmVariable
->SmmSetVariable (
160 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME
,
161 &gEfiMemoryOverwriteControlDataGuid
,
162 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
166 if (EFI_ERROR (Status
)) {
167 mTcgNvs
->MemoryClear
.ReturnCode
= MOR_REQUEST_GENERAL_FAILURE
;
168 DEBUG ((EFI_D_ERROR
, "[TPM] Set MOR variable failure! Status = %r\n", Status
));
175 Find the operation region in TCG ACPI table by given Name and Size,
176 and initialize it if the region is found.
178 @param[in, out] Table The TPM item in ACPI table.
179 @param[in] Name The name string to find in TPM table.
180 @param[in] Size The size of the region to find.
182 @return The allocated address for the found region.
187 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
193 AML_OP_REGION_32_8
*OpRegion
;
194 EFI_PHYSICAL_ADDRESS MemoryAddress
;
196 MemoryAddress
= SIZE_4GB
- 1;
199 // Patch some pointers for the ASL code before loading the SSDT.
201 for (OpRegion
= (AML_OP_REGION_32_8
*) (Table
+ 1);
202 OpRegion
<= (AML_OP_REGION_32_8
*) ((UINT8
*) Table
+ Table
->Length
);
203 OpRegion
= (AML_OP_REGION_32_8
*) ((UINT8
*) OpRegion
+ 1)) {
204 if ((OpRegion
->OpRegionOp
== AML_EXT_REGION_OP
) &&
205 (OpRegion
->NameString
== Name
) &&
206 (OpRegion
->DWordPrefix
== AML_DWORD_PREFIX
) &&
207 (OpRegion
->BytePrefix
== AML_BYTE_PREFIX
)) {
209 Status
= gBS
->AllocatePages(AllocateMaxAddress
, EfiACPIMemoryNVS
, EFI_SIZE_TO_PAGES (Size
), &MemoryAddress
);
210 ASSERT_EFI_ERROR (Status
);
211 ZeroMem ((VOID
*)(UINTN
)MemoryAddress
, Size
);
212 OpRegion
->RegionOffset
= (UINT32
) (UINTN
) MemoryAddress
;
213 OpRegion
->RegionLen
= (UINT8
) Size
;
218 return (VOID
*) (UINTN
) MemoryAddress
;
222 Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
225 @param[in, out] Table The TPM item in ACPI table.
226 @param[in] PPVer Version string of Physical Presence interface supported by platform.
228 @return The allocated address for the found region.
233 EFI_ACPI_DESCRIPTION_HEADER
*Table
,
241 // Patch some pointers for the ASL code before loading the SSDT.
243 for (DataPtr
= (UINT8
*)(Table
+ 1);
244 DataPtr
<= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- PHYSICAL_PRESENCE_VERSION_SIZE
);
246 if (AsciiStrCmp((CHAR8
*)DataPtr
, PHYSICAL_PRESENCE_VERSION_TAG
) == 0) {
247 Status
= AsciiStrCpyS((CHAR8
*)DataPtr
, PHYSICAL_PRESENCE_VERSION_SIZE
, PPVer
);
248 DEBUG((EFI_D_INFO
, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status
));
253 return EFI_NOT_FOUND
;
257 Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input
258 interrupt buffer size. BufferSize, PkgLength and interrupt descirptor in ByteList need to be patched
260 @param[in, out] Table The TPM item in ACPI table.
261 @param[in] IrqBuffer Input new IRQ buffer.
262 @param[in] IrqBuffserSize Input new IRQ buffer size.
263 @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).
265 @return patch status.
269 UpdatePossibleResource (
270 IN OUT EFI_ACPI_DESCRIPTION_HEADER
*Table
,
271 IN UINT32
*IrqBuffer
,
272 IN UINT32 IrqBuffserSize
,
273 OUT BOOLEAN
*IsShortFormPkgLength
279 UINT32 OrignalPkgLength
;
282 OrignalPkgLength
= 0;
287 // 6.4.3 Extend Interrupt Descriptor.
288 // 19.3.3 ASL Resource Template
289 // 20 AML specification
290 // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
292 // AML data is organized by following rule.
293 // Code need to patch BufferSize and PkgLength and interrupt descirptor in ByteList
295 // ============= Buffer ====================
296 // DefBuffer := BufferOp PkgLength BufferSize ByteList
299 // ==============PkgLength==================
300 // PkgLength := PkgLeadByte |
301 // <PkgLeadByte ByteData> |
302 // <PkgLeadByte ByteData ByteData> |
303 // <PkgLeadByte ByteData ByteData ByteData>
305 // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
306 // <bit 5-4: Only used if PkgLength <= 63 >
307 // <bit 3-0: Least significant package length nybble>
309 //==============BufferSize==================
310 // BufferSize := Integar
311 // Integar := ByteConst|WordConst|DwordConst....
313 // ByteConst := BytePrefix ByteData
315 //==============ByteList===================
316 // ByteList := ByteData ByteList
318 //=========================================
321 // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
323 for (DataPtr
= (UINT8
*)(Table
+ 1);
324 DataPtr
< (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- (TPM_PRS_RES_NAME_SIZE
+ TPM_POS_RES_TEMPLATE_MIN_SIZE
));
326 if (CompareMem(DataPtr
, TPM_PRS_RESS
, TPM_PRS_RES_NAME_SIZE
) == 0) {
328 // Jump over object name & BufferOp
330 DataPtr
+= TPM_PRS_RES_NAME_SIZE
+ 1;
332 if ((*DataPtr
& (BIT7
|BIT6
)) == 0) {
333 OrignalPkgLength
= (UINT32
)*DataPtr
;
334 DataEndPtr
= DataPtr
+ OrignalPkgLength
;
337 // Jump over PkgLength = PkgLeadByte only
342 // Jump over BufferSize
344 if (*(DataPtr
+ 1) == AML_BYTE_PREFIX
) {
346 } else if (*(DataPtr
+ 1) == AML_WORD_PREFIX
) {
348 } else if (*(DataPtr
+ 1) == AML_DWORD_PREFIX
) {
352 return EFI_UNSUPPORTED
;
356 return EFI_UNSUPPORTED
;
360 // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
362 NewPkgLength
+= 19 + IrqBuffserSize
;
363 if (NewPkgLength
> 63) {
367 if (NewPkgLength
> OrignalPkgLength
) {
369 return EFI_INVALID_PARAMETER
;
373 // 1.1 Patch PkgLength
375 *DataPtr
= (UINT8
)NewPkgLength
;
378 // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
379 // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
381 *(DataPtr
+ 2) = (UINT8
)(IrqBuffserSize
+ 19);
384 // Notify _PRS to report short formed ResourceTemplate
386 *IsShortFormPkgLength
= TRUE
;
393 // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
395 if (NewPkgLength
> 63) {
397 OrignalPkgLength
= 0;
398 for (DataPtr
= (UINT8
*)(Table
+ 1);
399 DataPtr
< (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- (TPM_PRS_RES_NAME_SIZE
+ TPM_POS_RES_TEMPLATE_MIN_SIZE
));
401 if (CompareMem(DataPtr
, TPM_PRS_RESL
, TPM_PRS_RES_NAME_SIZE
) == 0) {
403 // Jump over object name & BufferOp
405 DataPtr
+= TPM_PRS_RES_NAME_SIZE
+ 1;
407 if ((*DataPtr
& (BIT7
|BIT6
)) != 0) {
408 OrignalPkgLength
= (UINT32
)(*(DataPtr
+ 1) << 4) + (*DataPtr
& 0x0F);
409 DataEndPtr
= DataPtr
+ OrignalPkgLength
;
411 // Jump over PkgLength = PkgLeadByte + ByteData length
413 NewPkgLength
+= 1 + ((*DataPtr
& (BIT7
|BIT6
)) >> 6);
416 // Jump over BufferSize
418 if (*(DataPtr
+ NewPkgLength
) == AML_BYTE_PREFIX
) {
420 } else if (*(DataPtr
+ NewPkgLength
) == AML_WORD_PREFIX
) {
422 } else if (*(DataPtr
+ NewPkgLength
) == AML_DWORD_PREFIX
) {
426 return EFI_UNSUPPORTED
;
430 return EFI_UNSUPPORTED
;
434 // Include Memory32Fixed Descritor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
436 NewPkgLength
+= 19 + IrqBuffserSize
;
438 if (NewPkgLength
> OrignalPkgLength
) {
440 return EFI_INVALID_PARAMETER
;
444 // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
446 *DataPtr
= (UINT8
)((*DataPtr
) & 0xF0) | (NewPkgLength
& 0x0F);
447 *(DataPtr
+ 1) = (UINT8
)((NewPkgLength
& 0xFF0) >> 4);
450 // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descritor + Interrupt Descriptor + End Tag).
451 // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
453 *(DataPtr
+ 2 + ((*DataPtr
& (BIT7
|BIT6
)) >> 6)) = (UINT8
)(IrqBuffserSize
+ 19);
456 // Notify _PRS to report long formed ResourceTemplate
458 *IsShortFormPkgLength
= FALSE
;
464 if (DataPtr
>= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- (TPM_PRS_RES_NAME_SIZE
+ TPM_POS_RES_TEMPLATE_MIN_SIZE
))) {
465 return EFI_NOT_FOUND
;
469 // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
470 // 5 bytes for interrupt descriptor header, 2 bytes for End Tag
472 DataPtr
+= NewPkgLength
- (5 + IrqBuffserSize
+ 2);
474 // 3.1 Patch Length bit[7:0] of Interrupt descirptor patch interrupt descriptor
476 *(DataPtr
+ 1) = (UINT8
)(2 + IrqBuffserSize
);
478 // 3.2 Patch Interrupt Table Length
480 *(DataPtr
+ 4) = (UINT8
)(IrqBuffserSize
/ sizeof(UINT32
));
482 // 3.3 Copy patched InterruptNumBuffer
484 CopyMem(DataPtr
+ 5, IrqBuffer
, IrqBuffserSize
);
487 // 4. Jump over Interrupt descirptor and Patch END Tag, set Checksum field to 0
489 DataPtr
+= 5 + IrqBuffserSize
;
490 *DataPtr
= ACPI_END_TAG_DESCRIPTOR
;
494 // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
497 if (DataPtr
< DataEndPtr
) {
498 SetMem(DataPtr
, (UINTN
)DataEndPtr
- (UINTN
)DataPtr
, AML_NOOP_OP
);
505 Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".
507 @param[in, out] Table The TPM2 SSDT ACPI table.
509 @return HID Update status.
514 EFI_ACPI_DESCRIPTION_HEADER
*Table
519 CHAR8 Hid
[TPM_HID_ACPI_SIZE
];
520 UINT32 ManufacturerID
;
521 UINT32 FirmwareVersion1
;
522 UINT32 FirmwareVersion2
;
528 // Initialize HID with Default PNP string
530 ZeroMem(Hid
, TPM_HID_ACPI_SIZE
);
533 // Get Manufacturer ID
535 Status
= Tpm2GetCapabilityManufactureID(&ManufacturerID
);
536 if (!EFI_ERROR(Status
)) {
537 DEBUG((EFI_D_INFO
, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID
));
539 // ManufacturerID defined in TCG Vendor ID Registry
540 // may tailed with 0x00 or 0x20
542 if ((ManufacturerID
>> 24) == 0x00 || ((ManufacturerID
>> 24) == 0x20)) {
544 // HID containing PNP ID "NNN####"
545 // NNN is uppercase letter for Vendor ID specified by manufacturer
547 CopyMem(Hid
, &ManufacturerID
, 3);
550 // HID containing ACP ID "NNNN####"
551 // NNNN is uppercase letter for Vendor ID specified by manufacturer
553 CopyMem(Hid
, &ManufacturerID
, 4);
557 DEBUG ((EFI_D_ERROR
, "Get TPM_PT_MANUFACTURER failed %x!\n", Status
));
562 Status
= Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1
, &FirmwareVersion2
);
563 if (!EFI_ERROR(Status
)) {
564 DEBUG((EFI_D_INFO
, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1
));
565 DEBUG((EFI_D_INFO
, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2
));
567 // #### is Firmware Version 1
570 AsciiSPrint(Hid
+ 3, TPM_HID_PNP_SIZE
- 3, "%02d%02d", ((FirmwareVersion1
& 0xFFFF0000) >> 16), (FirmwareVersion1
& 0x0000FFFF));
572 AsciiSPrint(Hid
+ 4, TPM_HID_ACPI_SIZE
- 4, "%02d%02d", ((FirmwareVersion1
& 0xFFFF0000) >> 16), (FirmwareVersion1
& 0x0000FFFF));
576 DEBUG ((EFI_D_ERROR
, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status
));
582 // Patch HID in ASL code before loading the SSDT.
584 for (DataPtr
= (UINT8
*)(Table
+ 1);
585 DataPtr
<= (UINT8
*) ((UINT8
*) Table
+ Table
->Length
- TPM_HID_PNP_SIZE
);
587 if (AsciiStrCmp((CHAR8
*)DataPtr
, TPM_HID_TAG
) == 0) {
589 CopyMem(DataPtr
, Hid
, TPM_HID_PNP_SIZE
);
591 // if HID is PNP ID, patch the last byte in HID TAG to Noop
593 *(DataPtr
+ TPM_HID_PNP_SIZE
) = AML_NOOP_OP
;
596 CopyMem(DataPtr
, Hid
, TPM_HID_ACPI_SIZE
);
598 DEBUG((DEBUG_INFO
, "TPM2 ACPI _HID is patched to %a\n", DataPtr
));
604 DEBUG((EFI_D_ERROR
, "TPM2 ACPI HID TAG for patch not found!\n"));
605 return EFI_NOT_FOUND
;
609 Initialize and publish TPM items in ACPI table.
611 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
612 @retval Others The TCG ACPI table is not published.
621 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
623 EFI_ACPI_DESCRIPTION_HEADER
*Table
;
625 UINT32
*PossibleIrqNumBuf
;
626 UINT32 PossibleIrqNumBufSize
;
627 BOOLEAN IsShortFormPkgLength
;
629 IsShortFormPkgLength
= FALSE
;
631 Status
= GetSectionFromFv (
638 ASSERT_EFI_ERROR (Status
);
641 // Update Table version before measuring it to PCR
643 Status
= UpdatePPVersion(Table
, (CHAR8
*)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer
));
644 ASSERT_EFI_ERROR (Status
);
648 "Current physical presence interface version - %a\n",
649 (CHAR8
*) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer
)
653 // Update TPM2 HID before measuring it to PCR
655 Status
= UpdateHID(Table
);
656 if (EFI_ERROR(Status
)) {
660 if (PcdGet32(PcdTpm2CurrentIrqNum
) != 0) {
662 // Patch _PRS interrupt resource only when TPM interrupt is supported
664 PossibleIrqNumBuf
= (UINT32
*)PcdGetPtr(PcdTpm2PossibleIrqNumBuf
);
665 PossibleIrqNumBufSize
= (UINT32
)PcdGetSize(PcdTpm2PossibleIrqNumBuf
);
667 if (PossibleIrqNumBufSize
<= MAX_PRS_INT_BUF_SIZE
&& (PossibleIrqNumBufSize
% sizeof(UINT32
)) == 0) {
668 Status
= UpdatePossibleResource(Table
, PossibleIrqNumBuf
, PossibleIrqNumBufSize
, &IsShortFormPkgLength
);
671 "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",
677 "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",
678 PossibleIrqNumBufSize
684 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
686 TpmMeasureAndLogData(
689 EV_POSTCODE_INFO_ACPI_DATA
,
696 ASSERT (Table
->OemTableId
== SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
697 CopyMem (Table
->OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (Table
->OemId
) );
698 mTcgNvs
= AssignOpRegion (Table
, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16
) sizeof (TCG_NVS
));
699 ASSERT (mTcgNvs
!= NULL
);
700 mTcgNvs
->TpmIrqNum
= PcdGet32(PcdTpm2CurrentIrqNum
);
701 mTcgNvs
->IsShortFormPkgLength
= IsShortFormPkgLength
;
704 // Publish the TPM ACPI table. Table is re-checksumed.
706 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
707 ASSERT_EFI_ERROR (Status
);
710 Status
= AcpiTable
->InstallAcpiTable (
716 ASSERT_EFI_ERROR (Status
);
722 Publish TPM2 ACPI table
724 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
725 @retval Others The TPM2 ACPI table is not published.
734 EFI_ACPI_TABLE_PROTOCOL
*AcpiTable
;
737 EFI_TPM2_ACPI_CONTROL_AREA
*ControlArea
;
738 TPM2_PTP_INTERFACE_TYPE InterfaceType
;
740 mTpm2AcpiTemplate
.Header
.Revision
= PcdGet8(PcdTpm2AcpiTableRev
);
741 DEBUG((DEBUG_INFO
, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate
.Header
.Revision
));
744 // PlatformClass is only valid for version 4 and above
745 // BIT0~15: PlatformClass
746 // BIT16~31: Reserved
748 if (mTpm2AcpiTemplate
.Header
.Revision
>= EFI_TPM2_ACPI_TABLE_REVISION_4
) {
749 mTpm2AcpiTemplate
.Flags
= (mTpm2AcpiTemplate
.Flags
& 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass
);
750 DEBUG((DEBUG_INFO
, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate
.Flags
& 0x0000FFFF)));
754 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
756 TpmMeasureAndLogData(
759 EV_POSTCODE_INFO_ACPI_DATA
,
762 sizeof(mTpm2AcpiTemplate
)
765 InterfaceType
= PcdGet8(PcdActiveTpmInterfaceType
);
766 switch (InterfaceType
) {
767 case Tpm2PtpInterfaceCrb
:
768 mTpm2AcpiTemplate
.StartMethod
= EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE
;
769 mTpm2AcpiTemplate
.AddressOfControlArea
= PcdGet64 (PcdTpmBaseAddress
) + 0x40;
770 ControlArea
= (EFI_TPM2_ACPI_CONTROL_AREA
*)(UINTN
)mTpm2AcpiTemplate
.AddressOfControlArea
;
771 ControlArea
->CommandSize
= 0xF80;
772 ControlArea
->ResponseSize
= 0xF80;
773 ControlArea
->Command
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
774 ControlArea
->Response
= PcdGet64 (PcdTpmBaseAddress
) + 0x80;
776 case Tpm2PtpInterfaceFifo
:
777 case Tpm2PtpInterfaceTis
:
780 DEBUG((EFI_D_ERROR
, "TPM2 InterfaceType get error! %d\n", InterfaceType
));
784 CopyMem (mTpm2AcpiTemplate
.Header
.OemId
, PcdGetPtr (PcdAcpiDefaultOemId
), sizeof (mTpm2AcpiTemplate
.Header
.OemId
));
785 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
786 CopyMem (&mTpm2AcpiTemplate
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
787 mTpm2AcpiTemplate
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
788 mTpm2AcpiTemplate
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
789 mTpm2AcpiTemplate
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
792 // Construct ACPI table
794 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTable
);
795 ASSERT_EFI_ERROR (Status
);
797 Status
= AcpiTable
->InstallAcpiTable (
800 sizeof(mTpm2AcpiTemplate
),
803 ASSERT_EFI_ERROR (Status
);
809 The driver's entry point.
811 It install callbacks for TPM physical presence and MemoryClear, and locate
812 SMM variable to be used in the callback function.
814 @param[in] ImageHandle The firmware allocated handle for the EFI image.
815 @param[in] SystemTable A pointer to the EFI System Table.
817 @retval EFI_SUCCESS The entry point is executed successfully.
818 @retval Others Some error occurs when executing this entry point.
824 IN EFI_HANDLE ImageHandle
,
825 IN EFI_SYSTEM_TABLE
*SystemTable
829 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SwDispatch
;
830 EFI_SMM_SW_REGISTER_CONTEXT SwContext
;
833 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid
), &gEfiTpmDeviceInstanceTpm20DtpmGuid
)){
834 DEBUG ((EFI_D_ERROR
, "No TPM2 DTPM instance required!\n"));
835 return EFI_UNSUPPORTED
;
838 Status
= PublishAcpiTable ();
839 ASSERT_EFI_ERROR (Status
);
842 // Get the Sw dispatch protocol and register SMI callback functions.
844 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid
, NULL
, (VOID
**)&SwDispatch
);
845 ASSERT_EFI_ERROR (Status
);
846 SwContext
.SwSmiInputValue
= (UINTN
) -1;
847 Status
= SwDispatch
->Register (SwDispatch
, PhysicalPresenceCallback
, &SwContext
, &SwHandle
);
848 ASSERT_EFI_ERROR (Status
);
849 if (EFI_ERROR (Status
)) {
852 mTcgNvs
->PhysicalPresence
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
854 SwContext
.SwSmiInputValue
= (UINTN
) -1;
855 Status
= SwDispatch
->Register (SwDispatch
, MemoryClearCallback
, &SwContext
, &SwHandle
);
856 ASSERT_EFI_ERROR (Status
);
857 if (EFI_ERROR (Status
)) {
860 mTcgNvs
->MemoryClear
.SoftwareSmi
= (UINT8
) SwContext
.SwSmiInputValue
;
863 // Locate SmmVariableProtocol.
865 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid
, NULL
, (VOID
**)&mSmmVariable
);
866 ASSERT_EFI_ERROR (Status
);
869 // Set TPM2 ACPI table
871 Status
= PublishTpm2 ();
872 ASSERT_EFI_ERROR (Status
);