]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/IntelTdx/TdTcg2Dxe/TdTcg2Dxe.c
OvmfPkg/IntelTdx: Add TdTcg2Dxe
[mirror_edk2.git] / OvmfPkg / IntelTdx / TdTcg2Dxe / TdTcg2Dxe.c
CommitLineData
57a6ee34
MX
1/** @file\r
2 This module implements EFI TD Protocol.\r
3\r
4 Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include <PiDxe.h>\r
10#include <IndustryStandard/Acpi.h>\r
11#include <IndustryStandard/PeImage.h>\r
12#include <IndustryStandard/TcpaAcpi.h>\r
13\r
14#include <Guid/GlobalVariable.h>\r
15#include <Guid/HobList.h>\r
16#include <Guid/EventGroup.h>\r
17#include <Guid/EventExitBootServiceFailed.h>\r
18#include <Guid/ImageAuthentication.h>\r
19#include <Guid/TpmInstance.h>\r
20\r
21#include <Protocol/DevicePath.h>\r
22#include <Protocol/MpService.h>\r
23#include <Protocol/VariableWrite.h>\r
24#include <Protocol/Tcg2Protocol.h>\r
25#include <Protocol/TrEEProtocol.h>\r
26#include <Protocol/ResetNotification.h>\r
27#include <Protocol/AcpiTable.h>\r
28\r
29#include <Library/DebugLib.h>\r
30#include <Library/BaseMemoryLib.h>\r
31#include <Library/UefiRuntimeServicesTableLib.h>\r
32#include <Library/UefiDriverEntryPoint.h>\r
33#include <Library/HobLib.h>\r
34#include <Library/UefiBootServicesTableLib.h>\r
35#include <Library/BaseLib.h>\r
36#include <Library/MemoryAllocationLib.h>\r
37#include <Library/PrintLib.h>\r
38#include <Library/PcdLib.h>\r
39#include <Library/UefiLib.h>\r
40#include <Library/HashLib.h>\r
41#include <Library/PerformanceLib.h>\r
42#include <Library/ReportStatusCodeLib.h>\r
43#include <Library/TpmMeasurementLib.h>\r
44\r
45#include <Protocol/CcMeasurement.h>\r
46#include <Guid/CcEventHob.h>\r
47#include <Library/TdxLib.h>\r
48\r
49#define PERF_ID_CC_TCG2_DXE 0x3130\r
50\r
51#define CC_EVENT_LOG_AREA_COUNT_MAX 1\r
52#define INVALID_RTMR_INDEX 4\r
53\r
54typedef struct {\r
55 CHAR16 *VariableName;\r
56 EFI_GUID *VendorGuid;\r
57} VARIABLE_TYPE;\r
58\r
59typedef struct {\r
60 EFI_GUID *EventGuid;\r
61 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
62} CC_EVENT_INFO_STRUCT;\r
63\r
64typedef struct {\r
65 EFI_CC_EVENT_LOG_FORMAT EventLogFormat;\r
66 EFI_PHYSICAL_ADDRESS Lasa;\r
67 UINT64 Laml;\r
68 UINTN EventLogSize;\r
69 UINT8 *LastEvent;\r
70 BOOLEAN EventLogStarted;\r
71 BOOLEAN EventLogTruncated;\r
72 UINTN Next800155EventOffset;\r
73} CC_EVENT_LOG_AREA_STRUCT;\r
74\r
75typedef struct _TDX_DXE_DATA {\r
76 EFI_CC_BOOT_SERVICE_CAPABILITY BsCap;\r
77 CC_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
78 BOOLEAN GetEventLogCalled[CC_EVENT_LOG_AREA_COUNT_MAX];\r
79 CC_EVENT_LOG_AREA_STRUCT FinalEventLogAreaStruct[CC_EVENT_LOG_AREA_COUNT_MAX];\r
80 EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable[CC_EVENT_LOG_AREA_COUNT_MAX];\r
81} TDX_DXE_DATA;\r
82\r
83typedef struct {\r
84 TPMI_ALG_HASH HashAlgo;\r
85 UINT16 HashSize;\r
86 UINT32 HashMask;\r
87} TDX_HASH_INFO;\r
88\r
89//\r
90//\r
91CC_EVENT_INFO_STRUCT mCcEventInfo[] = {\r
92 { &gCcEventEntryHobGuid, EFI_CC_EVENT_LOG_FORMAT_TCG_2 },\r
93};\r
94\r
95TDX_DXE_DATA mTdxDxeData = {\r
96 {\r
97 sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY), // Size\r
98 { 1, 1 }, // StructureVersion\r
99 { 1, 1 }, // ProtocolVersion\r
100 EFI_CC_BOOT_HASH_ALG_SHA384, // HashAlgorithmBitmap\r
101 EFI_CC_EVENT_LOG_FORMAT_TCG_2, // SupportedEventLogs\r
102 { 2, 0 } // {CC_TYPE, CC_SUBTYPE}\r
103 },\r
104};\r
105\r
106UINTN mBootAttempts = 0;\r
107CHAR16 mBootVarName[] = L"BootOrder";\r
108\r
109VARIABLE_TYPE mVariableType[] = {\r
110 { EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid },\r
111 { EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid },\r
112 { EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid },\r
113 { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },\r
114 { EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid },\r
115};\r
116\r
117EFI_CC_EVENTLOG_ACPI_TABLE mTdxEventlogAcpiTemplate = {\r
118 {\r
119 EFI_CC_EVENTLOG_ACPI_TABLE_SIGNATURE,\r
120 sizeof (mTdxEventlogAcpiTemplate),\r
121 EFI_CC_EVENTLOG_ACPI_TABLE_REVISION,\r
122 //\r
123 // Compiler initializes the remaining bytes to 0\r
124 // These fields should be filled in production\r
125 //\r
126 },\r
127 { EFI_CC_TYPE_TDX, 0 }, // CcType\r
128 0, // rsvd\r
129 0, // laml\r
130 0, // lasa\r
131};\r
132\r
133//\r
134// Supported Hash list in Td guest.\r
135// Currently SHA384 is supported.\r
136//\r
137TDX_HASH_INFO mHashInfo[] = {\r
138 { TPM_ALG_SHA384, SHA384_DIGEST_SIZE, HASH_ALG_SHA384 }\r
139};\r
140\r
141/**\r
142 Get hash size based on Algo\r
143\r
144 @param[in] HashAlgo Hash Algorithm Id.\r
145\r
146 @return Size of the hash.\r
147**/\r
148UINT16\r
149GetHashSizeFromAlgo (\r
150 IN TPMI_ALG_HASH HashAlgo\r
151 )\r
152{\r
153 UINTN Index;\r
154\r
155 for (Index = 0; Index < sizeof (mHashInfo)/sizeof (mHashInfo[0]); Index++) {\r
156 if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
157 return mHashInfo[Index].HashSize;\r
158 }\r
159 }\r
160\r
161 return 0;\r
162}\r
163\r
164/**\r
165 Get hash mask based on Algo\r
166\r
167 @param[in] HashAlgo Hash Algorithm Id.\r
168\r
169 @return Hash mask.\r
170**/\r
171UINT32\r
172GetHashMaskFromAlgo (\r
173 IN TPMI_ALG_HASH HashAlgo\r
174 )\r
175{\r
176 UINTN Index;\r
177\r
178 for (Index = 0; Index < ARRAY_SIZE (mHashInfo); Index++) {\r
179 if (mHashInfo[Index].HashAlgo == HashAlgo) {\r
180 return mHashInfo[Index].HashMask;\r
181 }\r
182 }\r
183\r
184 ASSERT (FALSE);\r
185 return 0;\r
186}\r
187\r
188/**\r
189 Copy TPML_DIGEST_VALUES into a buffer\r
190\r
191 @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
192 @param[in] DigestList TPML_DIGEST_VALUES to be copied.\r
193 @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
194\r
195 @return The end of buffer to hold TPML_DIGEST_VALUES.\r
196**/\r
197VOID *\r
198CopyDigestListToBuffer (\r
199 IN OUT VOID *Buffer,\r
200 IN TPML_DIGEST_VALUES *DigestList,\r
201 IN UINT32 HashAlgorithmMask\r
202 )\r
203{\r
204 UINTN Index;\r
205 UINT16 DigestSize;\r
206 UINT32 DigestListCount;\r
207 UINT32 *DigestListCountPtr;\r
208\r
209 DigestListCountPtr = (UINT32 *)Buffer;\r
210 DigestListCount = 0;\r
211 Buffer = (UINT8 *)Buffer + sizeof (DigestList->count);\r
212 for (Index = 0; Index < DigestList->count; Index++) {\r
213 if ((DigestList->digests[Index].hashAlg & HashAlgorithmMask) == 0) {\r
214 DEBUG ((DEBUG_ERROR, "WARNING: TD Event log has HashAlg unsupported (0x%x)\n", DigestList->digests[Index].hashAlg));\r
215 continue;\r
216 }\r
217\r
218 CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof (DigestList->digests[Index].hashAlg));\r
219 Buffer = (UINT8 *)Buffer + sizeof (DigestList->digests[Index].hashAlg);\r
220 DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg);\r
221 CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize);\r
222 Buffer = (UINT8 *)Buffer + DigestSize;\r
223 DigestListCount++;\r
224 }\r
225\r
226 WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
227\r
228 return Buffer;\r
229}\r
230\r
231EFI_HANDLE mImageHandle;\r
232\r
233/**\r
234 Measure PE image into TPM log based on the authenticode image hashing in\r
235 PE/COFF Specification 8.0 Appendix A.\r
236\r
237 Caution: This function may receive untrusted input.\r
238 PE/COFF image is external input, so this function will validate its data structure\r
239 within this image buffer before use.\r
240\r
241 Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
242\r
243 @param[in] MrIndex RTMR index\r
244 @param[in] ImageAddress Start address of image buffer.\r
245 @param[in] ImageSize Image size\r
246 @param[out] DigestList Digest list of this image.\r
247\r
248 @retval EFI_SUCCESS Successfully measure image.\r
249 @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
250 @retval other error value\r
251**/\r
252EFI_STATUS\r
253MeasurePeImageAndExtend (\r
254 IN UINT32 MrIndex,\r
255 IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
256 IN UINTN ImageSize,\r
257 OUT TPML_DIGEST_VALUES *DigestList\r
258 );\r
259\r
260#define COLUME_SIZE (16 * 2)\r
261\r
262/**\r
263\r
264 This function dump raw data.\r
265\r
266 @param Data raw data\r
267 @param Size raw data size\r
268\r
269**/\r
270VOID\r
271InternalDumpData (\r
272 IN UINT8 *Data,\r
273 IN UINTN Size\r
274 )\r
275{\r
276 UINTN Index;\r
277\r
278 for (Index = 0; Index < Size; Index++) {\r
279 DEBUG ((DEBUG_INFO, Index == COLUME_SIZE/2 ? " | %02x" : " %02x", (UINTN)Data[Index]));\r
280 }\r
281}\r
282\r
283/**\r
284\r
285 This function dump raw data with colume format.\r
286\r
287 @param Data raw data\r
288 @param Size raw data size\r
289\r
290**/\r
291VOID\r
292InternalDumpHex (\r
293 IN UINT8 *Data,\r
294 IN UINTN Size\r
295 )\r
296{\r
297 UINTN Index;\r
298 UINTN Count;\r
299 UINTN Left;\r
300\r
301 Count = Size / COLUME_SIZE;\r
302 Left = Size % COLUME_SIZE;\r
303 for (Index = 0; Index < Count; Index++) {\r
304 DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
305 InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
306 DEBUG ((DEBUG_INFO, "\n"));\r
307 }\r
308\r
309 if (Left != 0) {\r
310 DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));\r
311 InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
312 DEBUG ((DEBUG_INFO, "\n"));\r
313 }\r
314}\r
315\r
316/**\r
317\r
318 This function initialize TD_EVENT_HDR for EV_NO_ACTION\r
319 Event Type other than EFI Specification ID event. The behavior is defined\r
320 by TCG PC Client PFP Spec. Section 9.3.4 EV_NO_ACTION Event Types\r
321\r
322 @param[in, out] NoActionEvent Event Header of EV_NO_ACTION Event\r
323 @param[in] EventSize Event Size of the EV_NO_ACTION Event\r
324\r
325**/\r
326VOID\r
327InitNoActionEvent (\r
328 IN OUT CC_EVENT_HDR *NoActionEvent,\r
329 IN UINT32 EventSize\r
330 )\r
331{\r
332 UINT32 DigestListCount;\r
333 TPMI_ALG_HASH HashAlgId;\r
334 UINT8 *DigestBuffer;\r
335\r
336 DigestBuffer = (UINT8 *)NoActionEvent->Digests.digests;\r
337 DigestListCount = 0;\r
338\r
339 NoActionEvent->MrIndex = 0;\r
340 NoActionEvent->EventType = EV_NO_ACTION;\r
341\r
342 //\r
343 // Set Hash count & hashAlg accordingly, while Digest.digests[n].digest to all 0\r
344 //\r
345 ZeroMem (&NoActionEvent->Digests, sizeof (NoActionEvent->Digests));\r
346\r
347 if ((mTdxDxeData.BsCap.HashAlgorithmBitmap & EFI_CC_BOOT_HASH_ALG_SHA384) != 0) {\r
348 HashAlgId = TPM_ALG_SHA384;\r
349 CopyMem (DigestBuffer, &HashAlgId, sizeof (TPMI_ALG_HASH));\r
350 DigestBuffer += sizeof (TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId);\r
351 DigestListCount++;\r
352 }\r
353\r
354 //\r
355 // Set Digests Count\r
356 //\r
357 WriteUnaligned32 ((UINT32 *)&NoActionEvent->Digests.count, DigestListCount);\r
358\r
359 //\r
360 // Set Event Size\r
361 //\r
362 WriteUnaligned32 ((UINT32 *)DigestBuffer, EventSize);\r
363}\r
364\r
365/**\r
366 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function\r
367 Caller is responsible to free LocationBuf.\r
368\r
369 @param[out] LocationBuf Returns Processor Location Buffer.\r
370 @param[out] Num Returns processor number.\r
371\r
372 @retval EFI_SUCCESS Operation completed successfully.\r
373 @retval EFI_UNSUPPORTED MpService protocol not found.\r
374\r
375**/\r
376EFI_STATUS\r
377GetProcessorsCpuLocation (\r
378 OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf,\r
379 OUT UINTN *Num\r
380 )\r
381{\r
382 EFI_STATUS Status;\r
383 EFI_MP_SERVICES_PROTOCOL *MpProtocol;\r
384 UINTN ProcessorNum;\r
385 UINTN EnabledProcessorNum;\r
386 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
387 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
388 UINTN Index;\r
389\r
390 Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpProtocol);\r
391 if (EFI_ERROR (Status)) {\r
392 //\r
393 // MP protocol is not installed\r
394 //\r
395 return EFI_UNSUPPORTED;\r
396 }\r
397\r
398 Status = MpProtocol->GetNumberOfProcessors (\r
399 MpProtocol,\r
400 &ProcessorNum,\r
401 &EnabledProcessorNum\r
402 );\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406\r
407 Status = gBS->AllocatePool (\r
408 EfiBootServicesData,\r
409 sizeof (EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
410 (VOID **)&ProcessorLocBuf\r
411 );\r
412 if (EFI_ERROR (Status)) {\r
413 return Status;\r
414 }\r
415\r
416 //\r
417 // Get each processor Location info\r
418 //\r
419 for (Index = 0; Index < ProcessorNum; Index++) {\r
420 Status = MpProtocol->GetProcessorInfo (\r
421 MpProtocol,\r
422 Index,\r
423 &ProcessorInfo\r
424 );\r
425 if (EFI_ERROR (Status)) {\r
426 FreePool (ProcessorLocBuf);\r
427 return Status;\r
428 }\r
429\r
430 //\r
431 // Get all Processor Location info & measure\r
432 //\r
433 CopyMem (\r
434 &ProcessorLocBuf[Index],\r
435 &ProcessorInfo.Location,\r
436 sizeof (EFI_CPU_PHYSICAL_LOCATION)\r
437 );\r
438 }\r
439\r
440 *LocationBuf = ProcessorLocBuf;\r
441 *Num = ProcessorNum;\r
442\r
443 return Status;\r
444}\r
445\r
446/**\r
447 The EFI_CC_MEASUREMENT_PROTOCOL GetCapability function call provides protocol\r
448 capability information and state information.\r
449\r
450 @param[in] This Indicates the calling context\r
451 @param[in, out] ProtocolCapability The caller allocates memory for a EFI_CC_BOOT_SERVICE_CAPABILITY\r
452 structure and sets the size field to the size of the structure allocated.\r
453 The callee fills in the fields with the EFI protocol capability information\r
454 and the current EFI TCG2 state information up to the number of fields which\r
455 fit within the size of the structure passed in.\r
456\r
457 @retval EFI_SUCCESS Operation completed successfully.\r
458 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
459 The ProtocolCapability variable will not be populated.\r
460 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
461 The ProtocolCapability variable will not be populated.\r
462 @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response.\r
463 It will be partially populated (required Size field will be set).\r
464**/\r
465EFI_STATUS\r
466EFIAPI\r
467TdGetCapability (\r
468 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
469 IN OUT EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
470 )\r
471{\r
472 DEBUG ((DEBUG_VERBOSE, "TdGetCapability\n"));\r
473\r
474 if ((This == NULL) || (ProtocolCapability == NULL)) {\r
475 return EFI_INVALID_PARAMETER;\r
476 }\r
477\r
478 CopyMem (ProtocolCapability, &mTdxDxeData.BsCap, sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY));\r
479\r
480 return EFI_SUCCESS;\r
481}\r
482\r
483/**\r
484 This function dump PCR event.\r
485 TD Event log reuse the TCG PCR Event spec.\r
486 The first event in the event log is the SHA1 log format.\r
487 There is only ONE TCG_PCR_EVENT in TD Event log.\r
488\r
489 @param[in] EventHdr TCG PCR event structure.\r
490**/\r
491VOID\r
492DumpPcrEvent (\r
493 IN TCG_PCR_EVENT_HDR *EventHdr\r
494 )\r
495{\r
496 UINTN Index;\r
497\r
498 DEBUG ((DEBUG_INFO, " Event:\n"));\r
499 DEBUG ((DEBUG_INFO, " MrIndex - %d\n", EventHdr->PCRIndex));\r
500 DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", EventHdr->EventType));\r
501 DEBUG ((DEBUG_INFO, " Digest - "));\r
502 for (Index = 0; Index < sizeof (TCG_DIGEST); Index++) {\r
503 DEBUG ((DEBUG_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
504 }\r
505\r
506 DEBUG ((DEBUG_INFO, "\n"));\r
507 DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize));\r
508 InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
509}\r
510\r
511/**\r
512 This function dump TCG_EfiSpecIDEventStruct.\r
513\r
514 @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
515**/\r
516VOID\r
517DumpTcgEfiSpecIdEventStruct (\r
518 IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
519 )\r
520{\r
521 TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
522 UINTN Index;\r
523 UINT8 *VendorInfoSize;\r
524 UINT8 *VendorInfo;\r
525 UINT32 NumberOfAlgorithms;\r
526\r
527 DEBUG ((DEBUG_INFO, " TCG_EfiSpecIDEventStruct:\n"));\r
528 DEBUG ((DEBUG_INFO, " signature - '"));\r
529 for (Index = 0; Index < sizeof (TcgEfiSpecIdEventStruct->signature); Index++) {\r
530 DEBUG ((DEBUG_INFO, "%c", TcgEfiSpecIdEventStruct->signature[Index]));\r
531 }\r
532\r
533 DEBUG ((DEBUG_INFO, "'\n"));\r
534 DEBUG ((DEBUG_INFO, " platformClass - 0x%08x\n", TcgEfiSpecIdEventStruct->platformClass));\r
535 DEBUG ((DEBUG_INFO, " specVersion - %d.%d%d\n", TcgEfiSpecIdEventStruct->specVersionMajor, TcgEfiSpecIdEventStruct->specVersionMinor, TcgEfiSpecIdEventStruct->specErrata));\r
536 DEBUG ((DEBUG_INFO, " uintnSize - 0x%02x\n", TcgEfiSpecIdEventStruct->uintnSize));\r
537\r
538 CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
539 DEBUG ((DEBUG_INFO, " NumberOfAlgorithms - 0x%08x\n", NumberOfAlgorithms));\r
540\r
541 DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
542 for (Index = 0; Index < NumberOfAlgorithms; Index++) {\r
543 DEBUG ((DEBUG_INFO, " digest(%d)\n", Index));\r
544 DEBUG ((DEBUG_INFO, " algorithmId - 0x%04x\n", DigestSize[Index].algorithmId));\r
545 DEBUG ((DEBUG_INFO, " digestSize - 0x%04x\n", DigestSize[Index].digestSize));\r
546 }\r
547\r
548 VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
549 DEBUG ((DEBUG_INFO, " VendorInfoSize - 0x%02x\n", *VendorInfoSize));\r
550 VendorInfo = VendorInfoSize + 1;\r
551 DEBUG ((DEBUG_INFO, " VendorInfo - "));\r
552 for (Index = 0; Index < *VendorInfoSize; Index++) {\r
553 DEBUG ((DEBUG_INFO, "%02x ", VendorInfo[Index]));\r
554 }\r
555\r
556 DEBUG ((DEBUG_INFO, "\n"));\r
557}\r
558\r
559/**\r
560 This function get size of TCG_EfiSpecIDEventStruct.\r
561\r
562 @param[in] TcgEfiSpecIdEventStruct A pointer to TCG_EfiSpecIDEventStruct.\r
563**/\r
564UINTN\r
565GetTcgEfiSpecIdEventStructSize (\r
566 IN TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct\r
567 )\r
568{\r
569 TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
570 UINT8 *VendorInfoSize;\r
571 UINT32 NumberOfAlgorithms;\r
572\r
573 CopyMem (&NumberOfAlgorithms, TcgEfiSpecIdEventStruct + 1, sizeof (NumberOfAlgorithms));\r
574\r
575 DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof (*TcgEfiSpecIdEventStruct) + sizeof (NumberOfAlgorithms));\r
576 VendorInfoSize = (UINT8 *)&DigestSize[NumberOfAlgorithms];\r
577 return sizeof (TCG_EfiSpecIDEventStruct) + sizeof (UINT32) + (NumberOfAlgorithms * sizeof (TCG_EfiSpecIdEventAlgorithmSize)) + sizeof (UINT8) + (*VendorInfoSize);\r
578}\r
579\r
580/**\r
581 This function dump TD Event (including the Digests).\r
582\r
583 @param[in] CcEvent TD Event structure.\r
584**/\r
585VOID\r
586DumpCcEvent (\r
587 IN CC_EVENT *CcEvent\r
588 )\r
589{\r
590 UINT32 DigestIndex;\r
591 UINT32 DigestCount;\r
592 TPMI_ALG_HASH HashAlgo;\r
593 UINT32 DigestSize;\r
594 UINT8 *DigestBuffer;\r
595 UINT32 EventSize;\r
596 UINT8 *EventBuffer;\r
597\r
598 DEBUG ((DEBUG_INFO, "Cc Event:\n"));\r
599 DEBUG ((DEBUG_INFO, " MrIndex - %d\n", CcEvent->MrIndex));\r
600 DEBUG ((DEBUG_INFO, " EventType - 0x%08x\n", CcEvent->EventType));\r
601 DEBUG ((DEBUG_INFO, " DigestCount: 0x%08x\n", CcEvent->Digests.count));\r
602\r
603 DigestCount = CcEvent->Digests.count;\r
604 HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
605 DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
606 for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
607 DEBUG ((DEBUG_INFO, " HashAlgo : 0x%04x\n", HashAlgo));\r
608 DEBUG ((DEBUG_INFO, " Digest(%d): \n", DigestIndex));\r
609 DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
610 InternalDumpHex (DigestBuffer, DigestSize);\r
611 //\r
612 // Prepare next\r
613 //\r
614 CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
615 DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
616 }\r
617\r
618 DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
619\r
620 CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
621 DEBUG ((DEBUG_INFO, " EventSize - 0x%08x\n", EventSize));\r
622 EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
623 InternalDumpHex (EventBuffer, EventSize);\r
624 DEBUG ((DEBUG_INFO, "\n"));\r
625}\r
626\r
627/**\r
628 This function returns size of Td Table event.\r
629\r
630 @param[in] CcEvent Td Table event structure.\r
631\r
632 @return size of Td event.\r
633**/\r
634UINTN\r
635GetCcEventSize (\r
636 IN CC_EVENT *CcEvent\r
637 )\r
638{\r
639 UINT32 DigestIndex;\r
640 UINT32 DigestCount;\r
641 TPMI_ALG_HASH HashAlgo;\r
642 UINT32 DigestSize;\r
643 UINT8 *DigestBuffer;\r
644 UINT32 EventSize;\r
645 UINT8 *EventBuffer;\r
646\r
647 DigestCount = CcEvent->Digests.count;\r
648 HashAlgo = CcEvent->Digests.digests[0].hashAlg;\r
649 DigestBuffer = (UINT8 *)&CcEvent->Digests.digests[0].digest;\r
650 for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) {\r
651 DigestSize = GetHashSizeFromAlgo (HashAlgo);\r
652 //\r
653 // Prepare next\r
654 //\r
655 CopyMem (&HashAlgo, DigestBuffer + DigestSize, sizeof (TPMI_ALG_HASH));\r
656 DigestBuffer = DigestBuffer + DigestSize + sizeof (TPMI_ALG_HASH);\r
657 }\r
658\r
659 DigestBuffer = DigestBuffer - sizeof (TPMI_ALG_HASH);\r
660\r
661 CopyMem (&EventSize, DigestBuffer, sizeof (CcEvent->EventSize));\r
662 EventBuffer = DigestBuffer + sizeof (CcEvent->EventSize);\r
663\r
664 return (UINTN)EventBuffer + EventSize - (UINTN)CcEvent;\r
665}\r
666\r
667/**\r
668 This function dump CC event log.\r
669 TDVF only supports EFI_CC_EVENT_LOG_FORMAT_TCG_2\r
670\r
671 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
672 @param[in] EventLogLocation A pointer to the memory address of the event log.\r
673 @param[in] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
674 address of the start of the last entry in the event log in memory.\r
675 @param[in] FinalEventsTable A pointer to the memory address of the final event table.\r
676**/\r
677VOID\r
678DumpCcEventLog (\r
679 IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
680 IN EFI_PHYSICAL_ADDRESS EventLogLocation,\r
681 IN EFI_PHYSICAL_ADDRESS EventLogLastEntry,\r
682 IN EFI_CC_FINAL_EVENTS_TABLE *FinalEventsTable\r
683 )\r
684{\r
685 TCG_PCR_EVENT_HDR *EventHdr;\r
686 CC_EVENT *CcEvent;\r
687 TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
688 UINTN NumberOfEvents;\r
689\r
690 DEBUG ((DEBUG_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
691 ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
692\r
693 //\r
694 // Dump first event.\r
695 // The first event is always the TCG_PCR_EVENT_HDR\r
696 // After this event is a TCG_EfiSpecIDEventStruct\r
697 //\r
698 EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
699 DumpPcrEvent (EventHdr);\r
700\r
701 TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)(EventHdr + 1);\r
702 DumpTcgEfiSpecIdEventStruct (TcgEfiSpecIdEventStruct);\r
703\r
704 //\r
705 // Then the CcEvent (Its structure is similar to TCG_PCR_EVENT2)\r
706 //\r
707 CcEvent = (CC_EVENT *)((UINTN)TcgEfiSpecIdEventStruct + GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct));\r
708 while ((UINTN)CcEvent <= EventLogLastEntry) {\r
709 DumpCcEvent (CcEvent);\r
710 CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
711 }\r
712\r
713 if (FinalEventsTable == NULL) {\r
714 DEBUG ((DEBUG_INFO, "FinalEventsTable: NOT FOUND\n"));\r
715 } else {\r
716 DEBUG ((DEBUG_INFO, "FinalEventsTable: (0x%x)\n", FinalEventsTable));\r
717 DEBUG ((DEBUG_INFO, " Version: (0x%x)\n", FinalEventsTable->Version));\r
718 DEBUG ((DEBUG_INFO, " NumberOfEvents: (0x%x)\n", FinalEventsTable->NumberOfEvents));\r
719\r
720 CcEvent = (CC_EVENT *)(UINTN)(FinalEventsTable + 1);\r
721 for (NumberOfEvents = 0; NumberOfEvents < FinalEventsTable->NumberOfEvents; NumberOfEvents++) {\r
722 DumpCcEvent (CcEvent);\r
723 CcEvent = (CC_EVENT *)((UINTN)CcEvent + GetCcEventSize (CcEvent));\r
724 }\r
725 }\r
726\r
727 return;\r
728}\r
729\r
730/**\r
731 The EFI_CC_MEASUREMENT_PROTOCOL Get Event Log function call allows a caller to\r
732 retrieve the address of a given event log and its last entry.\r
733\r
734 @param[in] This Indicates the calling context\r
735 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
736 @param[out] EventLogLocation A pointer to the memory address of the event log.\r
737 @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
738 address of the start of the last entry in the event log in memory.\r
739 @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would\r
740 have exceeded the area allocated for events, this value is set to TRUE.\r
741 Otherwise, the value will be FALSE and the Event Log will be complete.\r
742\r
743 @retval EFI_SUCCESS Operation completed successfully.\r
744 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect\r
745 (e.g. asking for an event log whose format is not supported).\r
746**/\r
747EFI_STATUS\r
748EFIAPI\r
749TdGetEventLog (\r
750 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
751 IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
752 OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,\r
753 OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,\r
754 OUT BOOLEAN *EventLogTruncated\r
755 )\r
756{\r
757 UINTN Index = 0;\r
758\r
759 DEBUG ((DEBUG_INFO, "TdGetEventLog ... (0x%x)\n", EventLogFormat));\r
760 ASSERT (EventLogFormat == EFI_CC_EVENT_LOG_FORMAT_TCG_2);\r
761\r
762 if (EventLogLocation != NULL) {\r
763 *EventLogLocation = mTdxDxeData.EventLogAreaStruct[Index].Lasa;\r
764 DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
765 }\r
766\r
767 if (EventLogLastEntry != NULL) {\r
768 if (!mTdxDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
769 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
770 } else {\r
771 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTdxDxeData.EventLogAreaStruct[Index].LastEvent;\r
772 }\r
773\r
774 DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
775 }\r
776\r
777 if (EventLogTruncated != NULL) {\r
778 *EventLogTruncated = mTdxDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
779 DEBUG ((DEBUG_INFO, "TdGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
780 }\r
781\r
782 DEBUG ((DEBUG_INFO, "TdGetEventLog - %r\n", EFI_SUCCESS));\r
783\r
784 // Dump Event Log for debug purpose\r
785 if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
786 DumpCcEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry, mTdxDxeData.FinalEventsTable[Index]);\r
787 }\r
788\r
789 //\r
790 // All events generated after the invocation of EFI_TCG2_GET_EVENT_LOG SHALL be stored\r
791 // in an instance of an EFI_CONFIGURATION_TABLE named by the VendorGuid of EFI_TCG2_FINAL_EVENTS_TABLE_GUID.\r
792 //\r
793 mTdxDxeData.GetEventLogCalled[Index] = TRUE;\r
794\r
795 return EFI_SUCCESS;\r
796}\r
797\r
798/**\r
799 Return if this is a Tcg800155PlatformIdEvent.\r
800\r
801 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.\r
802 @param[in] NewEventHdrSize New event header size.\r
803 @param[in] NewEventData Pointer to the new event data.\r
804 @param[in] NewEventSize New event data size.\r
805\r
806 @retval TRUE This is a Tcg800155PlatformIdEvent.\r
807 @retval FALSE This is NOT a Tcg800155PlatformIdEvent.\r
808\r
809**/\r
810BOOLEAN\r
811Is800155Event (\r
812 IN VOID *NewEventHdr,\r
813 IN UINT32 NewEventHdrSize,\r
814 IN UINT8 *NewEventData,\r
815 IN UINT32 NewEventSize\r
816 )\r
817{\r
818 if ((((TCG_PCR_EVENT2_HDR *)NewEventHdr)->EventType == EV_NO_ACTION) &&\r
819 (NewEventSize >= sizeof (TCG_Sp800_155_PlatformId_Event2)) &&\r
820 (CompareMem (\r
821 NewEventData,\r
822 TCG_Sp800_155_PlatformId_Event2_SIGNATURE,\r
823 sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1\r
824 ) == 0))\r
825 {\r
826 return TRUE;\r
827 }\r
828\r
829 return FALSE;\r
830}\r
831\r
832/**\r
833 Add a new entry to the Event Log.\r
834\r
835 @param[in, out] EventLogAreaStruct The event log area data structure\r
836 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.\r
837 @param[in] NewEventHdrSize New event header size.\r
838 @param[in] NewEventData Pointer to the new event data.\r
839 @param[in] NewEventSize New event data size.\r
840\r
841 @retval EFI_SUCCESS The new event log entry was added.\r
842 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
843\r
844**/\r
845EFI_STATUS\r
846TcgCommLogEvent (\r
847 IN OUT CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct,\r
848 IN VOID *NewEventHdr,\r
849 IN UINT32 NewEventHdrSize,\r
850 IN UINT8 *NewEventData,\r
851 IN UINT32 NewEventSize\r
852 )\r
853{\r
854 UINTN NewLogSize;\r
855 BOOLEAN Record800155Event;\r
856 CC_EVENT_HDR *CcEventHdr;\r
857\r
858 CcEventHdr = (CC_EVENT_HDR *)NewEventHdr;\r
859 DEBUG ((DEBUG_VERBOSE, "Td: Try to log event. Index = %d, EventType = 0x%x\n", CcEventHdr->MrIndex, CcEventHdr->EventType));\r
860\r
861 if (NewEventSize > MAX_ADDRESS - NewEventHdrSize) {\r
862 return EFI_OUT_OF_RESOURCES;\r
863 }\r
864\r
865 NewLogSize = NewEventHdrSize + NewEventSize;\r
866\r
867 if (NewLogSize > MAX_ADDRESS - EventLogAreaStruct->EventLogSize) {\r
868 return EFI_OUT_OF_RESOURCES;\r
869 }\r
870\r
871 if (NewLogSize + EventLogAreaStruct->EventLogSize > EventLogAreaStruct->Laml) {\r
872 DEBUG ((DEBUG_INFO, " Laml - 0x%x\n", EventLogAreaStruct->Laml));\r
873 DEBUG ((DEBUG_INFO, " NewLogSize - 0x%x\n", NewLogSize));\r
874 DEBUG ((DEBUG_INFO, " LogSize - 0x%x\n", EventLogAreaStruct->EventLogSize));\r
875 DEBUG ((DEBUG_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
876 return EFI_OUT_OF_RESOURCES;\r
877 }\r
878\r
879 //\r
880 // Check 800-155 event\r
881 // Record to 800-155 event offset only.\r
882 // If the offset is 0, no need to record.\r
883 //\r
884 Record800155Event = Is800155Event (NewEventHdr, NewEventHdrSize, NewEventData, NewEventSize);\r
885 if (Record800155Event) {\r
886 DEBUG ((DEBUG_INFO, "It is 800155Event.\n"));\r
887\r
888 if (EventLogAreaStruct->Next800155EventOffset != 0) {\r
889 CopyMem (\r
890 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewLogSize,\r
891 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
892 EventLogAreaStruct->EventLogSize - EventLogAreaStruct->Next800155EventOffset\r
893 );\r
894\r
895 CopyMem (\r
896 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset,\r
897 NewEventHdr,\r
898 NewEventHdrSize\r
899 );\r
900 CopyMem (\r
901 (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->Next800155EventOffset + NewEventHdrSize,\r
902 NewEventData,\r
903 NewEventSize\r
904 );\r
905\r
906 EventLogAreaStruct->Next800155EventOffset += NewLogSize;\r
907 EventLogAreaStruct->LastEvent += NewLogSize;\r
908 EventLogAreaStruct->EventLogSize += NewLogSize;\r
909 }\r
910\r
911 return EFI_SUCCESS;\r
912 }\r
913\r
914 EventLogAreaStruct->LastEvent = (UINT8 *)(UINTN)EventLogAreaStruct->Lasa + EventLogAreaStruct->EventLogSize;\r
915 EventLogAreaStruct->EventLogSize += NewLogSize;\r
916\r
917 CopyMem (EventLogAreaStruct->LastEvent, NewEventHdr, NewEventHdrSize);\r
918 CopyMem (\r
919 EventLogAreaStruct->LastEvent + NewEventHdrSize,\r
920 NewEventData,\r
921 NewEventSize\r
922 );\r
923\r
924 return EFI_SUCCESS;\r
925}\r
926\r
927/**\r
928 RTMR[0] => PCR[1,7]\r
929 RTMR[1] => PCR[2,3,4,5]\r
930 RTMR[2] => PCR[8~15]\r
931 RTMR[3] => NA\r
932**/\r
933UINT32\r
934EFIAPI\r
935MapPcrToMrIndex (\r
936 IN UINT32 PCRIndex\r
937 )\r
938{\r
939 UINT32 MrIndex;\r
940\r
941 if ((PCRIndex > 16) || (PCRIndex == 6) || (PCRIndex == 0)) {\r
942 ASSERT (FALSE);\r
943 return INVALID_RTMR_INDEX;\r
944 }\r
945\r
946 MrIndex = 0;\r
947 if ((PCRIndex == 1) || (PCRIndex == 7)) {\r
948 MrIndex = 0;\r
949 } else if ((PCRIndex > 1) && (PCRIndex < 6)) {\r
950 MrIndex = 1;\r
951 } else if ((PCRIndex > 7) && (PCRIndex < 16)) {\r
952 MrIndex = 2;\r
953 }\r
954\r
955 return MrIndex;\r
956}\r
957\r
958EFI_STATUS\r
959EFIAPI\r
960TdMapPcrToMrIndex (\r
961 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
962 IN UINT32 PCRIndex,\r
963 OUT UINT32 *MrIndex\r
964 )\r
965{\r
966 if (MrIndex == NULL) {\r
967 return EFI_INVALID_PARAMETER;\r
968 }\r
969\r
970 if ((PCRIndex > 16) || (PCRIndex == 0) || (PCRIndex == 6)) {\r
971 return EFI_INVALID_PARAMETER;\r
972 }\r
973\r
974 *MrIndex = MapPcrToMrIndex (PCRIndex);\r
975\r
976 return *MrIndex == INVALID_RTMR_INDEX ? EFI_INVALID_PARAMETER : EFI_SUCCESS;\r
977}\r
978\r
979/**\r
980 Add a new entry to the Event Log.\r
981\r
982 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
983 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure.\r
984 @param[in] NewEventHdrSize New event header size.\r
985 @param[in] NewEventData Pointer to the new event data.\r
986 @param[in] NewEventSize New event data size.\r
987\r
988 @retval EFI_SUCCESS The new event log entry was added.\r
989 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
990\r
991**/\r
992EFI_STATUS\r
993TdxDxeLogEvent (\r
994 IN EFI_CC_EVENT_LOG_FORMAT EventLogFormat,\r
995 IN VOID *NewEventHdr,\r
996 IN UINT32 NewEventHdrSize,\r
997 IN UINT8 *NewEventData,\r
998 IN UINT32 NewEventSize\r
999 )\r
1000{\r
1001 EFI_STATUS Status;\r
1002 UINTN Index;\r
1003 CC_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct;\r
1004\r
1005 if (EventLogFormat != EFI_CC_EVENT_LOG_FORMAT_TCG_2) {\r
1006 ASSERT (FALSE);\r
1007 return EFI_INVALID_PARAMETER;\r
1008 }\r
1009\r
1010 Index = 0;\r
1011\r
1012 //\r
1013 // Record to normal event log\r
1014 //\r
1015 EventLogAreaStruct = &mTdxDxeData.EventLogAreaStruct[Index];\r
1016\r
1017 if (EventLogAreaStruct->EventLogTruncated) {\r
1018 return EFI_VOLUME_FULL;\r
1019 }\r
1020\r
1021 Status = TcgCommLogEvent (\r
1022 EventLogAreaStruct,\r
1023 NewEventHdr,\r
1024 NewEventHdrSize,\r
1025 NewEventData,\r
1026 NewEventSize\r
1027 );\r
1028\r
1029 if (Status == EFI_OUT_OF_RESOURCES) {\r
1030 EventLogAreaStruct->EventLogTruncated = TRUE;\r
1031 return EFI_VOLUME_FULL;\r
1032 } else if (Status == EFI_SUCCESS) {\r
1033 EventLogAreaStruct->EventLogStarted = TRUE;\r
1034 }\r
1035\r
1036 //\r
1037 // If GetEventLog is called, record to FinalEventsTable, too.\r
1038 //\r
1039 if (mTdxDxeData.GetEventLogCalled[Index]) {\r
1040 if (mTdxDxeData.FinalEventsTable[Index] == NULL) {\r
1041 //\r
1042 // no need for FinalEventsTable\r
1043 //\r
1044 return EFI_SUCCESS;\r
1045 }\r
1046\r
1047 EventLogAreaStruct = &mTdxDxeData.FinalEventLogAreaStruct[Index];\r
1048\r
1049 if (EventLogAreaStruct->EventLogTruncated) {\r
1050 return EFI_VOLUME_FULL;\r
1051 }\r
1052\r
1053 Status = TcgCommLogEvent (\r
1054 EventLogAreaStruct,\r
1055 NewEventHdr,\r
1056 NewEventHdrSize,\r
1057 NewEventData,\r
1058 NewEventSize\r
1059 );\r
1060 if (Status == EFI_OUT_OF_RESOURCES) {\r
1061 EventLogAreaStruct->EventLogTruncated = TRUE;\r
1062 return EFI_VOLUME_FULL;\r
1063 } else if (Status == EFI_SUCCESS) {\r
1064 EventLogAreaStruct->EventLogStarted = TRUE;\r
1065 //\r
1066 // Increase the NumberOfEvents in FinalEventsTable\r
1067 //\r
1068 (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents++;\r
1069 DEBUG ((DEBUG_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents));\r
1070 DEBUG ((DEBUG_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize));\r
1071 }\r
1072 }\r
1073\r
1074 return Status;\r
1075}\r
1076\r
1077/**\r
1078 Get TPML_DIGEST_VALUES compact binary buffer size.\r
1079\r
1080 @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
1081\r
1082 @return TPML_DIGEST_VALUES compact binary buffer size.\r
1083**/\r
1084UINT32\r
1085GetDigestListBinSize (\r
1086 IN VOID *DigestListBin\r
1087 )\r
1088{\r
1089 UINTN Index;\r
1090 UINT16 DigestSize;\r
1091 UINT32 TotalSize;\r
1092 UINT32 Count;\r
1093 TPMI_ALG_HASH HashAlg;\r
1094\r
1095 Count = ReadUnaligned32 (DigestListBin);\r
1096 TotalSize = sizeof (Count);\r
1097 DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
1098 for (Index = 0; Index < Count; Index++) {\r
1099 HashAlg = ReadUnaligned16 (DigestListBin);\r
1100 TotalSize += sizeof (HashAlg);\r
1101 DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
1102\r
1103 DigestSize = GetHashSizeFromAlgo (HashAlg);\r
1104 TotalSize += DigestSize;\r
1105 DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
1106 }\r
1107\r
1108 return TotalSize;\r
1109}\r
1110\r
1111/**\r
1112 Copy TPML_DIGEST_VALUES compact binary into a buffer\r
1113\r
1114 @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.\r
1115 @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.\r
1116 @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.\r
1117 @param[out] HashAlgorithmMaskCopied Pointer to HASH bits corresponding to the digests copied.\r
1118\r
1119 @return The end of buffer to hold TPML_DIGEST_VALUES compact binary.\r
1120**/\r
1121VOID *\r
1122CopyDigestListBinToBuffer (\r
1123 IN OUT VOID *Buffer,\r
1124 IN VOID *DigestListBin,\r
1125 IN UINT32 HashAlgorithmMask,\r
1126 OUT UINT32 *HashAlgorithmMaskCopied\r
1127 )\r
1128{\r
1129 UINTN Index;\r
1130 UINT16 DigestSize;\r
1131 UINT32 Count;\r
1132 TPMI_ALG_HASH HashAlg;\r
1133 UINT32 DigestListCount;\r
1134 UINT32 *DigestListCountPtr;\r
1135\r
1136 DigestListCountPtr = (UINT32 *)Buffer;\r
1137 DigestListCount = 0;\r
1138 *HashAlgorithmMaskCopied = 0;\r
1139\r
1140 Count = ReadUnaligned32 (DigestListBin);\r
1141 Buffer = (UINT8 *)Buffer + sizeof (Count);\r
1142 DigestListBin = (UINT8 *)DigestListBin + sizeof (Count);\r
1143 for (Index = 0; Index < Count; Index++) {\r
1144 HashAlg = ReadUnaligned16 (DigestListBin);\r
1145 DigestListBin = (UINT8 *)DigestListBin + sizeof (HashAlg);\r
1146 DigestSize = GetHashSizeFromAlgo (HashAlg);\r
1147\r
1148 if ((HashAlg & HashAlgorithmMask) != 0) {\r
1149 CopyMem (Buffer, &HashAlg, sizeof (HashAlg));\r
1150 Buffer = (UINT8 *)Buffer + sizeof (HashAlg);\r
1151 CopyMem (Buffer, DigestListBin, DigestSize);\r
1152 Buffer = (UINT8 *)Buffer + DigestSize;\r
1153 DigestListCount++;\r
1154 (*HashAlgorithmMaskCopied) |= GetHashMaskFromAlgo (HashAlg);\r
1155 } else {\r
1156 DEBUG ((DEBUG_ERROR, "WARNING: CopyDigestListBinToBuffer Event log has HashAlg unsupported by PCR bank (0x%x)\n", HashAlg));\r
1157 }\r
1158\r
1159 DigestListBin = (UINT8 *)DigestListBin + DigestSize;\r
1160 }\r
1161\r
1162 WriteUnaligned32 (DigestListCountPtr, DigestListCount);\r
1163\r
1164 return Buffer;\r
1165}\r
1166\r
1167/**\r
1168 Add a new entry to the Event Log. The call chain is like below:\r
1169 TdxDxeLogHashEvent -> TdxDxeLogEvent -> TcgCommonLogEvent\r
1170\r
1171 Before this function is called, the event information (including the digest)\r
1172 is ready.\r
1173\r
1174 @param[in] DigestList A list of digest.\r
1175 @param[in,out] NewEventHdr Pointer to a TD_EVENT_HDR data structure.\r
1176 @param[in] NewEventData Pointer to the new event data.\r
1177\r
1178 @retval EFI_SUCCESS The new event log entry was added.\r
1179 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
1180**/\r
1181EFI_STATUS\r
1182TdxDxeLogHashEvent (\r
1183 IN TPML_DIGEST_VALUES *DigestList,\r
1184 IN OUT CC_EVENT_HDR *NewEventHdr,\r
1185 IN UINT8 *NewEventData\r
1186 )\r
1187{\r
1188 EFI_STATUS Status;\r
1189 EFI_TPL OldTpl;\r
1190 EFI_STATUS RetStatus;\r
1191 CC_EVENT CcEvent;\r
1192 UINT8 *DigestBuffer;\r
1193 UINT32 *EventSizePtr;\r
1194 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
1195\r
1196 RetStatus = EFI_SUCCESS;\r
1197 LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
1198\r
1199 ZeroMem (&CcEvent, sizeof (CcEvent));\r
1200 //\r
1201 // The index of event log is designed as below:\r
1202 // 0 : MRTD\r
1203 // 1-4: RTMR[0-3]\r
1204 //\r
1205 CcEvent.MrIndex = NewEventHdr->MrIndex + 1;\r
1206 CcEvent.EventType = NewEventHdr->EventType;\r
1207 DigestBuffer = (UINT8 *)&CcEvent.Digests;\r
1208 EventSizePtr = CopyDigestListToBuffer (DigestBuffer, DigestList, HASH_ALG_SHA384);\r
1209 CopyMem (EventSizePtr, &NewEventHdr->EventSize, sizeof (NewEventHdr->EventSize));\r
1210\r
1211 //\r
1212 // Enter critical region\r
1213 //\r
1214 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
1215 Status = TdxDxeLogEvent (\r
1216 LogFormat,\r
1217 &CcEvent,\r
1218 sizeof (CcEvent.MrIndex) + sizeof (CcEvent.EventType) + GetDigestListBinSize (DigestBuffer) + sizeof (CcEvent.EventSize),\r
1219 NewEventData,\r
1220 NewEventHdr->EventSize\r
1221 );\r
1222 if (Status != EFI_SUCCESS) {\r
1223 RetStatus = Status;\r
1224 }\r
1225\r
1226 gBS->RestoreTPL (OldTpl);\r
1227\r
1228 return RetStatus;\r
1229}\r
1230\r
1231/**\r
1232 Do a hash operation on a data buffer, extend a specific RTMR with the hash result,\r
1233 and add an entry to the Event Log.\r
1234\r
1235 @param[in] Flags Bitmap providing additional information.\r
1236 @param[in] HashData Physical address of the start of the data buffer\r
1237 to be hashed, extended, and logged.\r
1238 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
1239 @param[in, out] NewEventHdr Pointer to a TD_EVENT_HDR data structure.\r
1240 @param[in] NewEventData Pointer to the new event data.\r
1241\r
1242 @retval EFI_SUCCESS Operation completed successfully.\r
1243 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
1244 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
1245\r
1246**/\r
1247EFI_STATUS\r
1248TdxDxeHashLogExtendEvent (\r
1249 IN UINT64 Flags,\r
1250 IN UINT8 *HashData,\r
1251 IN UINT64 HashDataLen,\r
1252 IN OUT CC_EVENT_HDR *NewEventHdr,\r
1253 IN UINT8 *NewEventData\r
1254 )\r
1255{\r
1256 EFI_STATUS Status;\r
1257 TPML_DIGEST_VALUES DigestList;\r
1258 CC_EVENT_HDR NoActionEvent;\r
1259\r
1260 if (NewEventHdr->EventType == EV_NO_ACTION) {\r
1261 //\r
1262 // Do not do RTMR extend for EV_NO_ACTION\r
1263 //\r
1264 Status = EFI_SUCCESS;\r
1265 InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize);\r
1266 if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
1267 Status = TdxDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData);\r
1268 }\r
1269\r
1270 return Status;\r
1271 }\r
1272\r
1273 Status = HashAndExtend (\r
1274 NewEventHdr->MrIndex,\r
1275 HashData,\r
1276 (UINTN)HashDataLen,\r
1277 &DigestList\r
1278 );\r
1279 if (!EFI_ERROR (Status)) {\r
1280 if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
1281 Status = TdxDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
1282 }\r
1283 }\r
1284\r
1285 return Status;\r
1286}\r
1287\r
1288/**\r
1289 The EFI_CC_MEASUREMENT_PROTOCOL HashLogExtendEvent function call provides callers with\r
1290 an opportunity to extend and optionally log events without requiring\r
1291 knowledge of actual TPM commands.\r
1292 The extend operation will occur even if this function cannot create an event\r
1293 log entry (e.g. due to the event log being full).\r
1294\r
1295 @param[in] This Indicates the calling context\r
1296 @param[in] Flags Bitmap providing additional information.\r
1297 @param[in] DataToHash Physical address of the start of the data buffer to be hashed.\r
1298 @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash.\r
1299 @param[in] Event Pointer to data buffer containing information about the event.\r
1300\r
1301 @retval EFI_SUCCESS Operation completed successfully.\r
1302 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
1303 @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs.\r
1304 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
1305 @retval EFI_UNSUPPORTED The PE/COFF image type is not supported.\r
1306**/\r
1307EFI_STATUS\r
1308EFIAPI\r
1309TdHashLogExtendEvent (\r
1310 IN EFI_CC_MEASUREMENT_PROTOCOL *This,\r
1311 IN UINT64 Flags,\r
1312 IN EFI_PHYSICAL_ADDRESS DataToHash,\r
1313 IN UINT64 DataToHashLen,\r
1314 IN EFI_CC_EVENT *CcEvent\r
1315 )\r
1316{\r
1317 EFI_STATUS Status;\r
1318 CC_EVENT_HDR NewEventHdr;\r
1319 TPML_DIGEST_VALUES DigestList;\r
1320\r
1321 DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent ...\n"));\r
1322\r
1323 if ((This == NULL) || (CcEvent == NULL)) {\r
1324 return EFI_INVALID_PARAMETER;\r
1325 }\r
1326\r
1327 //\r
1328 // Do not check hash data size for EV_NO_ACTION event.\r
1329 //\r
1330 if ((CcEvent->Header.EventType != EV_NO_ACTION) && (DataToHash == 0)) {\r
1331 return EFI_INVALID_PARAMETER;\r
1332 }\r
1333\r
1334 if (CcEvent->Size < CcEvent->Header.HeaderSize + sizeof (UINT32)) {\r
1335 return EFI_INVALID_PARAMETER;\r
1336 }\r
1337\r
1338 if (CcEvent->Header.MrIndex > 4) {\r
1339 return EFI_INVALID_PARAMETER;\r
1340 }\r
1341\r
1342 NewEventHdr.MrIndex = CcEvent->Header.MrIndex;\r
1343 NewEventHdr.EventType = CcEvent->Header.EventType;\r
1344 NewEventHdr.EventSize = CcEvent->Size - sizeof (UINT32) - CcEvent->Header.HeaderSize;\r
1345 if ((Flags & EFI_CC_FLAG_PE_COFF_IMAGE) != 0) {\r
1346 Status = MeasurePeImageAndExtend (\r
1347 NewEventHdr.MrIndex,\r
1348 DataToHash,\r
1349 (UINTN)DataToHashLen,\r
1350 &DigestList\r
1351 );\r
1352 if (!EFI_ERROR (Status)) {\r
1353 if ((Flags & EFI_CC_FLAG_EXTEND_ONLY) == 0) {\r
1354 Status = TdxDxeLogHashEvent (&DigestList, &NewEventHdr, CcEvent->Event);\r
1355 }\r
1356 }\r
1357 } else {\r
1358 Status = TdxDxeHashLogExtendEvent (\r
1359 Flags,\r
1360 (UINT8 *)(UINTN)DataToHash,\r
1361 DataToHashLen,\r
1362 &NewEventHdr,\r
1363 CcEvent->Event\r
1364 );\r
1365 }\r
1366\r
1367 DEBUG ((DEBUG_VERBOSE, "TdHashLogExtendEvent - %r\n", Status));\r
1368 return Status;\r
1369}\r
1370\r
1371EFI_CC_MEASUREMENT_PROTOCOL mTdProtocol = {\r
1372 TdGetCapability,\r
1373 TdGetEventLog,\r
1374 TdHashLogExtendEvent,\r
1375 TdMapPcrToMrIndex,\r
1376};\r
1377\r
1378#define TD_HASH_COUNT 1\r
1379#define TEMP_BUF_LEN (sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) \\r
1380 + (TD_HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8))\r
1381\r
1382/**\r
1383 Initialize the TD Event Log and log events passed from the PEI phase.\r
1384\r
1385 @retval EFI_SUCCESS Operation completed successfully.\r
1386 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1387\r
1388**/\r
1389EFI_STATUS\r
1390SetupCcEventLog (\r
1391 VOID\r
1392 )\r
1393{\r
1394 EFI_STATUS Status;\r
1395 EFI_PHYSICAL_ADDRESS Lasa;\r
1396 UINTN Index;\r
1397 TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;\r
1398 UINT8 TempBuf[TEMP_BUF_LEN];\r
1399 TCG_PCR_EVENT_HDR SpecIdEvent;\r
1400 TCG_EfiSpecIdEventAlgorithmSize *DigestSize;\r
1401 TCG_EfiSpecIdEventAlgorithmSize *TempDigestSize;\r
1402 UINT8 *VendorInfoSize;\r
1403 UINT32 NumberOfAlgorithms;\r
1404 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
1405 EFI_PEI_HOB_POINTERS GuidHob;\r
1406 CC_EVENT_HDR NoActionEvent;\r
1407\r
1408 Status = EFI_SUCCESS;\r
1409 DEBUG ((DEBUG_INFO, "SetupCcEventLog\n"));\r
1410\r
1411 Index = 0;\r
1412 LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
1413\r
1414 //\r
1415 // 1. Create Log Area\r
1416 //\r
1417 mTdxDxeData.EventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
1418\r
1419 // allocate pages for TD Event log\r
1420 Status = gBS->AllocatePages (\r
1421 AllocateAnyPages,\r
1422 EfiACPIMemoryNVS,\r
1423 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
1424 &Lasa\r
1425 );\r
1426 if (EFI_ERROR (Status)) {\r
1427 return Status;\r
1428 }\r
1429\r
1430 mTdxDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
1431 mTdxDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
1432 mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = 0;\r
1433\r
1434 //\r
1435 // Report TD event log address and length, so that they can be reported in\r
1436 // TD ACPI table. Ignore the return status, because those fields are optional.\r
1437 //\r
1438 PcdSet32S (PcdCcEventlogAcpiTableLaml, (UINT32)mTdxDxeData.EventLogAreaStruct[Index].Laml);\r
1439 PcdSet64S (PcdCcEventlogAcpiTableLasa, mTdxDxeData.EventLogAreaStruct[Index].Lasa);\r
1440\r
1441 //\r
1442 // To initialize them as 0xFF is recommended\r
1443 // because the OS can know the last entry for that.\r
1444 //\r
1445 SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
1446\r
1447 //\r
1448 // Create first entry for Log Header Entry Data\r
1449 //\r
1450\r
1451 //\r
1452 // TcgEfiSpecIdEventStruct\r
1453 //\r
1454 TcgEfiSpecIdEventStruct = (TCG_EfiSpecIDEventStruct *)TempBuf;\r
1455 CopyMem (TcgEfiSpecIdEventStruct->signature, TCG_EfiSpecIDEventStruct_SIGNATURE_03, sizeof (TcgEfiSpecIdEventStruct->signature));\r
1456\r
1457 TcgEfiSpecIdEventStruct->platformClass = PcdGet8 (PcdTpmPlatformClass);\r
1458\r
1459 TcgEfiSpecIdEventStruct->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2;\r
1460 TcgEfiSpecIdEventStruct->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2;\r
1461 TcgEfiSpecIdEventStruct->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2;\r
1462 TcgEfiSpecIdEventStruct->uintnSize = sizeof (UINTN)/sizeof (UINT32);\r
1463 NumberOfAlgorithms = 0;\r
1464 DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct\r
1465 + sizeof (*TcgEfiSpecIdEventStruct)\r
1466 + sizeof (NumberOfAlgorithms));\r
1467\r
1468 TempDigestSize = DigestSize;\r
1469 TempDigestSize += NumberOfAlgorithms;\r
1470 TempDigestSize->algorithmId = TPM_ALG_SHA384;\r
1471 TempDigestSize->digestSize = SHA384_DIGEST_SIZE;\r
1472 NumberOfAlgorithms++;\r
1473\r
1474 CopyMem (TcgEfiSpecIdEventStruct + 1, &NumberOfAlgorithms, sizeof (NumberOfAlgorithms));\r
1475 TempDigestSize = DigestSize;\r
1476 TempDigestSize += NumberOfAlgorithms;\r
1477 VendorInfoSize = (UINT8 *)TempDigestSize;\r
1478 *VendorInfoSize = 0;\r
1479\r
1480 SpecIdEvent.PCRIndex = 1; // PCRIndex 0 maps to MrIndex 1\r
1481 SpecIdEvent.EventType = EV_NO_ACTION;\r
1482 ZeroMem (&SpecIdEvent.Digest, sizeof (SpecIdEvent.Digest));\r
1483 SpecIdEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct);\r
1484\r
1485 //\r
1486 // TD Event log re-use the spec of TCG2 Event log.\r
1487 // Log TcgEfiSpecIdEventStruct as the first Event. Event format is TCG_PCR_EVENT.\r
1488 // TCG EFI Protocol Spec. Section 5.3 Event Log Header\r
1489 // TCG PC Client PFP spec. Section 9.2 Measurement Event Entries and Log\r
1490 //\r
1491 Status = TdxDxeLogEvent (\r
1492 LogFormat,\r
1493 &SpecIdEvent,\r
1494 sizeof (SpecIdEvent),\r
1495 (UINT8 *)TcgEfiSpecIdEventStruct,\r
1496 SpecIdEvent.EventSize\r
1497 );\r
1498 //\r
1499 // record the offset at the end of 800-155 event.\r
1500 // the future 800-155 event can be inserted here.\r
1501 //\r
1502 mTdxDxeData.EventLogAreaStruct[Index].Next800155EventOffset = mTdxDxeData.EventLogAreaStruct[Index].EventLogSize;\r
1503\r
1504 //\r
1505 // Tcg800155PlatformIdEvent. Event format is TCG_PCR_EVENT2\r
1506 //\r
1507 GuidHob.Guid = GetFirstGuidHob (&gTcg800155PlatformIdEventHobGuid);\r
1508 while (GuidHob.Guid != NULL) {\r
1509 InitNoActionEvent (&NoActionEvent, GET_GUID_HOB_DATA_SIZE (GuidHob.Guid));\r
1510\r
1511 Status = TdxDxeLogEvent (\r
1512 LogFormat,\r
1513 &NoActionEvent,\r
1514 sizeof (NoActionEvent.MrIndex) + sizeof (NoActionEvent.EventType) + GetDigestListBinSize (&NoActionEvent.Digests) + sizeof (NoActionEvent.EventSize),\r
1515 GET_GUID_HOB_DATA (GuidHob.Guid),\r
1516 GET_GUID_HOB_DATA_SIZE (GuidHob.Guid)\r
1517 );\r
1518\r
1519 GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
1520 GuidHob.Guid = GetNextGuidHob (&gTcg800155PlatformIdEventHobGuid, GuidHob.Guid);\r
1521 }\r
1522\r
1523 //\r
1524 // 2. Create Final Log Area\r
1525 //\r
1526 Status = gBS->AllocatePages (\r
1527 AllocateAnyPages,\r
1528 EfiACPIMemoryNVS,\r
1529 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcg2FinalLogAreaLen)),\r
1530 &Lasa\r
1531 );\r
1532 if (EFI_ERROR (Status)) {\r
1533 return Status;\r
1534 }\r
1535\r
1536 SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcg2FinalLogAreaLen), 0xFF);\r
1537\r
1538 //\r
1539 // Initialize\r
1540 //\r
1541 mTdxDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa;\r
1542 (mTdxDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION;\r
1543 (mTdxDxeData.FinalEventsTable[Index])->NumberOfEvents = 0;\r
1544\r
1545 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = LogFormat;\r
1546 mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
1547 mTdxDxeData.FinalEventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcg2FinalLogAreaLen) - sizeof (EFI_CC_FINAL_EVENTS_TABLE);\r
1548 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0;\r
1549 mTdxDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTdxDxeData.FinalEventLogAreaStruct[Index].Lasa;\r
1550 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE;\r
1551 mTdxDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE;\r
1552 mTdxDxeData.FinalEventLogAreaStruct[Index].Next800155EventOffset = 0;\r
1553\r
1554 //\r
1555 // Install to configuration table for EFI_CC_EVENT_LOG_FORMAT_TCG_2\r
1556 //\r
1557 Status = gBS->InstallConfigurationTable (&gEfiCcFinalEventsTableGuid, (VOID *)mTdxDxeData.FinalEventsTable[Index]);\r
1558 if (EFI_ERROR (Status)) {\r
1559 return Status;\r
1560 }\r
1561\r
1562 return Status;\r
1563}\r
1564\r
1565/**\r
1566 Measure and log an action string, and extend the measurement result into RTMR.\r
1567\r
1568 @param[in] MrIndex MrIndex to extend\r
1569 @param[in] String A specific string that indicates an Action event.\r
1570\r
1571 @retval EFI_SUCCESS Operation completed successfully.\r
1572 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1573\r
1574**/\r
1575EFI_STATUS\r
1576TdMeasureAction (\r
1577 IN UINT32 MrIndex,\r
1578 IN CHAR8 *String\r
1579 )\r
1580{\r
1581 CC_EVENT_HDR CcEvent;\r
1582\r
1583 CcEvent.MrIndex = MrIndex;\r
1584 CcEvent.EventType = EV_EFI_ACTION;\r
1585 CcEvent.EventSize = (UINT32)AsciiStrLen (String);\r
1586 return TdxDxeHashLogExtendEvent (\r
1587 0,\r
1588 (UINT8 *)String,\r
1589 CcEvent.EventSize,\r
1590 &CcEvent,\r
1591 (UINT8 *)String\r
1592 );\r
1593}\r
1594\r
1595/**\r
1596 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
1597\r
1598 @retval EFI_SUCCESS Operation completed successfully.\r
1599 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1600\r
1601**/\r
1602EFI_STATUS\r
1603MeasureHandoffTables (\r
1604 VOID\r
1605 )\r
1606{\r
1607 EFI_STATUS Status;\r
1608 CC_EVENT_HDR CcEvent;\r
1609 EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
1610 UINTN ProcessorNum;\r
1611 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
1612\r
1613 ProcessorLocBuf = NULL;\r
1614 Status = EFI_SUCCESS;\r
1615\r
1616 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
1617 //\r
1618 // Tcg Server spec.\r
1619 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
1620 //\r
1621 Status = GetProcessorsCpuLocation (&ProcessorLocBuf, &ProcessorNum);\r
1622\r
1623 if (!EFI_ERROR (Status)) {\r
1624 CcEvent.MrIndex = MapPcrToMrIndex (1);\r
1625 CcEvent.EventType = EV_TABLE_OF_DEVICES;\r
1626 CcEvent.EventSize = sizeof (HandoffTables);\r
1627\r
1628 HandoffTables.NumberOfTables = 1;\r
1629 HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
1630 HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
1631\r
1632 Status = TdxDxeHashLogExtendEvent (\r
1633 0,\r
1634 (UINT8 *)(UINTN)ProcessorLocBuf,\r
1635 sizeof (EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
1636 &CcEvent,\r
1637 (UINT8 *)&HandoffTables\r
1638 );\r
1639\r
1640 FreePool (ProcessorLocBuf);\r
1641 }\r
1642 }\r
1643\r
1644 return Status;\r
1645}\r
1646\r
1647/**\r
1648 Measure and log Separator event, and extend the measurement result into a specific PCR.\r
1649\r
1650 @param[in] PCRIndex PCR index.\r
1651\r
1652 @retval EFI_SUCCESS Operation completed successfully.\r
1653 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1654\r
1655**/\r
1656EFI_STATUS\r
1657MeasureSeparatorEvent (\r
1658 IN UINT32 MrIndex\r
1659 )\r
1660{\r
1661 CC_EVENT_HDR CcEvent;\r
1662 UINT32 EventData;\r
1663\r
1664 DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent to Rtmr - %d\n", MrIndex));\r
1665\r
1666 EventData = 0;\r
1667 CcEvent.MrIndex = MrIndex;\r
1668 CcEvent.EventType = EV_SEPARATOR;\r
1669 CcEvent.EventSize = (UINT32)sizeof (EventData);\r
1670\r
1671 return TdxDxeHashLogExtendEvent (\r
1672 0,\r
1673 (UINT8 *)&EventData,\r
1674 sizeof (EventData),\r
1675 &CcEvent,\r
1676 (UINT8 *)&EventData\r
1677 );\r
1678}\r
1679\r
1680/**\r
1681 Measure and log an EFI variable, and extend the measurement result into a specific RTMR.\r
1682\r
1683 @param[in] MrIndex RTMR Index.\r
1684 @param[in] EventType Event type.\r
1685 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1686 @param[in] VendorGuid A unique identifier for the vendor.\r
1687 @param[in] VarData The content of the variable data.\r
1688 @param[in] VarSize The size of the variable data.\r
1689\r
1690 @retval EFI_SUCCESS Operation completed successfully.\r
1691 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1692 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1693\r
1694**/\r
1695EFI_STATUS\r
1696MeasureVariable (\r
1697 IN UINT32 MrIndex,\r
1698 IN TCG_EVENTTYPE EventType,\r
1699 IN CHAR16 *VarName,\r
1700 IN EFI_GUID *VendorGuid,\r
1701 IN VOID *VarData,\r
1702 IN UINTN VarSize\r
1703 )\r
1704{\r
1705 EFI_STATUS Status;\r
1706 CC_EVENT_HDR CcEvent;\r
1707 UINTN VarNameLength;\r
1708 UEFI_VARIABLE_DATA *VarLog;\r
1709\r
1710 DEBUG ((DEBUG_INFO, "TdTcg2Dxe: MeasureVariable (Rtmr - %x, EventType - %x, ", (UINTN)MrIndex, (UINTN)EventType));\r
1711 DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
1712\r
1713 VarNameLength = StrLen (VarName);\r
1714 CcEvent.MrIndex = MrIndex;\r
1715 CcEvent.EventType = EventType;\r
1716\r
1717 CcEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
1718 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
1719\r
1720 VarLog = (UEFI_VARIABLE_DATA *)AllocatePool (CcEvent.EventSize);\r
1721 if (VarLog == NULL) {\r
1722 return EFI_OUT_OF_RESOURCES;\r
1723 }\r
1724\r
1725 VarLog->VariableName = *VendorGuid;\r
1726 VarLog->UnicodeNameLength = VarNameLength;\r
1727 VarLog->VariableDataLength = VarSize;\r
1728 CopyMem (\r
1729 VarLog->UnicodeName,\r
1730 VarName,\r
1731 VarNameLength * sizeof (*VarName)\r
1732 );\r
1733 if ((VarSize != 0) && (VarData != NULL)) {\r
1734 CopyMem (\r
1735 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
1736 VarData,\r
1737 VarSize\r
1738 );\r
1739 }\r
1740\r
1741 if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
1742 //\r
1743 // Digest is the event data (UEFI_VARIABLE_DATA)\r
1744 //\r
1745 Status = TdxDxeHashLogExtendEvent (\r
1746 0,\r
1747 (UINT8 *)VarLog,\r
1748 CcEvent.EventSize,\r
1749 &CcEvent,\r
1750 (UINT8 *)VarLog\r
1751 );\r
1752 } else {\r
1753 ASSERT (VarData != NULL);\r
1754 Status = TdxDxeHashLogExtendEvent (\r
1755 0,\r
1756 (UINT8 *)VarData,\r
1757 VarSize,\r
1758 &CcEvent,\r
1759 (UINT8 *)VarLog\r
1760 );\r
1761 }\r
1762\r
1763 FreePool (VarLog);\r
1764 return Status;\r
1765}\r
1766\r
1767/**\r
1768 Read then Measure and log an EFI variable, and extend the measurement result into a specific RTMR.\r
1769\r
1770 @param[in] MrIndex RTMR Index.\r
1771 @param[in] EventType Event type.\r
1772 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1773 @param[in] VendorGuid A unique identifier for the vendor.\r
1774 @param[out] VarSize The size of the variable data.\r
1775 @param[out] VarData Pointer to the content of the variable.\r
1776\r
1777 @retval EFI_SUCCESS Operation completed successfully.\r
1778 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1779 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1780\r
1781**/\r
1782EFI_STATUS\r
1783ReadAndMeasureVariable (\r
1784 IN UINT32 MrIndex,\r
1785 IN TCG_EVENTTYPE EventType,\r
1786 IN CHAR16 *VarName,\r
1787 IN EFI_GUID *VendorGuid,\r
1788 OUT UINTN *VarSize,\r
1789 OUT VOID **VarData\r
1790 )\r
1791{\r
1792 EFI_STATUS Status;\r
1793\r
1794 Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);\r
1795 if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
1796 if (EFI_ERROR (Status)) {\r
1797 //\r
1798 // It is valid case, so we need handle it.\r
1799 //\r
1800 *VarData = NULL;\r
1801 *VarSize = 0;\r
1802 }\r
1803 } else {\r
1804 //\r
1805 // if status error, VarData is freed and set NULL by GetVariable2\r
1806 //\r
1807 if (EFI_ERROR (Status)) {\r
1808 return EFI_NOT_FOUND;\r
1809 }\r
1810 }\r
1811\r
1812 Status = MeasureVariable (\r
1813 MrIndex,\r
1814 EventType,\r
1815 VarName,\r
1816 VendorGuid,\r
1817 *VarData,\r
1818 *VarSize\r
1819 );\r
1820 return Status;\r
1821}\r
1822\r
1823/**\r
1824 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[1].\r
1825according to TCG PC Client PFP spec 0021 Section 2.4.4.2\r
1826\r
1827 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1828 @param[in] VendorGuid A unique identifier for the vendor.\r
1829 @param[out] VarSize The size of the variable data.\r
1830 @param[out] VarData Pointer to the content of the variable.\r
1831\r
1832 @retval EFI_SUCCESS Operation completed successfully.\r
1833 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1834 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1835\r
1836**/\r
1837EFI_STATUS\r
1838ReadAndMeasureBootVariable (\r
1839 IN CHAR16 *VarName,\r
1840 IN EFI_GUID *VendorGuid,\r
1841 OUT UINTN *VarSize,\r
1842 OUT VOID **VarData\r
1843 )\r
1844{\r
1845 //\r
1846 // Boot variables are measured into (PCR[5]) RTMR[1],\r
1847 // details in section 8.1 of TDVF design guide.\r
1848 //\r
1849 return ReadAndMeasureVariable (\r
1850 MapPcrToMrIndex (5),\r
1851 EV_EFI_VARIABLE_BOOT,\r
1852 VarName,\r
1853 VendorGuid,\r
1854 VarSize,\r
1855 VarData\r
1856 );\r
1857}\r
1858\r
1859/**\r
1860 Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].\r
1861\r
1862 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1863 @param[in] VendorGuid A unique identifier for the vendor.\r
1864 @param[out] VarSize The size of the variable data.\r
1865 @param[out] VarData Pointer to the content of the variable.\r
1866\r
1867 @retval EFI_SUCCESS Operation completed successfully.\r
1868 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1869 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1870\r
1871**/\r
1872EFI_STATUS\r
1873ReadAndMeasureSecureVariable (\r
1874 IN CHAR16 *VarName,\r
1875 IN EFI_GUID *VendorGuid,\r
1876 OUT UINTN *VarSize,\r
1877 OUT VOID **VarData\r
1878 )\r
1879{\r
1880 return ReadAndMeasureVariable (\r
1881 MapPcrToMrIndex (7),\r
1882 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
1883 VarName,\r
1884 VendorGuid,\r
1885 VarSize,\r
1886 VarData\r
1887 );\r
1888}\r
1889\r
1890/**\r
1891 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
1892\r
1893 The EFI boot variables are BootOrder and Boot#### variables.\r
1894\r
1895 @retval EFI_SUCCESS Operation completed successfully.\r
1896 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1897 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1898\r
1899**/\r
1900EFI_STATUS\r
1901MeasureAllBootVariables (\r
1902 VOID\r
1903 )\r
1904{\r
1905 EFI_STATUS Status;\r
1906 UINT16 *BootOrder;\r
1907 UINTN BootCount;\r
1908 UINTN Index;\r
1909 VOID *BootVarData;\r
1910 UINTN Size;\r
1911\r
1912 Status = ReadAndMeasureBootVariable (\r
1913 mBootVarName,\r
1914 &gEfiGlobalVariableGuid,\r
1915 &BootCount,\r
1916 (VOID **)&BootOrder\r
1917 );\r
1918 if ((Status == EFI_NOT_FOUND) || (BootOrder == NULL)) {\r
1919 return EFI_SUCCESS;\r
1920 }\r
1921\r
1922 if (EFI_ERROR (Status)) {\r
1923 //\r
1924 // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
1925 //\r
1926 FreePool (BootOrder);\r
1927 return Status;\r
1928 }\r
1929\r
1930 BootCount /= sizeof (*BootOrder);\r
1931 for (Index = 0; Index < BootCount; Index++) {\r
1932 UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
1933 Status = ReadAndMeasureBootVariable (\r
1934 mBootVarName,\r
1935 &gEfiGlobalVariableGuid,\r
1936 &Size,\r
1937 &BootVarData\r
1938 );\r
1939 if (!EFI_ERROR (Status)) {\r
1940 FreePool (BootVarData);\r
1941 }\r
1942 }\r
1943\r
1944 FreePool (BootOrder);\r
1945 return EFI_SUCCESS;\r
1946}\r
1947\r
1948/**\r
1949 Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.\r
1950\r
1951 The EFI boot variables are BootOrder and Boot#### variables.\r
1952\r
1953 @retval EFI_SUCCESS Operation completed successfully.\r
1954 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1955 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1956\r
1957**/\r
1958EFI_STATUS\r
1959MeasureAllSecureVariables (\r
1960 VOID\r
1961 )\r
1962{\r
1963 EFI_STATUS Status;\r
1964 VOID *Data;\r
1965 UINTN DataSize;\r
1966 UINTN Index;\r
1967\r
1968 Status = EFI_NOT_FOUND;\r
1969 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {\r
1970 Status = ReadAndMeasureSecureVariable (\r
1971 mVariableType[Index].VariableName,\r
1972 mVariableType[Index].VendorGuid,\r
1973 &DataSize,\r
1974 &Data\r
1975 );\r
1976 if (!EFI_ERROR (Status)) {\r
1977 if (Data != NULL) {\r
1978 FreePool (Data);\r
1979 }\r
1980 }\r
1981 }\r
1982\r
1983 //\r
1984 // Measure DBT if present and not empty\r
1985 //\r
1986 Status = GetVariable2 (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, &Data, &DataSize);\r
1987 if (!EFI_ERROR (Status)) {\r
1988 Status = MeasureVariable (\r
1989 MapPcrToMrIndex (7),\r
1990 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
1991 EFI_IMAGE_SECURITY_DATABASE2,\r
1992 &gEfiImageSecurityDatabaseGuid,\r
1993 Data,\r
1994 DataSize\r
1995 );\r
1996 FreePool (Data);\r
1997 } else {\r
1998 DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));\r
1999 }\r
2000\r
2001 return EFI_SUCCESS;\r
2002}\r
2003\r
2004/**\r
2005 Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.\r
2006\r
2007 @retval EFI_SUCCESS Operation completed successfully.\r
2008 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
2009 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
2010\r
2011**/\r
2012EFI_STATUS\r
2013MeasureLaunchOfFirmwareDebugger (\r
2014 VOID\r
2015 )\r
2016{\r
2017 CC_EVENT_HDR CcEvent;\r
2018\r
2019 CcEvent.MrIndex = MapPcrToMrIndex (7);\r
2020 CcEvent.EventType = EV_EFI_ACTION;\r
2021 CcEvent.EventSize = sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
2022 return TdxDxeHashLogExtendEvent (\r
2023 0,\r
2024 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
2025 sizeof (FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
2026 &CcEvent,\r
2027 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING\r
2028 );\r
2029}\r
2030\r
2031/**\r
2032 Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.\r
2033\r
2034 Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)\r
2035 - The contents of the SecureBoot variable\r
2036 - The contents of the PK variable\r
2037 - The contents of the KEK variable\r
2038 - The contents of the EFI_IMAGE_SECURITY_DATABASE variable\r
2039 - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable\r
2040 - Separator\r
2041 - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path\r
2042\r
2043 NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,\r
2044 EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].\r
2045\r
2046 @param[in] Event Event whose notification function is being invoked\r
2047 @param[in] Context Pointer to the notification function's context\r
2048**/\r
2049VOID\r
2050EFIAPI\r
2051MeasureSecureBootPolicy (\r
2052 IN EFI_EVENT Event,\r
2053 IN VOID *Context\r
2054 )\r
2055{\r
2056 EFI_STATUS Status;\r
2057 VOID *Protocol;\r
2058\r
2059 Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);\r
2060 if (EFI_ERROR (Status)) {\r
2061 return;\r
2062 }\r
2063\r
2064 if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {\r
2065 Status = MeasureLaunchOfFirmwareDebugger ();\r
2066 DEBUG ((DEBUG_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
2067 }\r
2068\r
2069 Status = MeasureAllSecureVariables ();\r
2070 DEBUG ((DEBUG_INFO, "MeasureAllSecureVariables - %r\n", Status));\r
2071\r
2072 //\r
2073 // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)\r
2074 // and ImageVerification (Authority)\r
2075 // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So\r
2076 // the Authority measurement happen before ReadToBoot event.\r
2077 //\r
2078 Status = MeasureSeparatorEvent (MapPcrToMrIndex (7));\r
2079 DEBUG ((DEBUG_INFO, "MeasureSeparatorEvent - %r\n", Status));\r
2080 return;\r
2081}\r
2082\r
2083/**\r
2084 Ready to Boot Event notification handler.\r
2085\r
2086 Sequence of OS boot events is measured in this event notification handler.\r
2087\r
2088 @param[in] Event Event whose notification function is being invoked\r
2089 @param[in] Context Pointer to the notification function's context\r
2090\r
2091**/\r
2092VOID\r
2093EFIAPI\r
2094OnReadyToBoot (\r
2095 IN EFI_EVENT Event,\r
2096 IN VOID *Context\r
2097 )\r
2098{\r
2099 EFI_STATUS Status;\r
2100\r
2101 PERF_START_EX (mImageHandle, "EventRec", "TdTcg2Dxe", 0, PERF_ID_CC_TCG2_DXE);\r
2102 if (mBootAttempts == 0) {\r
2103 //\r
2104 // Measure handoff tables.\r
2105 //\r
2106 Status = MeasureHandoffTables ();\r
2107 if (EFI_ERROR (Status)) {\r
2108 DEBUG ((DEBUG_ERROR, "HOBs not Measured. Error!\n"));\r
2109 }\r
2110\r
2111 //\r
2112 // Measure BootOrder & Boot#### variables.\r
2113 //\r
2114 Status = MeasureAllBootVariables ();\r
2115 if (EFI_ERROR (Status)) {\r
2116 DEBUG ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n"));\r
2117 }\r
2118\r
2119 //\r
2120 // 1. This is the first boot attempt.\r
2121 //\r
2122 Status = TdMeasureAction (\r
2123 MapPcrToMrIndex (4),\r
2124 EFI_CALLING_EFI_APPLICATION\r
2125 );\r
2126 if (EFI_ERROR (Status)) {\r
2127 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
2128 }\r
2129\r
2130 //\r
2131 // 2. Draw a line between pre-boot env and entering post-boot env.\r
2132 // PCR[7] (is RTMR[0]) is already done.\r
2133 //\r
2134 Status = MeasureSeparatorEvent (1);\r
2135 if (EFI_ERROR (Status)) {\r
2136 DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n"));\r
2137 }\r
2138\r
2139 //\r
2140 // 3. Measure GPT. It would be done in SAP driver.\r
2141 //\r
2142\r
2143 //\r
2144 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
2145 //\r
2146\r
2147 //\r
2148 // 5. Read & Measure variable. BootOrder already measured.\r
2149 //\r
2150 } else {\r
2151 //\r
2152 // 6. Not first attempt, meaning a return from last attempt\r
2153 //\r
2154 Status = TdMeasureAction (\r
2155 MapPcrToMrIndex (4),\r
2156 EFI_RETURNING_FROM_EFI_APPLICATION\r
2157 );\r
2158 if (EFI_ERROR (Status)) {\r
2159 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION));\r
2160 }\r
2161\r
2162 //\r
2163 // 7. Next boot attempt, measure "Calling EFI Application from Boot Option" again\r
2164 // TCG PC Client PFP spec Section 2.4.4.5 Step 4\r
2165 //\r
2166 Status = TdMeasureAction (\r
2167 MapPcrToMrIndex (4),\r
2168 EFI_CALLING_EFI_APPLICATION\r
2169 );\r
2170 if (EFI_ERROR (Status)) {\r
2171 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
2172 }\r
2173 }\r
2174\r
2175 DEBUG ((DEBUG_INFO, "TdTcg2Dxe Measure Data when ReadyToBoot\n"));\r
2176 //\r
2177 // Increase boot attempt counter.\r
2178 //\r
2179 mBootAttempts++;\r
2180 PERF_END_EX (mImageHandle, "EventRec", "Tcg2Dxe", 0, PERF_ID_CC_TCG2_DXE + 1);\r
2181}\r
2182\r
2183/**\r
2184 Exit Boot Services Event notification handler.\r
2185\r
2186 Measure invocation and success of ExitBootServices.\r
2187\r
2188 @param[in] Event Event whose notification function is being invoked\r
2189 @param[in] Context Pointer to the notification function's context\r
2190\r
2191**/\r
2192VOID\r
2193EFIAPI\r
2194OnExitBootServices (\r
2195 IN EFI_EVENT Event,\r
2196 IN VOID *Context\r
2197 )\r
2198{\r
2199 EFI_STATUS Status;\r
2200\r
2201 //\r
2202 // Measure invocation of ExitBootServices,\r
2203 //\r
2204 Status = TdMeasureAction (\r
2205 MapPcrToMrIndex (5),\r
2206 EFI_EXIT_BOOT_SERVICES_INVOCATION\r
2207 );\r
2208 if (EFI_ERROR (Status)) {\r
2209 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
2210 }\r
2211\r
2212 //\r
2213 // Measure success of ExitBootServices\r
2214 //\r
2215 Status = TdMeasureAction (\r
2216 MapPcrToMrIndex (5),\r
2217 EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
2218 );\r
2219 if (EFI_ERROR (Status)) {\r
2220 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
2221 }\r
2222}\r
2223\r
2224/**\r
2225 Exit Boot Services Failed Event notification handler.\r
2226\r
2227 Measure Failure of ExitBootServices.\r
2228\r
2229 @param[in] Event Event whose notification function is being invoked\r
2230 @param[in] Context Pointer to the notification function's context\r
2231\r
2232**/\r
2233VOID\r
2234EFIAPI\r
2235OnExitBootServicesFailed (\r
2236 IN EFI_EVENT Event,\r
2237 IN VOID *Context\r
2238 )\r
2239{\r
2240 EFI_STATUS Status;\r
2241\r
2242 //\r
2243 // Measure Failure of ExitBootServices,\r
2244 //\r
2245 Status = TdMeasureAction (\r
2246 MapPcrToMrIndex (5),\r
2247 EFI_EXIT_BOOT_SERVICES_FAILED\r
2248 );\r
2249 if (EFI_ERROR (Status)) {\r
2250 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
2251 }\r
2252}\r
2253\r
2254EFI_STATUS\r
2255SyncCcEvent (\r
2256 VOID\r
2257 )\r
2258{\r
2259 EFI_STATUS Status;\r
2260 EFI_PEI_HOB_POINTERS GuidHob;\r
2261 VOID *CcEvent;\r
2262 VOID *DigestListBin;\r
2263 UINT32 DigestListBinSize;\r
2264 UINT8 *Event;\r
2265 UINT32 EventSize;\r
2266 EFI_CC_EVENT_LOG_FORMAT LogFormat;\r
2267\r
2268 DEBUG ((DEBUG_INFO, "Sync Cc event from SEC\n"));\r
2269\r
2270 Status = EFI_SUCCESS;\r
2271 LogFormat = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
2272 GuidHob.Guid = GetFirstGuidHob (&gCcEventEntryHobGuid);\r
2273\r
2274 while (!EFI_ERROR (Status) && GuidHob.Guid != NULL) {\r
2275 CcEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid));\r
2276 if (CcEvent == NULL) {\r
2277 return EFI_OUT_OF_RESOURCES;\r
2278 }\r
2279\r
2280 GuidHob.Guid = GET_NEXT_HOB (GuidHob);\r
2281 GuidHob.Guid = GetNextGuidHob (&gCcEventEntryHobGuid, GuidHob.Guid);\r
2282\r
2283 DigestListBin = (UINT8 *)CcEvent + sizeof (UINT32) + sizeof (TCG_EVENTTYPE);\r
2284 DigestListBinSize = GetDigestListBinSize (DigestListBin);\r
2285\r
2286 //\r
2287 // Event size.\r
2288 //\r
2289 EventSize = *(UINT32 *)((UINT8 *)DigestListBin + DigestListBinSize);\r
2290 Event = (UINT8 *)DigestListBin + DigestListBinSize + sizeof (UINT32);\r
2291\r
2292 //\r
2293 // Log the event\r
2294 //\r
2295 Status = TdxDxeLogEvent (\r
2296 LogFormat,\r
2297 CcEvent,\r
2298 sizeof (UINT32) + sizeof (TCG_EVENTTYPE) + DigestListBinSize + sizeof (UINT32),\r
2299 Event,\r
2300 EventSize\r
2301 );\r
2302\r
2303 DumpCcEvent ((CC_EVENT *)CcEvent);\r
2304 FreePool (CcEvent);\r
2305 }\r
2306\r
2307 return Status;\r
2308}\r
2309\r
2310/**\r
2311 Install TDVF ACPI Table when ACPI Table Protocol is available.\r
2312\r
2313 @param[in] Event Event whose notification function is being invoked\r
2314 @param[in] Context Pointer to the notification function's context\r
2315**/\r
2316VOID\r
2317EFIAPI\r
2318InstallAcpiTable (\r
2319 IN EFI_EVENT Event,\r
2320 IN VOID *Context\r
2321 )\r
2322{\r
2323 UINTN TableKey;\r
2324 EFI_STATUS Status;\r
2325 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
2326 UINT64 OemTableId;\r
2327\r
2328 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
2329 if (EFI_ERROR (Status)) {\r
2330 DEBUG ((DEBUG_ERROR, "TD: AcpiTableProtocol is not installed. %r\n", Status));\r
2331 return;\r
2332 }\r
2333\r
2334 mTdxEventlogAcpiTemplate.Laml = (UINT64)PcdGet32 (PcdCcEventlogAcpiTableLaml);\r
2335 mTdxEventlogAcpiTemplate.Lasa = PcdGet64 (PcdCcEventlogAcpiTableLasa);\r
2336 CopyMem (mTdxEventlogAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTdxEventlogAcpiTemplate.Header.OemId));\r
2337 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
2338 CopyMem (&mTdxEventlogAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
2339 mTdxEventlogAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
2340 mTdxEventlogAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
2341 mTdxEventlogAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
2342\r
2343 //\r
2344 // Construct ACPI Table\r
2345 Status = AcpiTable->InstallAcpiTable (\r
2346 AcpiTable,\r
2347 &mTdxEventlogAcpiTemplate,\r
2348 mTdxEventlogAcpiTemplate.Header.Length,\r
2349 &TableKey\r
2350 );\r
2351 ASSERT_EFI_ERROR (Status);\r
2352\r
2353 DEBUG ((DEBUG_INFO, "TDVF Eventlog ACPI Table is installed.\n"));\r
2354}\r
2355\r
2356/**\r
2357 The function install TdTcg2 protocol.\r
2358\r
2359 @retval EFI_SUCCESS TdTcg2 protocol is installed.\r
2360 @retval other Some error occurs.\r
2361**/\r
2362EFI_STATUS\r
2363InstallCcMeasurementProtocol (\r
2364 VOID\r
2365 )\r
2366{\r
2367 EFI_STATUS Status;\r
2368 EFI_HANDLE Handle;\r
2369\r
2370 Handle = NULL;\r
2371 Status = gBS->InstallMultipleProtocolInterfaces (\r
2372 &Handle,\r
2373 &gEfiCcMeasurementProtocolGuid,\r
2374 &mTdProtocol,\r
2375 NULL\r
2376 );\r
2377 DEBUG ((DEBUG_INFO, "CcProtocol: Install %r\n", Status));\r
2378 return Status;\r
2379}\r
2380\r
2381/**\r
2382 The driver's entry point. It publishes EFI Tcg2 Protocol.\r
2383\r
2384 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
2385 @param[in] SystemTable A pointer to the EFI System Table.\r
2386\r
2387 @retval EFI_SUCCESS The entry point is executed successfully.\r
2388 @retval other Some error occurs when executing this entry point.\r
2389**/\r
2390EFI_STATUS\r
2391EFIAPI\r
2392DriverEntry (\r
2393 IN EFI_HANDLE ImageHandle,\r
2394 IN EFI_SYSTEM_TABLE *SystemTable\r
2395 )\r
2396{\r
2397 EFI_STATUS Status;\r
2398 EFI_EVENT Event;\r
2399 VOID *Registration;\r
2400\r
2401 if (!TdIsEnabled ()) {\r
2402 return EFI_UNSUPPORTED;\r
2403 }\r
2404\r
2405 mImageHandle = ImageHandle;\r
2406\r
2407 //\r
2408 // Fill information\r
2409 //\r
2410 // ASSERT (TD_EVENT_LOG_AREA_COUNT_MAX == sizeof(mTEventInfo)/sizeof(mTcg2EventInfo[0]));\r
2411\r
2412 mTdxDxeData.BsCap.Size = sizeof (EFI_CC_BOOT_SERVICE_CAPABILITY);\r
2413 mTdxDxeData.BsCap.ProtocolVersion.Major = 1;\r
2414 mTdxDxeData.BsCap.ProtocolVersion.Minor = 1;\r
2415 mTdxDxeData.BsCap.StructureVersion.Major = 1;\r
2416 mTdxDxeData.BsCap.StructureVersion.Minor = 1;\r
2417\r
2418 //\r
2419 // Get supported PCR and current Active PCRs\r
2420 // For TD gueset HA384 is supported.\r
2421 //\r
2422 mTdxDxeData.BsCap.HashAlgorithmBitmap = HASH_ALG_SHA384;\r
2423\r
2424 // TD guest only supports EFI_TCG2_EVENT_LOG_FORMAT_TCG_2\r
2425 mTdxDxeData.BsCap.SupportedEventLogs = EFI_CC_EVENT_LOG_FORMAT_TCG_2;\r
2426\r
2427 //\r
2428 // Setup the log area and copy event log from hob list to it\r
2429 //\r
2430 Status = SetupCcEventLog ();\r
2431 ASSERT_EFI_ERROR (Status);\r
2432\r
2433 if (!EFI_ERROR (Status)) {\r
2434 Status = SyncCcEvent ();\r
2435 ASSERT_EFI_ERROR (Status);\r
2436 }\r
2437\r
2438 //\r
2439 // Measure handoff tables, Boot#### variables etc.\r
2440 //\r
2441 Status = EfiCreateEventReadyToBootEx (\r
2442 TPL_CALLBACK,\r
2443 OnReadyToBoot,\r
2444 NULL,\r
2445 &Event\r
2446 );\r
2447\r
2448 Status = gBS->CreateEventEx (\r
2449 EVT_NOTIFY_SIGNAL,\r
2450 TPL_NOTIFY,\r
2451 OnExitBootServices,\r
2452 NULL,\r
2453 &gEfiEventExitBootServicesGuid,\r
2454 &Event\r
2455 );\r
2456\r
2457 //\r
2458 // Measure Exit Boot Service failed\r
2459 //\r
2460 Status = gBS->CreateEventEx (\r
2461 EVT_NOTIFY_SIGNAL,\r
2462 TPL_NOTIFY,\r
2463 OnExitBootServicesFailed,\r
2464 NULL,\r
2465 &gEventExitBootServicesFailedGuid,\r
2466 &Event\r
2467 );\r
2468\r
2469 //\r
2470 // Create event callback, because we need access variable on SecureBootPolicyVariable\r
2471 // We should use VariableWriteArch instead of VariableArch, because Variable driver\r
2472 // may update SecureBoot value based on last setting.\r
2473 //\r
2474 EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);\r
2475\r
2476 //\r
2477 // Install CcMeasurementProtocol\r
2478 //\r
2479 Status = InstallCcMeasurementProtocol ();\r
2480 DEBUG ((DEBUG_INFO, "InstallCcMeasurementProtocol - %r\n", Status));\r
2481\r
2482 if (Status == EFI_SUCCESS) {\r
2483 //\r
2484 // Create event callback to install CC EventLog ACPI Table\r
2485 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
2486 }\r
2487\r
2488 return Status;\r
2489}\r