TianoCore EDK2 master
Loading...
Searching...
No Matches
Tcg2Acpi.c
Go to the documentation of this file.
1
18#include <PiDxe.h>
19
21
22#include <Guid/TpmInstance.h>
23#include <Guid/TpmNvsMm.h>
26
27#include <Protocol/AcpiTable.h>
30
31#include <Library/BaseLib.h>
35#include <Library/DebugLib.h>
36#include <Library/PcdLib.h>
37#include <Library/PrintLib.h>
41#include <Library/UefiLib.h>
42#include <Library/HobLib.h>
43
44//
45// Physical Presence Interface Version supported by Platform
46//
47#define PHYSICAL_PRESENCE_VERSION_TAG "$PV"
48#define PHYSICAL_PRESENCE_VERSION_SIZE 4
49
50//
51// PNP _HID for TPM2 device
52//
53#define TPM_HID_TAG "NNNN0000"
54#define TPM_HID_PNP_SIZE 8
55#define TPM_HID_ACPI_SIZE 9
56
57#define TPM_PRS_RESL "RESL"
58#define TPM_PRS_RESS "RESS"
59#define TPM_PRS_RES_NAME_SIZE 4
60//
61// Minimum PRS resource template size
62// 1 byte for BufferOp
63// 1 byte for PkgLength
64// 2 bytes for BufferSize
65// 12 bytes for Memory32Fixed descriptor
66// 5 bytes for Interrupt descriptor
67// 2 bytes for END Tag
68//
69#define TPM_POS_RES_TEMPLATE_MIN_SIZE (1 + 1 + 2 + 12 + 5 + 2)
70
71//
72// Max Interrupt buffer size for PRS interrupt resource
73// Now support 15 interrupts in maxmum
74//
75#define MAX_PRS_INT_BUF_SIZE (15*4)
76
77#pragma pack(1)
78
79typedef struct {
81 // Flags field is replaced in version 4 and above
82 // BIT0~15: PlatformClass This field is only valid for version 4 and above
83 // BIT16~31: Reserved
84 UINT32 Flags;
85 UINT64 AddressOfControlArea;
86 UINT32 StartMethod;
87 UINT8 PlatformSpecificParameters[12]; // size up to 12
88 UINT32 Laml; // Optional
89 UINT64 Lasa; // Optional
91
92#pragma pack()
93
94EFI_TPM2_ACPI_TABLE_V4 mTpm2AcpiTemplate = {
95 {
97 sizeof (mTpm2AcpiTemplate),
98 EFI_TPM2_ACPI_TABLE_REVISION,
99 //
100 // Compiler initializes the remaining bytes to 0
101 // These fields should be filled in in production
102 //
103 },
104 0, // BIT0~15: PlatformClass
105 // BIT16~31: Reserved
106 0, // Control Area
107 EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
108};
109
110TCG_NVS *mTcgNvs;
111
123VOID *
126 UINT32 Name,
127 UINT16 Size
128 )
129{
130 AML_OP_REGION_32_8 *OpRegion;
131 EFI_PHYSICAL_ADDRESS MemoryAddress;
132 EFI_HOB_GUID_TYPE *GuidHob;
133 TCG2_ACPI_COMMUNICATE_BUFFER *Tcg2AcpiCommunicateBufferHob;
134
135 MemoryAddress = SIZE_4GB - 1;
136
137 //
138 // Patch some pointers for the ASL code before loading the SSDT.
139 //
140 for (OpRegion = (AML_OP_REGION_32_8 *)(Table + 1);
141 OpRegion <= (AML_OP_REGION_32_8 *)((UINT8 *)Table + Table->Length);
142 OpRegion = (AML_OP_REGION_32_8 *)((UINT8 *)OpRegion + 1))
143 {
144 if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) &&
145 (OpRegion->NameString == Name) &&
146 (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
147 (OpRegion->BytePrefix == AML_BYTE_PREFIX))
148 {
149 GuidHob = GetFirstGuidHob (&gEdkiiTcg2AcpiCommunicateBufferHobGuid);
150 ASSERT (GuidHob != NULL);
151 Tcg2AcpiCommunicateBufferHob = GET_GUID_HOB_DATA (GuidHob);
152 MemoryAddress = Tcg2AcpiCommunicateBufferHob->Tcg2AcpiCommunicateBuffer;
153 ASSERT (MemoryAddress != 0);
154 ASSERT (EFI_PAGES_TO_SIZE (Tcg2AcpiCommunicateBufferHob->Pages) >= Size);
155
156 ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
157 OpRegion->RegionOffset = (UINT32)(UINTN)MemoryAddress;
158 OpRegion->RegionLen = (UINT8)Size;
159
160 break;
161 }
162 }
163
164 return (VOID *)(UINTN)MemoryAddress;
165}
166
177EFIAPI
179 IN OUT TCG_NVS *TcgNvs
180 )
181{
182 EFI_STATUS Status;
183 EFI_MM_COMMUNICATION_PROTOCOL *MmCommunication;
184 EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
185 EFI_MEMORY_DESCRIPTOR *MmCommMemRegion;
186 EFI_MM_COMMUNICATE_HEADER *CommHeader;
187 TPM_NVS_MM_COMM_BUFFER *CommBuffer;
188 UINTN CommBufferSize;
189 UINTN Index;
190
191 // Step 0: Sanity check for input argument
192 if (TcgNvs == NULL) {
193 DEBUG ((DEBUG_ERROR, "%a - Input argument is NULL!\n", __func__));
194 return EFI_INVALID_PARAMETER;
195 }
196
197 // Step 1: Grab the common buffer header
198 Status = EfiGetSystemConfigurationTable (&gEdkiiPiSmmCommunicationRegionTableGuid, (VOID **)&PiSmmCommunicationRegionTable);
199 if (EFI_ERROR (Status)) {
200 DEBUG ((DEBUG_ERROR, "%a - Failed to locate SMM communciation common buffer - %r!\n", __func__, Status));
201 return Status;
202 }
203
204 // Step 2: Grab one that is large enough to hold TPM_NVS_MM_COMM_BUFFER, the IPL one should be sufficient
205 CommBufferSize = 0;
206 MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);
207 for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
208 if (MmCommMemRegion->Type == EfiConventionalMemory) {
209 CommBufferSize = EFI_PAGES_TO_SIZE ((UINTN)MmCommMemRegion->NumberOfPages);
210 if (CommBufferSize >= (sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data))) {
211 break;
212 }
213 }
214
215 MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MmCommMemRegion + PiSmmCommunicationRegionTable->DescriptorSize);
216 }
217
218 if (Index >= PiSmmCommunicationRegionTable->NumberOfEntries) {
219 // Could not find one that meets our goal...
220 DEBUG ((DEBUG_ERROR, "%a - Could not find a common buffer that is big enough for NVS!\n", __func__));
221 return EFI_OUT_OF_RESOURCES;
222 }
223
224 // Step 3: Start to populate contents
225 // Step 3.1: MM Communication common header
226 CommHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)MmCommMemRegion->PhysicalStart;
227 CommBufferSize = sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
228 ZeroMem (CommHeader, CommBufferSize);
229 CopyGuid (&CommHeader->HeaderGuid, &gTpmNvsMmGuid);
230 CommHeader->MessageLength = sizeof (TPM_NVS_MM_COMM_BUFFER);
231
232 // Step 3.2: TPM_NVS_MM_COMM_BUFFER content per our needs
233 CommBuffer = (TPM_NVS_MM_COMM_BUFFER *)(CommHeader->Data);
234 CommBuffer->Function = TpmNvsMmExchangeInfo;
235 CommBuffer->TargetAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)TcgNvs;
236
237 // Step 4: Locate the protocol and signal Mmi.
238 Status = gBS->LocateProtocol (&gEfiMmCommunicationProtocolGuid, NULL, (VOID **)&MmCommunication);
239 if (!EFI_ERROR (Status)) {
240 Status = MmCommunication->Communicate (MmCommunication, CommHeader, &CommBufferSize);
241 DEBUG ((DEBUG_INFO, "%a - Communicate() = %r\n", __func__, Status));
242 } else {
243 DEBUG ((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol - %r\n", __func__, Status));
244 return Status;
245 }
246
247 // Step 5: If everything goes well, populate the channel number
248 if (!EFI_ERROR (CommBuffer->ReturnStatus)) {
249 // Need to demote to UINT8 according to SMI value definition
250 TcgNvs->PhysicalPresence.SoftwareSmi = (UINT8)CommBuffer->RegisteredPpSwiValue;
251 TcgNvs->MemoryClear.SoftwareSmi = (UINT8)CommBuffer->RegisteredMcSwiValue;
252 DEBUG ((
253 DEBUG_INFO,
254 "%a Communication returned software SMI value. PP: 0x%x; MC: 0x%x.\n",
255 __func__,
256 TcgNvs->PhysicalPresence.SoftwareSmi,
257 TcgNvs->MemoryClear.SoftwareSmi
258 ));
259 }
260
261 return (EFI_STATUS)CommBuffer->ReturnStatus;
262}
263
277 CHAR8 *PPVer
278 )
279{
280 EFI_STATUS Status;
281 UINT8 *DataPtr;
282
283 //
284 // Patch some pointers for the ASL code before loading the SSDT.
285 //
286 for (DataPtr = (UINT8 *)(Table + 1);
287 DataPtr <= (UINT8 *)((UINT8 *)Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);
288 DataPtr += 1)
289 {
290 if (AsciiStrCmp ((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {
291 Status = AsciiStrCpyS ((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
292 DEBUG ((DEBUG_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));
293 return Status;
294 }
295 }
296
297 return EFI_NOT_FOUND;
298}
299
315 IN UINT32 *IrqBuffer,
316 IN UINT32 IrqBuffserSize,
317 OUT BOOLEAN *IsShortFormPkgLength
318 )
319{
320 UINT8 *DataPtr;
321 UINT8 *DataEndPtr;
322 UINT32 NewPkgLength;
323 UINT32 OrignalPkgLength;
324
325 NewPkgLength = 0;
326 OrignalPkgLength = 0;
327 DataEndPtr = NULL;
328
329 //
330 // Follow ACPI spec
331 // 6.4.3 Extend Interrupt Descriptor.
332 // 19.3.3 ASL Resource Template
333 // 20 AML specification
334 // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
335 //
336 // AML data is organized by following rule.
337 // Code need to patch BufferSize and PkgLength and interrupt descriptor in ByteList
338 //
339 // ============= Buffer ====================
340 // DefBuffer := BufferOp PkgLength BufferSize ByteList
341 // BufferOp := 0x11
342 //
343 // ==============PkgLength==================
344 // PkgLength := PkgLeadByte |
345 // <PkgLeadByte ByteData> |
346 // <PkgLeadByte ByteData ByteData> |
347 // <PkgLeadByte ByteData ByteData ByteData>
348 //
349 // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
350 // <bit 5-4: Only used if PkgLength <= 63 >
351 // <bit 3-0: Least significant package length nybble>
352 //
353 // ==============BufferSize==================
354 // BufferSize := Integer
355 // Integer := ByteConst|WordConst|DwordConst....
356 //
357 // ByteConst := BytePrefix ByteData
358 //
359 // ==============ByteList===================
360 // ByteList := ByteData ByteList
361 //
362 // =========================================
363
364 //
365 // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
366 //
367 for (DataPtr = (UINT8 *)(Table + 1);
368 DataPtr < (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
369 DataPtr += 1)
370 {
371 if (CompareMem (DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {
372 //
373 // Jump over object name & BufferOp
374 //
375 DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
376
377 if ((*DataPtr & (BIT7|BIT6)) == 0) {
378 OrignalPkgLength = (UINT32)*DataPtr;
379 DataEndPtr = DataPtr + OrignalPkgLength;
380
381 //
382 // Jump over PkgLength = PkgLeadByte only
383 //
384 NewPkgLength++;
385
386 //
387 // Jump over BufferSize
388 //
389 if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
390 NewPkgLength += 2;
391 } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
392 NewPkgLength += 3;
393 } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
394 NewPkgLength += 5;
395 } else {
396 ASSERT (FALSE);
397 return EFI_UNSUPPORTED;
398 }
399 } else {
400 ASSERT (FALSE);
401 return EFI_UNSUPPORTED;
402 }
403
404 //
405 // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
406 //
407 NewPkgLength += 19 + IrqBuffserSize;
408 if (NewPkgLength > 63) {
409 break;
410 }
411
412 if (NewPkgLength > OrignalPkgLength) {
413 ASSERT (FALSE);
414 return EFI_INVALID_PARAMETER;
415 }
416
417 //
418 // 1.1 Patch PkgLength
419 //
420 *DataPtr = (UINT8)NewPkgLength;
421
422 //
423 // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).
424 // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
425 //
426 *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
427
428 //
429 // Notify _PRS to report short formed ResourceTemplate
430 //
431 *IsShortFormPkgLength = TRUE;
432
433 break;
434 }
435 }
436
437 //
438 // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
439 //
440 if (NewPkgLength > 63) {
441 NewPkgLength = 0;
442 OrignalPkgLength = 0;
443 for (DataPtr = (UINT8 *)(Table + 1);
444 DataPtr < (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
445 DataPtr += 1)
446 {
447 if (CompareMem (DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {
448 //
449 // Jump over object name & BufferOp
450 //
451 DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
452
453 if ((*DataPtr & (BIT7|BIT6)) != 0) {
454 OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);
455 DataEndPtr = DataPtr + OrignalPkgLength;
456 //
457 // Jump over PkgLength = PkgLeadByte + ByteData length
458 //
459 NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
460
461 //
462 // Jump over BufferSize
463 //
464 if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
465 NewPkgLength += 2;
466 } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
467 NewPkgLength += 3;
468 } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
469 NewPkgLength += 5;
470 } else {
471 ASSERT (FALSE);
472 return EFI_UNSUPPORTED;
473 }
474 } else {
475 ASSERT (FALSE);
476 return EFI_UNSUPPORTED;
477 }
478
479 //
480 // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
481 //
482 NewPkgLength += 19 + IrqBuffserSize;
483
484 if (NewPkgLength > OrignalPkgLength) {
485 ASSERT (FALSE);
486 return EFI_INVALID_PARAMETER;
487 }
488
489 //
490 // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
491 //
492 *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
493 *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
494
495 //
496 // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).
497 // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
498 //
499 *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);
500
501 //
502 // Notify _PRS to report long formed ResourceTemplate
503 //
504 *IsShortFormPkgLength = FALSE;
505 break;
506 }
507 }
508 }
509
510 if (DataPtr >= (UINT8 *)((UINT8 *)Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
511 return EFI_NOT_FOUND;
512 }
513
514 //
515 // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
516 // 5 bytes for interrupt descriptor header, 2 bytes for End Tag
517 //
518 DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);
519 //
520 // 3.1 Patch Length bit[7:0] of Interrupt descriptor patch interrupt descriptor
521 //
522 *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
523 //
524 // 3.2 Patch Interrupt Table Length
525 //
526 *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof (UINT32));
527 //
528 // 3.3 Copy patched InterruptNumBuffer
529 //
530 CopyMem (DataPtr + 5, IrqBuffer, IrqBuffserSize);
531
532 //
533 // 4. Jump over Interrupt descriptor and Patch END Tag, set Checksum field to 0
534 //
535 DataPtr += 5 + IrqBuffserSize;
536 *DataPtr = ACPI_END_TAG_DESCRIPTOR;
537 *(DataPtr + 1) = 0;
538
539 //
540 // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
541 //
542 DataPtr += 2;
543 if (DataPtr < DataEndPtr) {
544 SetMem (DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);
545 }
546
547 return EFI_SUCCESS;
548}
549
561 )
562{
563 EFI_STATUS Status;
564 UINT8 *DataPtr;
565 CHAR8 Hid[TPM_HID_ACPI_SIZE];
566 UINT32 ManufacturerID;
567 UINT32 FirmwareVersion1;
568 UINT32 FirmwareVersion2;
569 BOOLEAN PnpHID;
570
571 PnpHID = TRUE;
572
573 //
574 // Initialize HID with Default PNP string
575 //
576 ZeroMem (Hid, TPM_HID_ACPI_SIZE);
577
578 //
579 // Get Manufacturer ID
580 //
581 Status = Tpm2GetCapabilityManufactureID (&ManufacturerID);
582 if (!EFI_ERROR (Status)) {
583 DEBUG ((DEBUG_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));
584 //
585 // ManufacturerID defined in TCG Vendor ID Registry
586 // may tailed with 0x00 or 0x20
587 //
588 if (((ManufacturerID >> 24) == 0x00) || ((ManufacturerID >> 24) == 0x20)) {
589 //
590 // HID containing PNP ID "NNN####"
591 // NNN is uppercase letter for Vendor ID specified by manufacturer
592 //
593 CopyMem (Hid, &ManufacturerID, 3);
594 } else {
595 //
596 // HID containing ACP ID "NNNN####"
597 // NNNN is uppercase letter for Vendor ID specified by manufacturer
598 //
599 CopyMem (Hid, &ManufacturerID, 4);
600 PnpHID = FALSE;
601 }
602 } else {
603 DEBUG ((DEBUG_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));
604 ASSERT (FALSE);
605 return Status;
606 }
607
608 Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2);
609 if (!EFI_ERROR (Status)) {
610 DEBUG ((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));
611 DEBUG ((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));
612 //
613 // #### is Firmware Version 1
614 //
615 if (PnpHID) {
616 AsciiSPrint (Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
617 } else {
618 AsciiSPrint (Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
619 }
620 } else {
621 DEBUG ((DEBUG_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));
622 ASSERT (FALSE);
623 return Status;
624 }
625
626 //
627 // Patch HID in ASL code before loading the SSDT.
628 //
629 for (DataPtr = (UINT8 *)(Table + 1);
630 DataPtr <= (UINT8 *)((UINT8 *)Table + Table->Length - TPM_HID_PNP_SIZE);
631 DataPtr += 1)
632 {
633 if (AsciiStrCmp ((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {
634 if (PnpHID) {
635 CopyMem (DataPtr, Hid, TPM_HID_PNP_SIZE);
636 //
637 // if HID is PNP ID, patch the last byte in HID TAG to Noop
638 //
639 *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;
640 } else {
641 CopyMem (DataPtr, Hid, TPM_HID_ACPI_SIZE);
642 }
643
644 DEBUG ((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", Hid));
645
646 return Status;
647 }
648 }
649
650 DEBUG ((DEBUG_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
651 return EFI_NOT_FOUND;
652}
653
663 VOID
664 )
665{
666 EFI_STATUS Status;
667 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
668 UINTN TableKey;
670 UINTN TableSize;
671 UINT32 *PossibleIrqNumBuf;
672 UINT32 PossibleIrqNumBufSize;
673 BOOLEAN IsShortFormPkgLength;
674
675 IsShortFormPkgLength = FALSE;
676
677 Status = GetSectionFromFv (
678 &gEfiCallerIdGuid,
679 EFI_SECTION_RAW,
680 0,
681 (VOID **)&Table,
682 &TableSize
683 );
684 ASSERT_EFI_ERROR (Status);
685
686 //
687 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
688 // The measurement has to be done before any update.
689 // Otherwise, the PCR record would be different after TPM FW update
690 // or the PCD configuration change.
691 //
693 0,
694 EV_POST_CODE,
695 EV_POSTCODE_INFO_ACPI_DATA,
696 ACPI_DATA_LEN,
697 Table,
698 TableSize
699 );
700
701 //
702 // Update Table version before measuring it to PCR
703 //
704 Status = UpdatePPVersion (Table, (CHAR8 *)PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer));
705 ASSERT_EFI_ERROR (Status);
706
707 DEBUG ((
708 DEBUG_INFO,
709 "Current physical presence interface version - %a\n",
710 (CHAR8 *)PcdGetPtr (PcdTcgPhysicalPresenceInterfaceVer)
711 ));
712
713 //
714 // Update TPM2 HID after measuring it to PCR
715 //
716 Status = UpdateHID (Table);
717 if (EFI_ERROR (Status)) {
718 return Status;
719 }
720
721 if (PcdGet32 (PcdTpm2CurrentIrqNum) != 0) {
722 //
723 // Patch _PRS interrupt resource only when TPM interrupt is supported
724 //
725 PossibleIrqNumBuf = (UINT32 *)PcdGetPtr (PcdTpm2PossibleIrqNumBuf);
726 PossibleIrqNumBufSize = (UINT32)PcdGetSize (PcdTpm2PossibleIrqNumBuf);
727
728 if ((PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE) && ((PossibleIrqNumBufSize % sizeof (UINT32)) == 0)) {
729 Status = UpdatePossibleResource (Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);
730 DEBUG ((
731 DEBUG_INFO,
732 "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",
733 Status
734 ));
735 } else {
736 DEBUG ((
737 DEBUG_INFO,
738 "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",
739 PossibleIrqNumBufSize
740 ));
741 }
742 }
743
744 ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
745 CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId));
746 mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16)sizeof (TCG_NVS));
747 ASSERT (mTcgNvs != NULL);
748 mTcgNvs->TpmIrqNum = PcdGet32 (PcdTpm2CurrentIrqNum);
749 mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;
750
751 Status = ExchangeCommonBuffer (mTcgNvs);
752
753 //
754 // Publish the TPM ACPI table. Table is re-checksummed.
755 //
756 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
757 ASSERT_EFI_ERROR (Status);
758
759 TableKey = 0;
760 Status = AcpiTable->InstallAcpiTable (
761 AcpiTable,
762 Table,
763 TableSize,
764 &TableKey
765 );
766 ASSERT_EFI_ERROR (Status);
767
768 return Status;
769}
770
780 VOID
781 )
782{
783 EFI_STATUS Status;
784 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
785 UINTN TableKey;
786 UINT64 OemTableId;
787 EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;
788 TPM2_PTP_INTERFACE_TYPE InterfaceType;
789
790 //
791 // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
792 // The measurement has to be done before any update.
793 // Otherwise, the PCR record would be different after event log update
794 // or the PCD configuration change.
795 //
797 0,
798 EV_POST_CODE,
799 EV_POSTCODE_INFO_ACPI_DATA,
800 ACPI_DATA_LEN,
801 &mTpm2AcpiTemplate,
802 mTpm2AcpiTemplate.Header.Length
803 );
804
805 mTpm2AcpiTemplate.Header.Revision = PcdGet8 (PcdTpm2AcpiTableRev);
806 DEBUG ((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));
807
808 //
809 // PlatformClass is only valid for version 4 and above
810 // BIT0~15: PlatformClass
811 // BIT16~31: Reserved
812 //
813 if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {
814 mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8 (PcdTpmPlatformClass);
815 DEBUG ((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));
816 }
817
818 mTpm2AcpiTemplate.Laml = PcdGet32 (PcdTpm2AcpiTableLaml);
819 mTpm2AcpiTemplate.Lasa = PcdGet64 (PcdTpm2AcpiTableLasa);
820 if ((mTpm2AcpiTemplate.Header.Revision < EFI_TPM2_ACPI_TABLE_REVISION_4) ||
821 (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0))
822 {
823 //
824 // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original Length.
825 //
826 mTpm2AcpiTemplate.Header.Length = sizeof (EFI_TPM2_ACPI_TABLE);
827 }
828
829 InterfaceType = PcdGet8 (PcdActiveTpmInterfaceType);
830 switch (InterfaceType) {
831 case Tpm2PtpInterfaceCrb:
832 mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;
833 mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;
834 ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
835 ControlArea->CommandSize = 0xF80;
836 ControlArea->ResponseSize = 0xF80;
837 ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;
838 ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;
839 break;
840 case Tpm2PtpInterfaceFifo:
841 case Tpm2PtpInterfaceTis:
842 break;
843 default:
844 DEBUG ((DEBUG_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));
845 break;
846 }
847
848 CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
849 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
850 CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
851 mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
852 mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
853 mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
854
855 //
856 // Construct ACPI table
857 //
858 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);
859 ASSERT_EFI_ERROR (Status);
860
861 Status = AcpiTable->InstallAcpiTable (
862 AcpiTable,
863 &mTpm2AcpiTemplate,
864 mTpm2AcpiTemplate.Header.Length,
865 &TableKey
866 );
867 ASSERT_EFI_ERROR (Status);
868
869 return Status;
870}
871
886EFIAPI
888 IN EFI_HANDLE ImageHandle,
889 IN EFI_SYSTEM_TABLE *SystemTable
890 )
891{
892 EFI_STATUS Status;
893
894 if (!CompareGuid (PcdGetPtr (PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)) {
895 DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));
896 return EFI_UNSUPPORTED;
897 }
898
899 Status = PublishAcpiTable ();
900 ASSERT_EFI_ERROR (Status);
901
902 //
903 // Set TPM2 ACPI table
904 //
905 Status = PublishTpm2 ();
906 ASSERT_EFI_ERROR (Status);
907
908 return EFI_SUCCESS;
909}
UINT64 UINTN
#define EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE
Definition: Acpi50.h:2100
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
INTN EFIAPI AsciiStrCmp(IN CONST CHAR8 *FirstString, IN CONST CHAR8 *SecondString)
Definition: String.c:716
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI GetSectionFromFv(IN CONST EFI_GUID *NameGuid, IN EFI_SECTION_TYPE SectionType, IN UINTN SectionInstance, OUT VOID **Buffer, OUT UINTN *Size)
UINTN EFIAPI AsciiSPrint(OUT CHAR8 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR8 *FormatString,...)
Definition: PrintLib.c:813
#define NULL
Definition: Base.h:319
#define SIGNATURE_64(A, B, C, D, E, F, G, H)
Definition: Base.h:1331
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define SIGNATURE_32(A, B, C, D)
Definition: Base.h:1310
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGetSize(TokenName)
Definition: PcdLib.h:440
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet8(TokenName)
Definition: PcdLib.h:336
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
EFI_STATUS PublishTpm2(VOID)
Definition: Tcg2Acpi.c:779
VOID * AssignOpRegion(EFI_ACPI_DESCRIPTION_HEADER *Table, UINT32 Name, UINT16 Size)
Definition: Tcg2Acpi.c:124
EFI_STATUS UpdatePossibleResource(IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table, IN UINT32 *IrqBuffer, IN UINT32 IrqBuffserSize, OUT BOOLEAN *IsShortFormPkgLength)
Definition: Tcg2Acpi.c:313
EFI_STATUS EFIAPI InitializeTcgAcpi(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Tcg2Acpi.c:887
EFI_STATUS PublishAcpiTable(VOID)
Definition: Tcg2Acpi.c:662
EFI_STATUS UpdatePPVersion(EFI_ACPI_DESCRIPTION_HEADER *Table, CHAR8 *PPVer)
Definition: Tcg2Acpi.c:275
EFI_STATUS EFIAPI ExchangeCommonBuffer(IN OUT TCG_NVS *TcgNvs)
Definition: Tcg2Acpi.c:178
EFI_STATUS UpdateHID(EFI_ACPI_DESCRIPTION_HEADER *Table)
Definition: Tcg2Acpi.c:559
EFI_STATUS EFIAPI Tpm2GetCapabilityFirmwareVersion(OUT UINT32 *FirmwareVersion1, OUT UINT32 *FirmwareVersion2)
EFI_STATUS EFIAPI Tpm2GetCapabilityManufactureID(OUT UINT32 *ManufactureId)
EFI_STATUS EFIAPI TpmMeasureAndLogData(IN UINT32 PcrIndex, IN UINT32 EventType, IN VOID *EventLog, IN UINT32 LogLen, IN VOID *HashData, IN UINT64 HashDataLen)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
@ EfiConventionalMemory
EFI_PHYSICAL_ADDRESS PhysicalStart
Definition: UefiSpec.h:155
EFI_PHYSICAL_ADDRESS Tcg2AcpiCommunicateBuffer