SecuritPkg: Tcg2Smm: Add PlatformClass to TPM2 Table
[mirror_edk2.git] / SecurityPkg / Tcg / Tcg2Smm / Tcg2Smm.c
1 /** @file
2 It updates TPM2 items in ACPI table and registers SMI2 callback
3 functions for Tcg2 physical presence, ClearMemory, and sample
4 for dTPM StartMethod.
5
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.
9
10 PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
11
12 Copyright (c) 2015 - 2017, 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
17
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.
20
21 **/
22
23 #include "Tcg2Smm.h"
24
25 typedef enum {
26 PtpInterfaceTis,
27 PtpInterfaceFifo,
28 PtpInterfaceCrb,
29 PtpInterfaceMax,
30 } PTP_INTERFACE_TYPE;
31
32 /**
33 Return PTP interface type.
34
35 @param[in] Register Pointer to PTP register.
36
37 @return PTP interface type.
38 **/
39 PTP_INTERFACE_TYPE
40 GetPtpInterface (
41 IN VOID *Register
42 )
43 {
44 PTP_CRB_INTERFACE_IDENTIFIER InterfaceId;
45 PTP_FIFO_INTERFACE_CAPABILITY InterfaceCapability;
46
47 //
48 // Check interface id
49 //
50 InterfaceId.Uint32 = MmioRead32 ((UINTN)&((PTP_CRB_REGISTERS *)Register)->InterfaceId);
51 InterfaceCapability.Uint32 = MmioRead32 ((UINTN)&((PTP_FIFO_REGISTERS *)Register)->InterfaceCapability);
52
53 if (InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_TIS) {
54 return PtpInterfaceTis;
55 }
56
57 if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_CRB) &&
58 (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_CRB) &&
59 (InterfaceId.Bits.CapCRB != 0)) {
60 return PtpInterfaceCrb;
61 }
62
63 if ((InterfaceId.Bits.InterfaceType == PTP_INTERFACE_IDENTIFIER_INTERFACE_TYPE_FIFO) &&
64 (InterfaceId.Bits.InterfaceVersion == PTP_INTERFACE_IDENTIFIER_INTERFACE_VERSION_FIFO) &&
65 (InterfaceId.Bits.CapFIFO != 0) &&
66 (InterfaceCapability.Bits.InterfaceVersion == INTERFACE_CAPABILITY_INTERFACE_VERSION_PTP)) {
67 return PtpInterfaceFifo;
68 }
69
70 //
71 // No Ptp interface available
72 //
73 return PtpInterfaceMax;
74 }
75
76 EFI_TPM2_ACPI_TABLE mTpm2AcpiTemplate = {
77 {
78 EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
79 sizeof (mTpm2AcpiTemplate),
80 EFI_TPM2_ACPI_TABLE_REVISION,
81 //
82 // Compiler initializes the remaining bytes to 0
83 // These fields should be filled in in production
84 //
85 },
86 0, // BIT0~15: PlatformClass
87 // BIT16~31: Reserved
88 0, // Control Area
89 EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
90 };
91
92 EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
93 TCG_NVS *mTcgNvs;
94
95 /**
96 Software SMI callback for TPM physical presence which is called from ACPI method.
97
98 Caution: This function may receive untrusted input.
99 Variable and ACPINvs are external input, so this function will validate
100 its data structure to be valid value.
101
102 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
103 @param[in] Context Points to an optional handler context which was specified when the
104 handler was registered.
105 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
106 be conveyed from a non-SMM environment into an SMM environment.
107 @param[in, out] CommBufferSize The size of the CommBuffer.
108
109 @retval EFI_SUCCESS The interrupt was handled successfully.
110
111 **/
112 EFI_STATUS
113 EFIAPI
114 PhysicalPresenceCallback (
115 IN EFI_HANDLE DispatchHandle,
116 IN CONST VOID *Context,
117 IN OUT VOID *CommBuffer,
118 IN OUT UINTN *CommBufferSize
119 )
120 {
121 UINT32 MostRecentRequest;
122 UINT32 Response;
123 UINT32 OperationRequest;
124 UINT32 RequestParameter;
125
126
127 if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_RETURN_REQUEST_RESPONSE_TO_OS) {
128 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
129 &MostRecentRequest,
130 &Response
131 );
132 mTcgNvs->PhysicalPresence.LastRequest = MostRecentRequest;
133 mTcgNvs->PhysicalPresence.Response = Response;
134 return EFI_SUCCESS;
135 } else if ((mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS)
136 || (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_SUBMIT_REQUEST_TO_BIOS_2)) {
137
138 OperationRequest = mTcgNvs->PhysicalPresence.Request;
139 RequestParameter = mTcgNvs->PhysicalPresence.RequestParameter;
140 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
141 &OperationRequest,
142 &RequestParameter
143 );
144 mTcgNvs->PhysicalPresence.Request = OperationRequest;
145 mTcgNvs->PhysicalPresence.RequestParameter = RequestParameter;
146 } else if (mTcgNvs->PhysicalPresence.Parameter == TCG_ACPI_FUNCTION_GET_USER_CONFIRMATION_STATUS_FOR_REQUEST) {
147 mTcgNvs->PhysicalPresence.ReturnCode = Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (mTcgNvs->PPRequestUserConfirm);
148 }
149
150 return EFI_SUCCESS;
151 }
152
153
154 /**
155 Software SMI callback for MemoryClear which is called from ACPI method.
156
157 Caution: This function may receive untrusted input.
158 Variable and ACPINvs are external input, so this function will validate
159 its data structure to be valid value.
160
161 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
162 @param[in] Context Points to an optional handler context which was specified when the
163 handler was registered.
164 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
165 be conveyed from a non-SMM environment into an SMM environment.
166 @param[in, out] CommBufferSize The size of the CommBuffer.
167
168 @retval EFI_SUCCESS The interrupt was handled successfully.
169
170 **/
171 EFI_STATUS
172 EFIAPI
173 MemoryClearCallback (
174 IN EFI_HANDLE DispatchHandle,
175 IN CONST VOID *Context,
176 IN OUT VOID *CommBuffer,
177 IN OUT UINTN *CommBufferSize
178 )
179 {
180 EFI_STATUS Status;
181 UINTN DataSize;
182 UINT8 MorControl;
183
184 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_SUCCESS;
185 if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_DSM_MEMORY_CLEAR_INTERFACE) {
186 MorControl = (UINT8) mTcgNvs->MemoryClear.Request;
187 } else if (mTcgNvs->MemoryClear.Parameter == ACPI_FUNCTION_PTS_CLEAR_MOR_BIT) {
188 DataSize = sizeof (UINT8);
189 Status = mSmmVariable->SmmGetVariable (
190 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
191 &gEfiMemoryOverwriteControlDataGuid,
192 NULL,
193 &DataSize,
194 &MorControl
195 );
196 if (EFI_ERROR (Status)) {
197 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
198 DEBUG ((EFI_D_ERROR, "[TPM] Get MOR variable failure! Status = %r\n", Status));
199 return EFI_SUCCESS;
200 }
201
202 if (MOR_CLEAR_MEMORY_VALUE (MorControl) == 0x0) {
203 return EFI_SUCCESS;
204 }
205 MorControl &= ~MOR_CLEAR_MEMORY_BIT_MASK;
206 }
207
208 DataSize = sizeof (UINT8);
209 Status = mSmmVariable->SmmSetVariable (
210 MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
211 &gEfiMemoryOverwriteControlDataGuid,
212 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
213 DataSize,
214 &MorControl
215 );
216 if (EFI_ERROR (Status)) {
217 mTcgNvs->MemoryClear.ReturnCode = MOR_REQUEST_GENERAL_FAILURE;
218 DEBUG ((EFI_D_ERROR, "[TPM] Set MOR variable failure! Status = %r\n", Status));
219 }
220
221 return EFI_SUCCESS;
222 }
223
224 /**
225 Find the operation region in TCG ACPI table by given Name and Size,
226 and initialize it if the region is found.
227
228 @param[in, out] Table The TPM item in ACPI table.
229 @param[in] Name The name string to find in TPM table.
230 @param[in] Size The size of the region to find.
231
232 @return The allocated address for the found region.
233
234 **/
235 VOID *
236 AssignOpRegion (
237 EFI_ACPI_DESCRIPTION_HEADER *Table,
238 UINT32 Name,
239 UINT16 Size
240 )
241 {
242 EFI_STATUS Status;
243 AML_OP_REGION_32_8 *OpRegion;
244 EFI_PHYSICAL_ADDRESS MemoryAddress;
245
246 MemoryAddress = SIZE_4GB - 1;
247
248 //
249 // Patch some pointers for the ASL code before loading the SSDT.
250 //
251 for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);
252 OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);
253 OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {
254 if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) &&
255 (OpRegion->NameString == Name) &&
256 (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
257 (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {
258
259 Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
260 ASSERT_EFI_ERROR (Status);
261 ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
262 OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;
263 OpRegion->RegionLen = (UINT8) Size;
264 break;
265 }
266 }
267
268 return (VOID *) (UINTN) MemoryAddress;
269 }
270
271 /**
272 Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
273 ACPI table is "$PV".
274
275 @param[in, out] Table The TPM item in ACPI table.
276 @param[in] PPVer Version string of Physical Presence interface supported by platform.
277
278 @return The allocated address for the found region.
279
280 **/
281 EFI_STATUS
282 UpdatePPVersion (
283 EFI_ACPI_DESCRIPTION_HEADER *Table,
284 CHAR8 *PPVer
285 )
286 {
287 EFI_STATUS Status;
288 UINT8 *DataPtr;
289
290 //
291 // Patch some pointers for the ASL code before loading the SSDT.
292 //
293 for (DataPtr = (UINT8 *)(Table + 1);
294 DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);
295 DataPtr += 1) {
296 if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {
297 Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
298 DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));
299 return Status;
300 }
301 }
302
303 return EFI_NOT_FOUND;
304 }
305
306 /**
307 Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".
308
309 @param[in, out] Table The TPM2 SSDT ACPI table.
310
311 @return HID Update status.
312
313 **/
314 EFI_STATUS
315 UpdateHID (
316 EFI_ACPI_DESCRIPTION_HEADER *Table
317 )
318 {
319 EFI_STATUS Status;
320 UINT8 *DataPtr;
321 CHAR8 Hid[TPM_HID_ACPI_SIZE];
322 UINT32 ManufacturerID;
323 UINT32 FirmwareVersion1;
324 UINT32 FirmwareVersion2;
325 BOOLEAN PnpHID;
326
327 PnpHID = TRUE;
328
329 //
330 // Initialize HID with Default PNP string
331 //
332 ZeroMem(Hid, TPM_HID_ACPI_SIZE);
333
334 //
335 // Get Manufacturer ID
336 //
337 Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);
338 if (!EFI_ERROR(Status)) {
339 DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));
340 //
341 // ManufacturerID defined in TCG Vendor ID Registry
342 // may tailed with 0x00 or 0x20
343 //
344 if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {
345 //
346 // HID containing PNP ID "NNN####"
347 // NNN is uppercase letter for Vendor ID specified by manufacturer
348 //
349 CopyMem(Hid, &ManufacturerID, 3);
350 } else {
351 //
352 // HID containing ACP ID "NNNN####"
353 // NNNN is uppercase letter for Vendor ID specified by manufacturer
354 //
355 CopyMem(Hid, &ManufacturerID, 4);
356 PnpHID = FALSE;
357 }
358 } else {
359 DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));
360 ASSERT(FALSE);
361 return Status;
362 }
363
364 Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);
365 if (!EFI_ERROR(Status)) {
366 DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));
367 DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));
368 //
369 // #### is Firmware Version 1
370 //
371 if (PnpHID) {
372 AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
373 } else {
374 AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
375 }
376
377 } else {
378 DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));
379 ASSERT(FALSE);
380 return Status;
381 }
382
383 //
384 // Patch HID in ASL code before loading the SSDT.
385 //
386 for (DataPtr = (UINT8 *)(Table + 1);
387 DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);
388 DataPtr += 1) {
389 if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {
390 if (PnpHID) {
391 CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);
392 //
393 // if HID is PNP ID, patch the last byte in HID TAG to Noop
394 //
395 *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;
396 } else {
397
398 CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);
399 }
400 DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));
401
402 return Status;
403 }
404 }
405
406 DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
407 return EFI_NOT_FOUND;
408 }
409
410 /**
411 Initialize and publish TPM items in ACPI table.
412
413 @retval EFI_SUCCESS The TCG ACPI table is published successfully.
414 @retval Others The TCG ACPI table is not published.
415
416 **/
417 EFI_STATUS
418 PublishAcpiTable (
419 VOID
420 )
421 {
422 EFI_STATUS Status;
423 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
424 UINTN TableKey;
425 EFI_ACPI_DESCRIPTION_HEADER *Table;
426 UINTN TableSize;
427
428 Status = GetSectionFromFv (
429 &gEfiCallerIdGuid,
430 EFI_SECTION_RAW,
431 0,
432 (VOID **) &Table,
433 &TableSize
434 );
435 ASSERT_EFI_ERROR (Status);
436
437 //
438 // Update Table version before measuring it to PCR
439 //
440 Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));
441 ASSERT_EFI_ERROR (Status);
442
443 DEBUG ((
444 DEBUG_INFO,
445 "Current physical presence interface version - %a\n",
446 (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)
447 ));
448
449 //
450 // Update TPM2 HID before measuring it to PCR
451 //
452 Status = UpdateHID(Table);
453 if (EFI_ERROR(Status)) {
454 return Status;
455 }
456
457 //
458 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
459 //
460 TpmMeasureAndLogData(
461 0,
462 EV_POST_CODE,
463 EV_POSTCODE_INFO_ACPI_DATA,
464 ACPI_DATA_LEN,
465 Table,
466 TableSize
467 );
468
469
470 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
471 CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );
472 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
473 ASSERT (mTcgNvs != NULL);
474
475 //
476 // Publish the TPM ACPI table. Table is re-checksumed.
477 //
478 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
479 ASSERT_EFI_ERROR (Status);
480
481 TableKey = 0;
482 Status = AcpiTable->InstallAcpiTable (
483 AcpiTable,
484 Table,
485 TableSize,
486 &TableKey
487 );
488 ASSERT_EFI_ERROR (Status);
489
490 return Status;
491 }
492
493 /**
494 Publish TPM2 ACPI table
495
496 @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
497 @retval Others The TPM2 ACPI table is not published.
498
499 **/
500 EFI_STATUS
501 PublishTpm2 (
502 VOID
503 )
504 {
505 EFI_STATUS Status;
506 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
507 UINTN TableKey;
508 UINT64 OemTableId;
509 EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;
510 PTP_INTERFACE_TYPE InterfaceType;
511
512 mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);
513 DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));
514
515 //
516 // PlatformClass is only valid for version 4 and above
517 // BIT0~15: PlatformClass
518 // BIT16~31: Reserved
519 //
520 if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {
521 mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass);
522 DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));
523 }
524
525 //
526 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
527 //
528 TpmMeasureAndLogData(
529 0,
530 EV_POST_CODE,
531 EV_POSTCODE_INFO_ACPI_DATA,
532 ACPI_DATA_LEN,
533 &mTpm2AcpiTemplate,
534 sizeof(mTpm2AcpiTemplate)
535 );
536
537 InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
538 switch (InterfaceType) {
539 case PtpInterfaceCrb:
540 mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;
541 mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;
542 ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
543 ControlArea->CommandSize = 0xF80;
544 ControlArea->ResponseSize = 0xF80;
545 ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;
546 ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;
547 break;
548 case PtpInterfaceFifo:
549 case PtpInterfaceTis:
550 break;
551 default:
552 DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));
553 break;
554 }
555
556 CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
557 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
558 CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
559 mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
560 mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
561 mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
562
563 //
564 // Construct ACPI table
565 //
566 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
567 ASSERT_EFI_ERROR (Status);
568
569 Status = AcpiTable->InstallAcpiTable (
570 AcpiTable,
571 &mTpm2AcpiTemplate,
572 sizeof(mTpm2AcpiTemplate),
573 &TableKey
574 );
575 ASSERT_EFI_ERROR (Status);
576
577 return Status;
578 }
579
580 /**
581 The driver's entry point.
582
583 It install callbacks for TPM physical presence and MemoryClear, and locate
584 SMM variable to be used in the callback function.
585
586 @param[in] ImageHandle The firmware allocated handle for the EFI image.
587 @param[in] SystemTable A pointer to the EFI System Table.
588
589 @retval EFI_SUCCESS The entry point is executed successfully.
590 @retval Others Some error occurs when executing this entry point.
591
592 **/
593 EFI_STATUS
594 EFIAPI
595 InitializeTcgSmm (
596 IN EFI_HANDLE ImageHandle,
597 IN EFI_SYSTEM_TABLE *SystemTable
598 )
599 {
600 EFI_STATUS Status;
601 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
602 EFI_SMM_SW_REGISTER_CONTEXT SwContext;
603 EFI_HANDLE SwHandle;
604
605 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
606 DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));
607 return EFI_UNSUPPORTED;
608 }
609
610 Status = PublishAcpiTable ();
611 ASSERT_EFI_ERROR (Status);
612
613 //
614 // Get the Sw dispatch protocol and register SMI callback functions.
615 //
616 Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);
617 ASSERT_EFI_ERROR (Status);
618 SwContext.SwSmiInputValue = (UINTN) -1;
619 Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);
620 ASSERT_EFI_ERROR (Status);
621 if (EFI_ERROR (Status)) {
622 return Status;
623 }
624 mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
625
626 SwContext.SwSmiInputValue = (UINTN) -1;
627 Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
628 ASSERT_EFI_ERROR (Status);
629 if (EFI_ERROR (Status)) {
630 return Status;
631 }
632 mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
633
634 //
635 // Locate SmmVariableProtocol.
636 //
637 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
638 ASSERT_EFI_ERROR (Status);
639
640 //
641 // Set TPM2 ACPI table
642 //
643 Status = PublishTpm2 ();
644 ASSERT_EFI_ERROR (Status);
645
646
647 return EFI_SUCCESS;
648 }
649