]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c
SecurityPkg/TrEESmm: remove TrEE.
[mirror_edk2.git] / SecurityPkg / Tcg / TrEEDxe / TrEEDxe.c
CommitLineData
c1d93242
JY
1/** @file\r
2 This module implements TrEE Protocol.\r
3 \r
f0f1a3cb 4Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>\r
c1d93242
JY
5This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiDxe.h>\r
16#include <IndustryStandard/Acpi.h>\r
17#include <IndustryStandard/PeImage.h>\r
c1d93242
JY
18#include <IndustryStandard/TcpaAcpi.h>\r
19\r
20#include <Guid/GlobalVariable.h>\r
c1d93242
JY
21#include <Guid/HobList.h>\r
22#include <Guid/TcgEventHob.h>\r
23#include <Guid/EventGroup.h>\r
24#include <Guid/EventExitBootServiceFailed.h>\r
25#include <Guid/ImageAuthentication.h>\r
26#include <Guid/TpmInstance.h>\r
27\r
28#include <Protocol/DevicePath.h>\r
29#include <Protocol/AcpiTable.h>\r
30#include <Protocol/MpService.h>\r
31#include <Protocol/VariableWrite.h>\r
32#include <Protocol/TrEEProtocol.h>\r
33\r
34#include <Library/DebugLib.h>\r
35#include <Library/BaseMemoryLib.h>\r
36#include <Library/UefiRuntimeServicesTableLib.h>\r
37#include <Library/UefiDriverEntryPoint.h>\r
38#include <Library/HobLib.h>\r
39#include <Library/UefiBootServicesTableLib.h>\r
40#include <Library/BaseLib.h>\r
41#include <Library/MemoryAllocationLib.h>\r
42#include <Library/PrintLib.h>\r
43#include <Library/Tpm2CommandLib.h>\r
44#include <Library/PcdLib.h>\r
45#include <Library/UefiLib.h>\r
46#include <Library/Tpm2DeviceLib.h>\r
47#include <Library/HashLib.h>\r
48#include <Library/PerformanceLib.h>\r
6f785cfc 49#include <Library/ReportStatusCodeLib.h>\r
c1d93242
JY
50\r
51#define PERF_ID_TREE_DXE 0x3120\r
52\r
53typedef struct {\r
54 CHAR16 *VariableName;\r
55 EFI_GUID *VendorGuid;\r
56} VARIABLE_TYPE;\r
57\r
c1d93242
JY
58#define TREE_DEFAULT_MAX_COMMAND_SIZE 0x1000\r
59#define TREE_DEFAULT_MAX_RESPONSE_SIZE 0x1000\r
60\r
61typedef struct {\r
62 EFI_GUID *EventGuid;\r
63 TREE_EVENT_LOG_FORMAT LogFormat;\r
c1d93242
JY
64} TREE_EVENT_INFO_STRUCT;\r
65\r
66TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {\r
6f785cfc 67 {&gTcgEventEntryHobGuid, TREE_EVENT_LOG_FORMAT_TCG_1_2},\r
c1d93242
JY
68};\r
69\r
6f785cfc 70#define TCG_EVENT_LOG_AREA_COUNT_MAX 2\r
c1d93242
JY
71\r
72typedef struct {\r
73 TREE_EVENT_LOG_FORMAT EventLogFormat;\r
74 EFI_PHYSICAL_ADDRESS Lasa;\r
75 UINT64 Laml;\r
76 UINTN EventLogSize;\r
77 UINT8 *LastEvent;\r
78 BOOLEAN EventLogStarted;\r
79 BOOLEAN EventLogTruncated;\r
80} TCG_EVENT_LOG_AREA_STRUCT;\r
81\r
82typedef struct _TCG_DXE_DATA {\r
83 TREE_BOOT_SERVICE_CAPABILITY BsCap;\r
84 EFI_TCG_CLIENT_ACPI_TABLE *TcgClientAcpiTable;\r
85 EFI_TCG_SERVER_ACPI_TABLE *TcgServerAcpiTable;\r
86 TCG_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX];\r
87} TCG_DXE_DATA;\r
88\r
89EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate = {\r
90 {\r
91 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
92 sizeof (mTcgClientAcpiTemplate),\r
93 0x02 //Revision\r
94 //\r
95 // Compiler initializes the remaining bytes to 0\r
96 // These fields should be filled in in production\r
97 //\r
98 },\r
99 0, // 0 for PC Client Platform Class\r
100 0, // Log Area Max Length\r
101 (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1) // Log Area Start Address\r
102};\r
103\r
104//\r
105// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,\r
106// the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,\r
107// this _UID can be changed and should match with the _UID setting of the TPM \r
108// ACPI device object \r
109//\r
110EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate = {\r
111 {\r
112 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
113 sizeof (mTcgServerAcpiTemplate),\r
114 0x02 //Revision\r
115 //\r
116 // Compiler initializes the remaining bytes to 0\r
117 // These fields should be filled in in production\r
118 //\r
119 },\r
120 1, // 1 for Server Platform Class\r
121 0, // Reserved\r
122 0, // Log Area Max Length\r
123 (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address\r
124 0x0100, // TCG Specification revision 1.0\r
125 2, // Device Flags\r
126 0, // Interrupt Flags\r
127 0, // GPE\r
128 {0}, // Reserved 3 bytes\r
129 0, // Global System Interrupt\r
130 {\r
131 EFI_ACPI_3_0_SYSTEM_MEMORY,\r
132 0,\r
133 0,\r
134 EFI_ACPI_3_0_BYTE,\r
135 0x0 // Base Address\r
136 },\r
137 0, // Reserved\r
138 {0}, // Configuration Address\r
139 0xFF, // ACPI _UID value of the device, can be changed for different platforms\r
140 0, // ACPI _UID value of the device, can be changed for different platforms\r
141 0, // ACPI _UID value of the device, can be changed for different platforms\r
142 0 // ACPI _UID value of the device, can be changed for different platforms\r
143};\r
144\r
145TCG_DXE_DATA mTcgDxeData = {\r
146 {\r
147 sizeof (TREE_BOOT_SERVICE_CAPABILITY_1_0), // Size\r
148 { 1, 0 }, // StructureVersion\r
149 { 1, 0 }, // ProtocolVersion\r
150 TREE_BOOT_HASH_ALG_SHA1, // HashAlgorithmBitmap\r
151 TREE_EVENT_LOG_FORMAT_TCG_1_2, // SupportedEventLogs\r
152 TRUE, // TrEEPresentFlag\r
153 TREE_DEFAULT_MAX_COMMAND_SIZE, // MaxCommandSize\r
154 TREE_DEFAULT_MAX_RESPONSE_SIZE, // MaxResponseSize\r
155 0 // ManufacturerID\r
156 },\r
157 &mTcgClientAcpiTemplate,\r
158 &mTcgServerAcpiTemplate,\r
159};\r
160\r
161UINTN mBootAttempts = 0;\r
162CHAR16 mBootVarName[] = L"BootOrder";\r
163\r
164VARIABLE_TYPE mVariableType[] = {\r
165 {EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid},\r
166 {EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid},\r
167 {EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid},\r
168 {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid},\r
169 {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},\r
170};\r
171\r
172EFI_HANDLE mImageHandle;\r
173\r
174/**\r
175 Measure PE image into TPM log based on the authenticode image hashing in\r
176 PE/COFF Specification 8.0 Appendix A.\r
177\r
178 Caution: This function may receive untrusted input.\r
179 PE/COFF image is external input, so this function will validate its data structure\r
180 within this image buffer before use.\r
181\r
cad19cd3
LG
182 Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo().\r
183\r
c1d93242
JY
184 @param[in] PCRIndex TPM PCR index\r
185 @param[in] ImageAddress Start address of image buffer.\r
186 @param[in] ImageSize Image size\r
187 @param[out] DigestList Digeest list of this image.\r
188\r
189 @retval EFI_SUCCESS Successfully measure image.\r
190 @retval EFI_OUT_OF_RESOURCES No enough resource to measure image.\r
191 @retval other error value\r
192**/\r
193EFI_STATUS\r
194MeasurePeImageAndExtend (\r
195 IN UINT32 PCRIndex,\r
196 IN EFI_PHYSICAL_ADDRESS ImageAddress,\r
197 IN UINTN ImageSize,\r
198 OUT TPML_DIGEST_VALUES *DigestList\r
199 );\r
200\r
201/**\r
202\r
203 This function dump raw data.\r
204\r
205 @param Data raw data\r
206 @param Size raw data size\r
207\r
208**/\r
209VOID\r
210InternalDumpData (\r
211 IN UINT8 *Data,\r
212 IN UINTN Size\r
213 )\r
214{\r
215 UINTN Index;\r
216 for (Index = 0; Index < Size; Index++) {\r
217 DEBUG ((EFI_D_INFO, "%02x", (UINTN)Data[Index]));\r
218 }\r
219}\r
220\r
221/**\r
222\r
223 This function dump raw data with colume format.\r
224\r
225 @param Data raw data\r
226 @param Size raw data size\r
227\r
228**/\r
229VOID\r
230InternalDumpHex (\r
231 IN UINT8 *Data,\r
232 IN UINTN Size\r
233 )\r
234{\r
235 UINTN Index;\r
236 UINTN Count;\r
237 UINTN Left;\r
238\r
239#define COLUME_SIZE (16 * 2)\r
240\r
241 Count = Size / COLUME_SIZE;\r
242 Left = Size % COLUME_SIZE;\r
243 for (Index = 0; Index < Count; Index++) {\r
244 DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));\r
245 InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);\r
246 DEBUG ((EFI_D_INFO, "\n"));\r
247 }\r
248\r
249 if (Left != 0) {\r
250 DEBUG ((EFI_D_INFO, "%04x: ", Index * COLUME_SIZE));\r
251 InternalDumpData (Data + Index * COLUME_SIZE, Left);\r
252 DEBUG ((EFI_D_INFO, "\n"));\r
253 }\r
254}\r
255\r
256/**\r
257 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function\r
258 Caller is responsible to free LocationBuf.\r
259\r
260 @param[out] LocationBuf Returns Processor Location Buffer.\r
261 @param[out] Num Returns processor number.\r
262\r
263 @retval EFI_SUCCESS Operation completed successfully.\r
264 @retval EFI_UNSUPPORTED MpService protocol not found.\r
265\r
266**/\r
267EFI_STATUS\r
268GetProcessorsCpuLocation (\r
269 OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf,\r
270 OUT UINTN *Num\r
271 )\r
272{\r
273 EFI_STATUS Status;\r
274 EFI_MP_SERVICES_PROTOCOL *MpProtocol;\r
275 UINTN ProcessorNum;\r
276 UINTN EnabledProcessorNum;\r
277 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
278 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
279 UINTN Index;\r
280\r
281 Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);\r
282 if (EFI_ERROR (Status)) {\r
283 //\r
284 // MP protocol is not installed\r
285 //\r
286 return EFI_UNSUPPORTED;\r
287 }\r
288\r
289 Status = MpProtocol->GetNumberOfProcessors(\r
290 MpProtocol,\r
291 &ProcessorNum,\r
292 &EnabledProcessorNum\r
293 );\r
294 if (EFI_ERROR(Status)){\r
295 return Status;\r
296 }\r
297\r
298 Status = gBS->AllocatePool(\r
299 EfiBootServicesData,\r
300 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
301 (VOID **) &ProcessorLocBuf\r
302 );\r
303 if (EFI_ERROR(Status)){\r
304 return Status;\r
305 }\r
306\r
307 //\r
308 // Get each processor Location info\r
309 //\r
310 for (Index = 0; Index < ProcessorNum; Index++) {\r
311 Status = MpProtocol->GetProcessorInfo(\r
312 MpProtocol,\r
313 Index,\r
314 &ProcessorInfo\r
315 );\r
316 if (EFI_ERROR(Status)){\r
317 FreePool(ProcessorLocBuf);\r
318 return Status;\r
319 }\r
320\r
321 //\r
322 // Get all Processor Location info & measure\r
323 //\r
324 CopyMem(\r
325 &ProcessorLocBuf[Index],\r
326 &ProcessorInfo.Location,\r
327 sizeof(EFI_CPU_PHYSICAL_LOCATION)\r
328 );\r
329 }\r
330\r
331 *LocationBuf = ProcessorLocBuf;\r
332 *Num = ProcessorNum;\r
333\r
334 return Status;\r
335}\r
336\r
337/**\r
338 The EFI_TREE_PROTOCOL GetCapability function call provides protocol\r
339 capability information and state information about the TrEE.\r
340\r
341 @param[in] This Indicates the calling context\r
342 @param[in, out] ProtocolCapability The caller allocates memory for a TREE_BOOT_SERVICE_CAPABILITY\r
343 structure and sets the size field to the size of the structure allocated.\r
344 The callee fills in the fields with the EFI protocol capability information\r
345 and the current TrEE state information up to the number of fields which\r
346 fit within the size of the structure passed in.\r
347\r
348 @retval EFI_SUCCESS Operation completed successfully.\r
349 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
350 The ProtocolCapability variable will not be populated. \r
351 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
352 The ProtocolCapability variable will not be populated.\r
353 @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response.\r
354 It will be partially populated (required Size field will be set). \r
355**/\r
356EFI_STATUS\r
357EFIAPI\r
358TreeGetCapability (\r
359 IN EFI_TREE_PROTOCOL *This,\r
360 IN OUT TREE_BOOT_SERVICE_CAPABILITY *ProtocolCapability\r
361 )\r
362{\r
33985e3b 363 DEBUG ((EFI_D_INFO, "TreeGetCapability ...\n"));\r
c1d93242
JY
364\r
365 if ((This == NULL) || (ProtocolCapability == NULL)) {\r
366 return EFI_INVALID_PARAMETER;\r
367 }\r
368\r
369 if (ProtocolCapability->Size < mTcgDxeData.BsCap.Size) {\r
370 ProtocolCapability->Size = mTcgDxeData.BsCap.Size;\r
371 return EFI_BUFFER_TOO_SMALL;\r
372 }\r
373\r
374 CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, mTcgDxeData.BsCap.Size);\r
33985e3b 375 DEBUG ((EFI_D_INFO, "TreeGetCapability - %r\n", EFI_SUCCESS));\r
c1d93242
JY
376 return EFI_SUCCESS;\r
377}\r
378\r
379/**\r
380 This function dump event log.\r
381\r
382 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
383 @param[in] EventLogLocation A pointer to the memory address of the event log.\r
384 @param[in] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
385 address of the start of the last entry in the event log in memory.\r
386**/\r
387VOID\r
388DumpEventLog (\r
389 IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
390 IN EFI_PHYSICAL_ADDRESS EventLogLocation,\r
391 IN EFI_PHYSICAL_ADDRESS EventLogLastEntry\r
392 )\r
393{\r
394 TCG_PCR_EVENT_HDR *EventHdr;\r
395 UINTN Index;\r
396\r
397 DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat));\r
398 \r
399 switch (EventLogFormat) {\r
400 case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
401 EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation;\r
402 while ((UINTN)EventHdr <= EventLogLastEntry) {\r
403 DEBUG ((EFI_D_INFO, " Event:\n"));\r
404 DEBUG ((EFI_D_INFO, " PCRIndex - %d\n", EventHdr->PCRIndex));\r
405 DEBUG ((EFI_D_INFO, " EventType - 0x%08x\n", EventHdr->EventType));\r
406 DEBUG ((EFI_D_INFO, " Digest - "));\r
407 for (Index = 0; Index < sizeof(TCG_DIGEST); Index++) {\r
408 DEBUG ((EFI_D_INFO, "%02x ", EventHdr->Digest.digest[Index]));\r
409 }\r
410 DEBUG ((EFI_D_INFO, "\n"));\r
411 DEBUG ((EFI_D_INFO, " EventSize - 0x%08x\n", EventHdr->EventSize));\r
412 InternalDumpHex ((UINT8 *)(EventHdr + 1), EventHdr->EventSize);\r
413 EventHdr = (TCG_PCR_EVENT_HDR *)((UINTN)EventHdr + sizeof(TCG_PCR_EVENT_HDR) + EventHdr->EventSize);\r
414 }\r
415 break;\r
416 }\r
417\r
418 return ;\r
419}\r
420\r
421/**\r
422 The EFI_TREE_PROTOCOL Get Event Log function call allows a caller to\r
423 retrieve the address of a given event log and its last entry. \r
424\r
425 @param[in] This Indicates the calling context\r
426 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
427 @param[out] EventLogLocation A pointer to the memory address of the event log.\r
428 @param[out] EventLogLastEntry If the Event Log contains more than one entry, this is a pointer to the\r
429 address of the start of the last entry in the event log in memory.\r
430 @param[out] EventLogTruncated If the Event Log is missing at least one entry because an event would\r
431 have exceeded the area allocated for events, this value is set to TRUE.\r
432 Otherwise, the value will be FALSE and the Event Log will be complete.\r
433\r
434 @retval EFI_SUCCESS Operation completed successfully.\r
435 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect\r
436 (e.g. asking for an event log whose format is not supported).\r
437**/\r
438EFI_STATUS\r
439EFIAPI\r
440TreeGetEventLog (\r
441 IN EFI_TREE_PROTOCOL *This,\r
442 IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
443 OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,\r
444 OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry,\r
445 OUT BOOLEAN *EventLogTruncated\r
446 )\r
447{\r
448 UINTN Index;\r
449\r
33985e3b 450 DEBUG ((EFI_D_INFO, "TreeGetEventLog ...\n"));\r
c1d93242
JY
451\r
452 if (This == NULL) {\r
453 return EFI_INVALID_PARAMETER;\r
454 }\r
455\r
456 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
457 if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {\r
458 break;\r
459 }\r
460 }\r
461\r
462 if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {\r
463 return EFI_INVALID_PARAMETER;\r
464 }\r
465\r
466 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
467 if (EventLogLocation != NULL) {\r
468 *EventLogLocation = 0;\r
469 }\r
470 if (EventLogLastEntry != NULL) {\r
471 *EventLogLastEntry = 0;\r
472 }\r
473 if (EventLogTruncated != NULL) {\r
474 *EventLogTruncated = FALSE;\r
475 }\r
476 return EFI_SUCCESS;\r
477 }\r
478\r
479 if (EventLogLocation != NULL) {\r
480 *EventLogLocation = mTcgDxeData.EventLogAreaStruct[Index].Lasa;\r
33985e3b 481 DEBUG ((EFI_D_INFO, "TreeGetEventLog (EventLogLocation - %x)\n", *EventLogLocation));\r
c1d93242
JY
482 }\r
483\r
484 if (EventLogLastEntry != NULL) {\r
485 if (!mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted) {\r
486 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
487 } else {\r
488 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].LastEvent;\r
489 }\r
33985e3b 490 DEBUG ((EFI_D_INFO, "TreeGetEventLog (EventLogLastEntry - %x)\n", *EventLogLastEntry));\r
c1d93242
JY
491 }\r
492\r
493 if (EventLogTruncated != NULL) {\r
494 *EventLogTruncated = mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated;\r
33985e3b 495 DEBUG ((EFI_D_INFO, "TreeGetEventLog (EventLogTruncated - %x)\n", *EventLogTruncated));\r
c1d93242
JY
496 }\r
497\r
33985e3b 498 DEBUG ((EFI_D_INFO, "TreeGetEventLog - %r\n", EFI_SUCCESS));\r
c1d93242
JY
499\r
500 // Dump Event Log for debug purpose\r
501 if ((EventLogLocation != NULL) && (EventLogLastEntry != NULL)) {\r
502 DumpEventLog (EventLogFormat, *EventLogLocation, *EventLogLastEntry);\r
503 }\r
504\r
505 return EFI_SUCCESS;\r
506}\r
507\r
508/**\r
509 Add a new entry to the Event Log.\r
510\r
511 @param[in, out] EventLogPtr Pointer to the Event Log data. \r
512 @param[in, out] LogSize Size of the Event Log. \r
513 @param[in] MaxSize Maximum size of the Event Log.\r
514 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. \r
515 @param[in] NewEventHdrSize New event header size.\r
516 @param[in] NewEventData Pointer to the new event data. \r
517 @param[in] NewEventSize New event data size.\r
518 \r
519 @retval EFI_SUCCESS The new event log entry was added.\r
520 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
521\r
522**/\r
523EFI_STATUS\r
524TcgCommLogEvent (\r
525 IN OUT UINT8 **EventLogPtr,\r
526 IN OUT UINTN *LogSize,\r
527 IN UINTN MaxSize,\r
528 IN VOID *NewEventHdr,\r
529 IN UINT32 NewEventHdrSize,\r
530 IN UINT8 *NewEventData,\r
531 IN UINT32 NewEventSize\r
532 )\r
533{\r
534 UINTN NewLogSize;\r
535\r
536 if (NewEventSize > MAX_ADDRESS - NewEventHdrSize) {\r
537 return EFI_OUT_OF_RESOURCES;\r
538 }\r
539\r
540 NewLogSize = NewEventHdrSize + NewEventSize;\r
541\r
542 if (NewLogSize > MAX_ADDRESS - *LogSize) {\r
543 return EFI_OUT_OF_RESOURCES;\r
544 }\r
545\r
546 if (NewLogSize + *LogSize > MaxSize) {\r
547 DEBUG ((EFI_D_INFO, " MaxSize - 0x%x\n", MaxSize));\r
548 DEBUG ((EFI_D_INFO, " NewLogSize - 0x%x\n", NewLogSize));\r
549 DEBUG ((EFI_D_INFO, " LogSize - 0x%x\n", *LogSize));\r
550 DEBUG ((EFI_D_INFO, "TcgCommLogEvent - %r\n", EFI_OUT_OF_RESOURCES));\r
551 return EFI_OUT_OF_RESOURCES;\r
552 }\r
553\r
554 *EventLogPtr += *LogSize;\r
555 *LogSize += NewLogSize;\r
556 CopyMem (*EventLogPtr, NewEventHdr, NewEventHdrSize);\r
557 CopyMem (\r
558 *EventLogPtr + NewEventHdrSize,\r
559 NewEventData,\r
560 NewEventSize\r
561 );\r
562 return EFI_SUCCESS;\r
563}\r
564\r
565/**\r
566 Add a new entry to the Event Log.\r
567\r
568 @param[in] EventLogFormat The type of the event log for which the information is requested.\r
569 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. \r
570 @param[in] NewEventHdrSize New event header size.\r
571 @param[in] NewEventData Pointer to the new event data. \r
572 @param[in] NewEventSize New event data size.\r
573\r
574 @retval EFI_SUCCESS The new event log entry was added.\r
575 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
576\r
577**/\r
578EFI_STATUS\r
579TcgDxeLogEvent (\r
580 IN TREE_EVENT_LOG_FORMAT EventLogFormat,\r
581 IN VOID *NewEventHdr,\r
582 IN UINT32 NewEventHdrSize,\r
583 IN UINT8 *NewEventData,\r
584 IN UINT32 NewEventSize\r
585 )\r
586{\r
587 EFI_STATUS Status;\r
588 UINTN Index;\r
589\r
590 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
591 if (EventLogFormat == mTreeEventInfo[Index].LogFormat) {\r
592 break;\r
593 }\r
594 }\r
595\r
596 if (Index == sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0])) {\r
597 return EFI_INVALID_PARAMETER;\r
598 }\r
599\r
600 if (mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated) {\r
601 return EFI_VOLUME_FULL;\r
602 }\r
603\r
604 mTcgDxeData.EventLogAreaStruct[Index].LastEvent = (UINT8*)(UINTN)mTcgDxeData.EventLogAreaStruct[Index].Lasa;\r
605 Status = TcgCommLogEvent (\r
606 &mTcgDxeData.EventLogAreaStruct[Index].LastEvent,\r
607 &mTcgDxeData.EventLogAreaStruct[Index].EventLogSize,\r
608 (UINTN)mTcgDxeData.EventLogAreaStruct[Index].Laml,\r
609 NewEventHdr,\r
610 NewEventHdrSize,\r
611 NewEventData,\r
612 NewEventSize\r
613 );\r
614 \r
615 if (Status == EFI_DEVICE_ERROR) {\r
616 return EFI_DEVICE_ERROR;\r
617 } else if (Status == EFI_OUT_OF_RESOURCES) {\r
618 mTcgDxeData.EventLogAreaStruct[Index].EventLogTruncated = TRUE;\r
619 return EFI_VOLUME_FULL;\r
620 } else if (Status == EFI_SUCCESS) {\r
621 mTcgDxeData.EventLogAreaStruct[Index].EventLogStarted = TRUE;\r
622 }\r
623\r
624 return Status;\r
625}\r
626\r
c1d93242
JY
627/**\r
628 Add a new entry to the Event Log.\r
629\r
630 @param[in] DigestList A list of digest.\r
631 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
632 @param[in] NewEventData Pointer to the new event data.\r
633\r
634 @retval EFI_SUCCESS The new event log entry was added.\r
635 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
636**/\r
637EFI_STATUS\r
638TcgDxeLogHashEvent (\r
639 IN TPML_DIGEST_VALUES *DigestList,\r
640 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
641 IN UINT8 *NewEventData\r
642 )\r
643{\r
644 EFI_STATUS Status;\r
645 EFI_TPL OldTpl;\r
646 UINTN Index;\r
647 EFI_STATUS RetStatus;\r
648\r
649 RetStatus = EFI_SUCCESS;\r
650 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
651 DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));\r
652 switch (mTreeEventInfo[Index].LogFormat) {\r
653 case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
d4b9b2c3 654 Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
c1d93242
JY
655 if (!EFI_ERROR (Status)) {\r
656 //\r
657 // Enter critical region\r
658 //\r
659 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
660 Status = TcgDxeLogEvent (\r
661 mTreeEventInfo[Index].LogFormat,\r
662 NewEventHdr,\r
663 sizeof(TCG_PCR_EVENT_HDR),\r
664 NewEventData,\r
665 NewEventHdr->EventSize\r
666 );\r
667 if (Status != EFI_SUCCESS) {\r
668 RetStatus = Status;\r
669 }\r
670 gBS->RestoreTPL (OldTpl);\r
671 //\r
672 // Exit critical region\r
673 //\r
674 }\r
675 break;\r
676 }\r
677 }\r
678\r
679 return RetStatus;\r
680}\r
681\r
682/**\r
683 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
684 and add an entry to the Event Log.\r
685\r
686 @param[in] Flags Bitmap providing additional information.\r
687 @param[in] HashData Physical address of the start of the data buffer \r
688 to be hashed, extended, and logged.\r
689 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
690 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
691 @param[in] NewEventData Pointer to the new event data. \r
692\r
693 @retval EFI_SUCCESS Operation completed successfully.\r
694 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
695 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
696\r
697**/\r
698EFI_STATUS\r
699TcgDxeHashLogExtendEvent (\r
700 IN UINT64 Flags,\r
701 IN UINT8 *HashData,\r
702 IN UINT64 HashDataLen,\r
703 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
704 IN UINT8 *NewEventData\r
705 )\r
706{\r
707 EFI_STATUS Status;\r
708 TPML_DIGEST_VALUES DigestList;\r
6f785cfc
JY
709 \r
710 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
711 return EFI_DEVICE_ERROR;\r
712 }\r
c1d93242
JY
713\r
714 Status = HashAndExtend (\r
715 NewEventHdr->PCRIndex,\r
716 HashData,\r
717 (UINTN)HashDataLen,\r
718 &DigestList\r
719 );\r
720 if (!EFI_ERROR (Status)) {\r
721 if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
722 Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
723 }\r
724 }\r
725\r
6f785cfc
JY
726 if (Status == EFI_DEVICE_ERROR) {\r
727 DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEvent - %r. Disable TPM.\n", Status));\r
728 mTcgDxeData.BsCap.TrEEPresentFlag = FALSE;\r
729 REPORT_STATUS_CODE (\r
730 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
731 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
732 );\r
733 }\r
734\r
c1d93242
JY
735 return Status;\r
736}\r
737\r
738/**\r
739 The EFI_TREE_PROTOCOL HashLogExtendEvent function call provides callers with\r
740 an opportunity to extend and optionally log events without requiring\r
741 knowledge of actual TPM commands. \r
742 The extend operation will occur even if this function cannot create an event\r
743 log entry (e.g. due to the event log being full). \r
744\r
745 @param[in] This Indicates the calling context\r
746 @param[in] Flags Bitmap providing additional information.\r
747 @param[in] DataToHash Physical address of the start of the data buffer to be hashed. \r
748 @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash.\r
749 @param[in] Event Pointer to data buffer containing information about the event.\r
750\r
751 @retval EFI_SUCCESS Operation completed successfully.\r
752 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
753 @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs.\r
754 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
755 @retval EFI_UNSUPPORTED The PE/COFF image type is not supported.\r
756**/\r
757EFI_STATUS\r
758EFIAPI\r
759TreeHashLogExtendEvent (\r
760 IN EFI_TREE_PROTOCOL *This,\r
761 IN UINT64 Flags,\r
762 IN EFI_PHYSICAL_ADDRESS DataToHash,\r
763 IN UINT64 DataToHashLen,\r
764 IN TrEE_EVENT *Event\r
765 )\r
766{\r
767 EFI_STATUS Status;\r
768 TCG_PCR_EVENT_HDR NewEventHdr;\r
769 TPML_DIGEST_VALUES DigestList;\r
770\r
33985e3b 771 DEBUG ((EFI_D_INFO, "TreeHashLogExtendEvent ...\n"));\r
c1d93242
JY
772\r
773 if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) {\r
774 return EFI_INVALID_PARAMETER;\r
775 }\r
776\r
777 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
778 return EFI_UNSUPPORTED;\r
779 }\r
780\r
781 if (Event->Size < Event->Header.HeaderSize + sizeof(UINT32)) {\r
782 return EFI_INVALID_PARAMETER;\r
783 }\r
784\r
785 if (Event->Header.PCRIndex > MAX_PCR_INDEX) {\r
786 return EFI_INVALID_PARAMETER;\r
787 }\r
788\r
789 NewEventHdr.PCRIndex = Event->Header.PCRIndex;\r
790 NewEventHdr.EventType = Event->Header.EventType;\r
791 NewEventHdr.EventSize = Event->Size - sizeof(UINT32) - Event->Header.HeaderSize;\r
792 if ((Flags & PE_COFF_IMAGE) != 0) {\r
793 Status = MeasurePeImageAndExtend (\r
794 NewEventHdr.PCRIndex,\r
795 DataToHash,\r
796 (UINTN)DataToHashLen,\r
797 &DigestList\r
798 );\r
799 if (!EFI_ERROR (Status)) {\r
800 if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
801 Status = TcgDxeLogHashEvent (&DigestList, &NewEventHdr, Event->Event);\r
802 }\r
803 }\r
6f785cfc
JY
804 if (Status == EFI_DEVICE_ERROR) {\r
805 DEBUG ((EFI_D_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status));\r
806 mTcgDxeData.BsCap.TrEEPresentFlag = FALSE;\r
807 REPORT_STATUS_CODE (\r
808 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
809 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
810 );\r
811 }\r
c1d93242
JY
812 } else {\r
813 Status = TcgDxeHashLogExtendEvent (\r
814 Flags,\r
815 (UINT8 *) (UINTN) DataToHash,\r
816 DataToHashLen,\r
817 &NewEventHdr,\r
818 Event->Event\r
819 );\r
820 }\r
33985e3b 821 DEBUG ((EFI_D_INFO, "TreeHashLogExtendEvent - %r\n", Status));\r
c1d93242
JY
822 return Status;\r
823}\r
824\r
825/**\r
826 This service enables the sending of commands to the TrEE.\r
827\r
828 @param[in] This Indicates the calling context\r
829 @param[in] InputParameterBlockSize Size of the TrEE input parameter block.\r
830 @param[in] InputParameterBlock Pointer to the TrEE input parameter block.\r
831 @param[in] OutputParameterBlockSize Size of the TrEE output parameter block.\r
832 @param[in] OutputParameterBlock Pointer to the TrEE output parameter block.\r
833\r
834 @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received.\r
835 @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device.\r
836 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
837 @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. \r
838**/\r
839EFI_STATUS\r
840EFIAPI\r
841TreeSubmitCommand (\r
842 IN EFI_TREE_PROTOCOL *This,\r
843 IN UINT32 InputParameterBlockSize,\r
844 IN UINT8 *InputParameterBlock,\r
845 IN UINT32 OutputParameterBlockSize,\r
846 IN UINT8 *OutputParameterBlock\r
847 )\r
848{\r
849 EFI_STATUS Status;\r
850\r
33985e3b 851 DEBUG ((EFI_D_INFO, "TreeSubmitCommand ...\n"));\r
c1d93242
JY
852\r
853 if ((This == NULL) ||\r
854 (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) ||\r
855 (OutputParameterBlockSize == 0) || (OutputParameterBlock == NULL)) {\r
856 return EFI_INVALID_PARAMETER;\r
857 }\r
858\r
859 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
860 return EFI_UNSUPPORTED;\r
861 }\r
862\r
e1f35834 863 if (InputParameterBlockSize > mTcgDxeData.BsCap.MaxCommandSize) {\r
c1d93242
JY
864 return EFI_INVALID_PARAMETER;\r
865 }\r
e1f35834 866 if (OutputParameterBlockSize > mTcgDxeData.BsCap.MaxResponseSize) {\r
c1d93242
JY
867 return EFI_INVALID_PARAMETER;\r
868 }\r
869\r
870 Status = Tpm2SubmitCommand (\r
871 InputParameterBlockSize,\r
872 InputParameterBlock,\r
873 &OutputParameterBlockSize,\r
874 OutputParameterBlock\r
875 );\r
33985e3b 876 DEBUG ((EFI_D_INFO, "TreeSubmitCommand - %r\n", Status));\r
c1d93242
JY
877 return Status;\r
878}\r
879\r
880\r
881EFI_TREE_PROTOCOL mTreeProtocol = {\r
882 TreeGetCapability,\r
883 TreeGetEventLog,\r
884 TreeHashLogExtendEvent,\r
885 TreeSubmitCommand\r
886};\r
887\r
888/**\r
889 Initialize the Event Log and log events passed from the PEI phase.\r
890\r
891 @retval EFI_SUCCESS Operation completed successfully.\r
892 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
893\r
894**/\r
895EFI_STATUS\r
896SetupEventLog (\r
897 VOID\r
898 )\r
899{\r
900 EFI_STATUS Status;\r
901 VOID *TcgEvent;\r
902 EFI_PEI_HOB_POINTERS GuidHob;\r
903 EFI_PHYSICAL_ADDRESS Lasa;\r
904 UINTN Index;\r
905\r
906 DEBUG ((EFI_D_INFO, "SetupEventLog\n"));\r
907\r
908 //\r
909 // 1. Create Log Area\r
910 //\r
911 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
912 mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTreeEventInfo[Index].LogFormat;\r
913 Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
914 Status = gBS->AllocatePages (\r
915 AllocateMaxAddress,\r
916 EfiACPIMemoryNVS,\r
91e914f5 917 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
c1d93242
JY
918 &Lasa\r
919 );\r
920 if (EFI_ERROR (Status)) {\r
921 return Status;\r
922 }\r
923 mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
91e914f5 924 mTcgDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
c1d93242
JY
925 //\r
926 // To initialize them as 0xFF is recommended \r
927 // because the OS can know the last entry for that.\r
928 //\r
91e914f5 929 SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
c1d93242
JY
930 }\r
931\r
932 //\r
933 // 2. Create ACPI table for TCG1.2 only\r
934 //\r
935 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
936 mTcgClientAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
91e914f5 937 mTcgClientAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
c1d93242
JY
938 } else {\r
939 mTcgServerAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
91e914f5 940 mTcgServerAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
c1d93242
JY
941 }\r
942\r
943 //\r
944 // 3. Sync data from PEI to DXE\r
945 //\r
946 Status = EFI_SUCCESS;\r
947 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
948 GuidHob.Raw = GetHobList ();\r
949 Status = EFI_SUCCESS;\r
950 while (!EFI_ERROR (Status) && \r
951 (GuidHob.Raw = GetNextGuidHob (mTreeEventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) {\r
952 TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);\r
953 GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
954 switch (mTreeEventInfo[Index].LogFormat) {\r
955 case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
956 Status = TcgDxeLogEvent (\r
957 mTreeEventInfo[Index].LogFormat,\r
958 TcgEvent,\r
959 sizeof(TCG_PCR_EVENT_HDR),\r
960 ((TCG_PCR_EVENT*)TcgEvent)->Event,\r
961 ((TCG_PCR_EVENT_HDR*)TcgEvent)->EventSize\r
962 );\r
963 break;\r
964 }\r
965 }\r
966 }\r
967\r
968 return Status;\r
969}\r
970\r
971/**\r
972 Measure and log an action string, and extend the measurement result into PCR[5].\r
973\r
974 @param[in] String A specific string that indicates an Action event. \r
975 \r
976 @retval EFI_SUCCESS Operation completed successfully.\r
977 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
978\r
979**/\r
980EFI_STATUS\r
981TcgMeasureAction (\r
982 IN CHAR8 *String\r
983 )\r
984{\r
985 TCG_PCR_EVENT_HDR TcgEvent;\r
986\r
987 TcgEvent.PCRIndex = 5;\r
988 TcgEvent.EventType = EV_EFI_ACTION;\r
989 TcgEvent.EventSize = (UINT32)AsciiStrLen (String);\r
990 return TcgDxeHashLogExtendEvent (\r
991 0,\r
992 (UINT8*)String,\r
993 TcgEvent.EventSize,\r
994 &TcgEvent,\r
995 (UINT8 *) String\r
996 );\r
997}\r
998\r
999/**\r
1000 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
1001\r
1002 @retval EFI_SUCCESS Operation completed successfully.\r
1003 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1004\r
1005**/\r
1006EFI_STATUS\r
1007MeasureHandoffTables (\r
1008 VOID\r
1009 )\r
1010{\r
1011 EFI_STATUS Status;\r
c1d93242
JY
1012 TCG_PCR_EVENT_HDR TcgEvent;\r
1013 EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
1014 UINTN ProcessorNum;\r
1015 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
1016\r
d4193108 1017 ProcessorLocBuf = NULL;\r
d2de4483 1018 Status = EFI_SUCCESS;\r
c1d93242
JY
1019\r
1020 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
1021 //\r
1022 // Tcg Server spec. \r
1023 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
1024 //\r
1025 Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);\r
1026\r
1027 if (!EFI_ERROR(Status)){\r
1028 TcgEvent.PCRIndex = 1;\r
1029 TcgEvent.EventType = EV_TABLE_OF_DEVICES;\r
1030 TcgEvent.EventSize = sizeof (HandoffTables);\r
1031\r
1032 HandoffTables.NumberOfTables = 1;\r
1033 HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
1034 HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
1035\r
1036 Status = TcgDxeHashLogExtendEvent (\r
1037 0,\r
1038 (UINT8*)(UINTN)ProcessorLocBuf,\r
1039 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
1040 &TcgEvent,\r
1041 (UINT8*)&HandoffTables\r
1042 );\r
1043\r
1044 FreePool(ProcessorLocBuf);\r
1045 }\r
1046 }\r
1047\r
1048 return Status;\r
1049}\r
1050\r
1051/**\r
1052 Measure and log Separator event, and extend the measurement result into a specific PCR.\r
1053\r
1054 @param[in] PCRIndex PCR index. \r
1055\r
1056 @retval EFI_SUCCESS Operation completed successfully.\r
1057 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1058\r
1059**/\r
1060EFI_STATUS\r
1061MeasureSeparatorEvent (\r
1062 IN TPM_PCRINDEX PCRIndex\r
1063 )\r
1064{\r
1065 TCG_PCR_EVENT_HDR TcgEvent;\r
1066 UINT32 EventData;\r
1067\r
33985e3b 1068 DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex));\r
c1d93242
JY
1069\r
1070 EventData = 0;\r
1071 TcgEvent.PCRIndex = PCRIndex;\r
1072 TcgEvent.EventType = EV_SEPARATOR;\r
1073 TcgEvent.EventSize = (UINT32)sizeof (EventData);\r
1074 return TcgDxeHashLogExtendEvent (\r
1075 0,\r
1076 (UINT8 *)&EventData,\r
1077 sizeof (EventData),\r
1078 &TcgEvent,\r
1079 (UINT8 *)&EventData\r
1080 );\r
1081}\r
1082\r
1083/**\r
1084 Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
1085\r
1086 @param[in] PCRIndex PCR Index. \r
1087 @param[in] EventType Event type. \r
1088 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1089 @param[in] VendorGuid A unique identifier for the vendor.\r
1090 @param[in] VarData The content of the variable data. \r
1091 @param[in] VarSize The size of the variable data. \r
1092 \r
1093 @retval EFI_SUCCESS Operation completed successfully.\r
1094 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1095 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1096\r
1097**/\r
1098EFI_STATUS\r
1099MeasureVariable (\r
1100 IN TPM_PCRINDEX PCRIndex,\r
1101 IN TCG_EVENTTYPE EventType,\r
1102 IN CHAR16 *VarName,\r
1103 IN EFI_GUID *VendorGuid,\r
1104 IN VOID *VarData,\r
1105 IN UINTN VarSize\r
1106 )\r
1107{\r
1108 EFI_STATUS Status;\r
1109 TCG_PCR_EVENT_HDR TcgEvent;\r
1110 UINTN VarNameLength;\r
1111 EFI_VARIABLE_DATA_TREE *VarLog;\r
1112\r
33985e3b
CZ
1113 DEBUG ((EFI_D_INFO, "TrEEDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType));\r
1114 DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
c1d93242
JY
1115\r
1116 VarNameLength = StrLen (VarName);\r
1117 TcgEvent.PCRIndex = PCRIndex;\r
1118 TcgEvent.EventType = EventType;\r
1119 TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
1120 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
1121\r
1122 VarLog = (EFI_VARIABLE_DATA_TREE*)AllocatePool (TcgEvent.EventSize);\r
1123 if (VarLog == NULL) {\r
1124 return EFI_OUT_OF_RESOURCES;\r
1125 }\r
1126\r
1127 VarLog->VariableName = *VendorGuid;\r
1128 VarLog->UnicodeNameLength = VarNameLength;\r
1129 VarLog->VariableDataLength = VarSize;\r
1130 CopyMem (\r
1131 VarLog->UnicodeName,\r
1132 VarName,\r
1133 VarNameLength * sizeof (*VarName)\r
1134 );\r
61959fa9 1135 if (VarSize != 0 && VarData != NULL) {\r
c1d93242
JY
1136 CopyMem (\r
1137 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
1138 VarData,\r
1139 VarSize\r
1140 );\r
1141 }\r
1142\r
36811012
CZ
1143 Status = TcgDxeHashLogExtendEvent (\r
1144 0,\r
1145 (UINT8*)VarLog,\r
1146 TcgEvent.EventSize,\r
1147 &TcgEvent,\r
1148 (UINT8*)VarLog\r
1149 );\r
1150\r
c1d93242
JY
1151 FreePool (VarLog);\r
1152 return Status;\r
1153}\r
1154\r
1155/**\r
1156 Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
1157\r
1158 @param[in] PCRIndex PCR Index. \r
1159 @param[in] EventType Event type. \r
1160 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1161 @param[in] VendorGuid A unique identifier for the vendor.\r
1162 @param[out] VarSize The size of the variable data. \r
1163 @param[out] VarData Pointer to the content of the variable. \r
1164 \r
1165 @retval EFI_SUCCESS Operation completed successfully.\r
1166 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1167 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1168\r
1169**/\r
1170EFI_STATUS\r
1171ReadAndMeasureVariable (\r
1172 IN TPM_PCRINDEX PCRIndex,\r
1173 IN TCG_EVENTTYPE EventType,\r
1174 IN CHAR16 *VarName,\r
1175 IN EFI_GUID *VendorGuid,\r
1176 OUT UINTN *VarSize,\r
1177 OUT VOID **VarData\r
1178 )\r
1179{\r
1180 EFI_STATUS Status;\r
1181\r
1182 Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);\r
1183 if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
1184 if (EFI_ERROR (Status)) {\r
1185 //\r
1186 // It is valid case, so we need handle it.\r
1187 //\r
1188 *VarData = NULL;\r
1189 *VarSize = 0;\r
1190 }\r
1191 } else {\r
f7fe68db
CZ
1192 //\r
1193 // if status error, VarData is freed and set NULL by GetVariable2\r
1194 //\r
c1d93242 1195 if (EFI_ERROR (Status)) {\r
f7fe68db 1196 return EFI_NOT_FOUND;\r
c1d93242 1197 }\r
c1d93242
JY
1198 }\r
1199\r
1200 Status = MeasureVariable (\r
1201 PCRIndex,\r
1202 EventType,\r
1203 VarName,\r
1204 VendorGuid,\r
1205 *VarData,\r
1206 *VarSize\r
1207 );\r
1208 return Status;\r
1209}\r
1210\r
1211/**\r
1212 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].\r
1213\r
1214 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1215 @param[in] VendorGuid A unique identifier for the vendor.\r
1216 @param[out] VarSize The size of the variable data. \r
1217 @param[out] VarData Pointer to the content of the variable. \r
1218 \r
1219 @retval EFI_SUCCESS Operation completed successfully.\r
1220 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1221 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1222\r
1223**/\r
1224EFI_STATUS\r
1225ReadAndMeasureBootVariable (\r
1226 IN CHAR16 *VarName,\r
1227 IN EFI_GUID *VendorGuid,\r
1228 OUT UINTN *VarSize,\r
1229 OUT VOID **VarData\r
1230 )\r
1231{\r
1232 return ReadAndMeasureVariable (\r
1233 5,\r
1234 EV_EFI_VARIABLE_BOOT,\r
1235 VarName,\r
1236 VendorGuid,\r
1237 VarSize,\r
1238 VarData\r
1239 );\r
1240}\r
1241\r
1242/**\r
1243 Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].\r
1244\r
1245 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1246 @param[in] VendorGuid A unique identifier for the vendor.\r
1247 @param[out] VarSize The size of the variable data. \r
1248 @param[out] VarData Pointer to the content of the variable. \r
1249 \r
1250 @retval EFI_SUCCESS Operation completed successfully.\r
1251 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1252 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1253\r
1254**/\r
1255EFI_STATUS\r
1256ReadAndMeasureSecureVariable (\r
1257 IN CHAR16 *VarName,\r
1258 IN EFI_GUID *VendorGuid,\r
1259 OUT UINTN *VarSize,\r
1260 OUT VOID **VarData\r
1261 )\r
1262{\r
1263 return ReadAndMeasureVariable (\r
1264 7,\r
1265 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
1266 VarName,\r
1267 VendorGuid,\r
1268 VarSize,\r
1269 VarData\r
1270 );\r
1271}\r
1272\r
1273/**\r
1274 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
1275\r
1276 The EFI boot variables are BootOrder and Boot#### variables.\r
1277\r
1278 @retval EFI_SUCCESS Operation completed successfully.\r
1279 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1280 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1281\r
1282**/\r
1283EFI_STATUS\r
1284MeasureAllBootVariables (\r
1285 VOID\r
1286 )\r
1287{\r
1288 EFI_STATUS Status;\r
1289 UINT16 *BootOrder;\r
1290 UINTN BootCount;\r
1291 UINTN Index;\r
1292 VOID *BootVarData;\r
1293 UINTN Size;\r
1294\r
1295 Status = ReadAndMeasureBootVariable (\r
1296 mBootVarName,\r
1297 &gEfiGlobalVariableGuid,\r
1298 &BootCount,\r
1299 (VOID **) &BootOrder\r
1300 );\r
61959fa9 1301 if (Status == EFI_NOT_FOUND || BootOrder == NULL) {\r
c1d93242
JY
1302 return EFI_SUCCESS;\r
1303 }\r
c1d93242
JY
1304\r
1305 if (EFI_ERROR (Status)) {\r
f7fe68db
CZ
1306 //\r
1307 // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
1308 //\r
c1d93242
JY
1309 FreePool (BootOrder);\r
1310 return Status;\r
1311 }\r
1312\r
1313 BootCount /= sizeof (*BootOrder);\r
1314 for (Index = 0; Index < BootCount; Index++) {\r
1315 UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
1316 Status = ReadAndMeasureBootVariable (\r
1317 mBootVarName,\r
1318 &gEfiGlobalVariableGuid,\r
1319 &Size,\r
1320 &BootVarData\r
1321 );\r
1322 if (!EFI_ERROR (Status)) {\r
1323 FreePool (BootVarData);\r
1324 }\r
1325 }\r
1326\r
1327 FreePool (BootOrder);\r
1328 return EFI_SUCCESS;\r
1329}\r
1330\r
1331/**\r
1332 Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.\r
1333\r
1334 The EFI boot variables are BootOrder and Boot#### variables.\r
1335\r
1336 @retval EFI_SUCCESS Operation completed successfully.\r
1337 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1338 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1339\r
1340**/\r
1341EFI_STATUS\r
1342MeasureAllSecureVariables (\r
1343 VOID\r
1344 )\r
1345{\r
1346 EFI_STATUS Status;\r
1347 VOID *Data;\r
1348 UINTN DataSize;\r
1349 UINTN Index;\r
1350\r
1351 Status = EFI_NOT_FOUND;\r
1352 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
1353 Status = ReadAndMeasureSecureVariable (\r
1354 mVariableType[Index].VariableName,\r
1355 mVariableType[Index].VendorGuid,\r
1356 &DataSize,\r
1357 &Data\r
1358 );\r
1359 if (!EFI_ERROR (Status)) {\r
1360 if (Data != NULL) {\r
1361 FreePool (Data);\r
1362 }\r
1363 }\r
1364 }\r
1365\r
1366 return EFI_SUCCESS;\r
1367}\r
1368\r
1369/**\r
1370 Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.\r
1371\r
1372 @retval EFI_SUCCESS Operation completed successfully.\r
1373 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1374 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1375\r
1376**/\r
1377EFI_STATUS\r
1378MeasureLaunchOfFirmwareDebugger (\r
1379 VOID\r
1380 )\r
1381{\r
1382 TCG_PCR_EVENT_HDR TcgEvent;\r
1383\r
1384 TcgEvent.PCRIndex = 7;\r
1385 TcgEvent.EventType = EV_EFI_ACTION;\r
1386 TcgEvent.EventSize = sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
1387 return TcgDxeHashLogExtendEvent (\r
1388 0,\r
1389 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
1390 sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
1391 &TcgEvent,\r
1392 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING\r
1393 );\r
1394}\r
1395\r
1396/**\r
1397 Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.\r
1398\r
1399 Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)\r
1400 - The contents of the SecureBoot variable\r
1401 - The contents of the PK variable\r
1402 - The contents of the KEK variable\r
1403 - The contents of the EFI_IMAGE_SECURITY_DATABASE variable\r
1404 - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable\r
1405 - Separator\r
1406 - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path\r
1407\r
1408 NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,\r
1409 EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].\r
1410\r
1411 @param[in] Event Event whose notification function is being invoked\r
1412 @param[in] Context Pointer to the notification function's context\r
1413**/\r
1414VOID\r
1415EFIAPI\r
1416MeasureSecureBootPolicy (\r
1417 IN EFI_EVENT Event,\r
1418 IN VOID *Context\r
1419 )\r
1420{\r
1421 EFI_STATUS Status;\r
1422 VOID *Protocol;\r
1423\r
1424 Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);\r
1425 if (EFI_ERROR (Status)) {\r
1426 return;\r
1427 }\r
1428\r
1429 if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {\r
1430 Status = MeasureLaunchOfFirmwareDebugger ();\r
33985e3b 1431 DEBUG ((EFI_D_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
c1d93242
JY
1432 }\r
1433\r
1434 Status = MeasureAllSecureVariables ();\r
33985e3b 1435 DEBUG ((EFI_D_INFO, "MeasureAllSecureVariables - %r\n", Status));\r
c1d93242
JY
1436\r
1437 //\r
1438 // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)\r
1439 // and ImageVerification (Authority)\r
1440 // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So\r
1441 // the Authority measurement happen before ReadToBoot event.\r
1442 //\r
1443 Status = MeasureSeparatorEvent (7);\r
33985e3b 1444 DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent - %r\n", Status));\r
c1d93242
JY
1445 return ;\r
1446}\r
1447\r
1448/**\r
1449 Ready to Boot Event notification handler.\r
1450\r
1451 Sequence of OS boot events is measured in this event notification handler.\r
1452\r
1453 @param[in] Event Event whose notification function is being invoked\r
1454 @param[in] Context Pointer to the notification function's context\r
1455\r
1456**/\r
1457VOID\r
1458EFIAPI\r
1459OnReadyToBoot (\r
1460 IN EFI_EVENT Event,\r
1461 IN VOID *Context\r
1462 )\r
1463{\r
1464 EFI_STATUS Status;\r
1465 TPM_PCRINDEX PcrIndex;\r
1466\r
1467 PERF_START_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE);\r
1468 if (mBootAttempts == 0) {\r
1469\r
1470 //\r
1471 // Measure handoff tables.\r
1472 //\r
1473 Status = MeasureHandoffTables ();\r
1474 if (EFI_ERROR (Status)) {\r
1475 DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));\r
1476 }\r
1477\r
1478 //\r
1479 // Measure BootOrder & Boot#### variables.\r
1480 //\r
1481 Status = MeasureAllBootVariables ();\r
1482 if (EFI_ERROR (Status)) {\r
1483 DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));\r
1484 }\r
1485\r
1486 //\r
1487 // 1. This is the first boot attempt.\r
1488 //\r
1489 Status = TcgMeasureAction (\r
1490 EFI_CALLING_EFI_APPLICATION\r
1491 );\r
6f785cfc 1492 if (EFI_ERROR (Status)) {\r
655dabe3 1493 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
6f785cfc 1494 }\r
c1d93242
JY
1495\r
1496 //\r
1497 // 2. Draw a line between pre-boot env and entering post-boot env.\r
1498 // PCR[7] is already done.\r
1499 //\r
1500 for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) {\r
1501 Status = MeasureSeparatorEvent (PcrIndex);\r
6f785cfc
JY
1502 if (EFI_ERROR (Status)) {\r
1503 DEBUG ((EFI_D_ERROR, "Seperator Event not Measured. Error!\n"));\r
1504 }\r
c1d93242
JY
1505 }\r
1506\r
1507 //\r
1508 // 3. Measure GPT. It would be done in SAP driver.\r
1509 //\r
1510\r
1511 //\r
1512 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
1513 //\r
1514\r
1515 //\r
1516 // 5. Read & Measure variable. BootOrder already measured.\r
1517 //\r
1518 } else {\r
1519 //\r
1520 // 6. Not first attempt, meaning a return from last attempt\r
1521 //\r
1522 Status = TcgMeasureAction (\r
1523 EFI_RETURNING_FROM_EFI_APPLICATOIN\r
1524 );\r
6f785cfc 1525 if (EFI_ERROR (Status)) {\r
655dabe3 1526 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN));\r
6f785cfc 1527 }\r
c1d93242
JY
1528 }\r
1529\r
1530 DEBUG ((EFI_D_INFO, "TPM2 TrEEDxe Measure Data when ReadyToBoot\n"));\r
1531 //\r
1532 // Increase boot attempt counter.\r
1533 //\r
1534 mBootAttempts++;\r
1535 PERF_END_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE + 1);\r
1536}\r
1537\r
1538/**\r
1539 Install TCG ACPI Table when ACPI Table Protocol is available.\r
1540\r
1541 A system's firmware uses an ACPI table to identify the system's TCG capabilities \r
1542 to the Post-Boot environment. The information in this ACPI table is not guaranteed \r
1543 to be valid until the Host Platform transitions from pre-boot state to post-boot state. \r
1544\r
1545 @param[in] Event Event whose notification function is being invoked\r
1546 @param[in] Context Pointer to the notification function's context\r
1547**/\r
1548VOID\r
1549EFIAPI\r
1550InstallAcpiTable (\r
1551 IN EFI_EVENT Event,\r
1552 IN VOID *Context\r
1553 )\r
1554{\r
1555 UINTN TableKey;\r
1556 EFI_STATUS Status;\r
1557 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
1558 UINT8 Checksum;\r
1559 UINT64 OemTableId;\r
1560\r
1561 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
1562 if (EFI_ERROR (Status)) {\r
1563 return;\r
1564 }\r
1565\r
1566 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
1567 CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));\r
1568 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1569 CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1570 mTcgClientAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1571 mTcgClientAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1572 mTcgClientAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
1573 //\r
1574 // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
1575 // service of the ACPI table protocol to install it.\r
1576 //\r
1577 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));\r
1578 mTcgClientAcpiTemplate.Header.Checksum = Checksum;\r
1579\r
1580 Status = AcpiTable->InstallAcpiTable (\r
1581 AcpiTable,\r
1582 &mTcgClientAcpiTemplate,\r
1583 sizeof (mTcgClientAcpiTemplate),\r
1584 &TableKey\r
1585 );\r
1586 } else {\r
1587 CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));\r
1588 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1589 CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1590 mTcgServerAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1591 mTcgServerAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1592 mTcgServerAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
1593 //\r
1594 // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
1595 // service of the ACPI table protocol to install it.\r
1596 //\r
1597 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));\r
1598 mTcgServerAcpiTemplate.Header.Checksum = Checksum;\r
1599\r
1600 mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);\r
1601 Status = AcpiTable->InstallAcpiTable (\r
1602 AcpiTable,\r
1603 &mTcgServerAcpiTemplate,\r
1604 sizeof (mTcgServerAcpiTemplate),\r
1605 &TableKey\r
1606 );\r
1607 }\r
f7fe68db
CZ
1608\r
1609 if (EFI_ERROR (Status)) {\r
1610 DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure"));\r
1611 }\r
c1d93242
JY
1612}\r
1613\r
1614/**\r
1615 Exit Boot Services Event notification handler.\r
1616\r
1617 Measure invocation and success of ExitBootServices.\r
1618\r
1619 @param[in] Event Event whose notification function is being invoked\r
1620 @param[in] Context Pointer to the notification function's context\r
1621\r
1622**/\r
1623VOID\r
1624EFIAPI\r
1625OnExitBootServices (\r
1626 IN EFI_EVENT Event,\r
1627 IN VOID *Context\r
1628 )\r
1629{\r
1630 EFI_STATUS Status;\r
1631\r
1632 //\r
1633 // Measure invocation of ExitBootServices,\r
1634 //\r
1635 Status = TcgMeasureAction (\r
1636 EFI_EXIT_BOOT_SERVICES_INVOCATION\r
1637 );\r
f7fe68db 1638 if (EFI_ERROR (Status)) {\r
655dabe3 1639 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
f7fe68db 1640 }\r
c1d93242
JY
1641\r
1642 //\r
1643 // Measure success of ExitBootServices\r
1644 //\r
1645 Status = TcgMeasureAction (\r
1646 EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
1647 );\r
f7fe68db 1648 if (EFI_ERROR (Status)) {\r
655dabe3 1649 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
f7fe68db 1650 }\r
c1d93242
JY
1651}\r
1652\r
1653/**\r
1654 Exit Boot Services Failed Event notification handler.\r
1655\r
1656 Measure Failure of ExitBootServices.\r
1657\r
1658 @param[in] Event Event whose notification function is being invoked\r
1659 @param[in] Context Pointer to the notification function's context\r
1660\r
1661**/\r
1662VOID\r
1663EFIAPI\r
1664OnExitBootServicesFailed (\r
1665 IN EFI_EVENT Event,\r
1666 IN VOID *Context\r
1667 )\r
1668{\r
1669 EFI_STATUS Status;\r
1670\r
1671 //\r
1672 // Measure Failure of ExitBootServices,\r
1673 //\r
1674 Status = TcgMeasureAction (\r
1675 EFI_EXIT_BOOT_SERVICES_FAILED\r
1676 );\r
f7fe68db 1677 if (EFI_ERROR (Status)) {\r
655dabe3 1678 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
f7fe68db 1679 }\r
c1d93242
JY
1680\r
1681}\r
1682\r
1683/**\r
1684 The function install TrEE protocol.\r
1685 \r
1686 @retval EFI_SUCCESS TrEE protocol is installed.\r
1687 @retval other Some error occurs.\r
1688**/\r
1689EFI_STATUS\r
1690InstallTrEE (\r
1691 VOID\r
1692 )\r
1693{\r
1694 EFI_STATUS Status;\r
1695 EFI_HANDLE Handle;\r
1696\r
1697 Handle = NULL;\r
1698 Status = gBS->InstallMultipleProtocolInterfaces (\r
1699 &Handle,\r
1700 &gEfiTrEEProtocolGuid,\r
1701 &mTreeProtocol,\r
1702 NULL\r
1703 );\r
1704 return Status;\r
1705}\r
1706\r
1707/**\r
1708 The driver's entry point. It publishes EFI TrEE Protocol.\r
1709\r
1710 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
1711 @param[in] SystemTable A pointer to the EFI System Table.\r
1712 \r
1713 @retval EFI_SUCCESS The entry point is executed successfully.\r
1714 @retval other Some error occurs when executing this entry point.\r
1715**/\r
1716EFI_STATUS\r
1717EFIAPI\r
1718DriverEntry (\r
1719 IN EFI_HANDLE ImageHandle,\r
1720 IN EFI_SYSTEM_TABLE *SystemTable\r
1721 )\r
1722{\r
1723 EFI_STATUS Status;\r
1724 EFI_EVENT Event;\r
1725 VOID *Registration;\r
1726 UINT32 MaxCommandSize;\r
1727 UINT32 MaxResponseSize;\r
1728 TPML_PCR_SELECTION Pcrs;\r
1729 UINTN Index;\r
1730 UINT32 TpmHashAlgorithmBitmap;\r
1731\r
1732 mImageHandle = ImageHandle;\r
1733\r
1734 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
1735 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
f0f1a3cb 1736 DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n"));\r
c1d93242
JY
1737 return EFI_UNSUPPORTED;\r
1738 }\r
1739\r
3dd05ac3
JY
1740 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
1741 DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));\r
1742 return EFI_DEVICE_ERROR;\r
1743 }\r
1744 \r
c1d93242
JY
1745 Status = Tpm2RequestUseTpm ();\r
1746 if (EFI_ERROR (Status)) {\r
3dd05ac3 1747 DEBUG ((EFI_D_ERROR, "TPM2 not detected!\n"));\r
c1d93242
JY
1748 return Status;\r
1749 }\r
6f785cfc 1750 \r
c1d93242
JY
1751 //\r
1752 // Fill information\r
1753 //\r
33985e3b
CZ
1754 DEBUG ((EFI_D_INFO, "TrEE.ProtocolVersion - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor));\r
1755 DEBUG ((EFI_D_INFO, "TrEE.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor));\r
c1d93242
JY
1756\r
1757 Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID);\r
1758 if (EFI_ERROR (Status)) {\r
1759 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n"));\r
1760 } else {\r
33985e3b 1761 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID));\r
c1d93242
JY
1762 }\r
1763\r
1764 DEBUG_CODE (\r
1765 UINT32 FirmwareVersion1;\r
1766 UINT32 FirmwareVersion2;\r
1767\r
1768 Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2);\r
1769 if (EFI_ERROR (Status)) {\r
1770 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n"));\r
1771 } else {\r
33985e3b 1772 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2));\r
c1d93242
JY
1773 }\r
1774 );\r
1775\r
1776 Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize);\r
1777 if (EFI_ERROR (Status)) {\r
1778 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n"));\r
1779 } else {\r
1780 mTcgDxeData.BsCap.MaxCommandSize = (UINT16)MaxCommandSize;\r
1781 mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize;\r
33985e3b 1782 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize));\r
c1d93242
JY
1783 }\r
1784\r
1785 Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
1786 if (EFI_ERROR (Status)) {\r
1787 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));\r
1788 TpmHashAlgorithmBitmap = TREE_BOOT_HASH_ALG_SHA1;\r
1789 } else {\r
33985e3b 1790 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));\r
c1d93242
JY
1791 TpmHashAlgorithmBitmap = 0;\r
1792 for (Index = 0; Index < Pcrs.count; Index++) {\r
33985e3b 1793 DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash));\r
c1d93242
JY
1794 switch (Pcrs.pcrSelections[Index].hash) {\r
1795 case TPM_ALG_SHA1:\r
1796 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA1;\r
1797 break;\r
1798 case TPM_ALG_SHA256:\r
1799 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA256;\r
1800 break;\r
1801 case TPM_ALG_SHA384:\r
1802 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA384;\r
1803 break;\r
1804 case TPM_ALG_SHA512:\r
1805 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA512;\r
1806 break;\r
1807 case TPM_ALG_SM3_256:\r
1808 // TBD: Spec not define TREE_BOOT_HASH_ALG_SM3_256 yet\r
1809 break;\r
1810 }\r
1811 }\r
1812 }\r
33985e3b 1813 DEBUG ((EFI_D_INFO, "TPM.HashAlgorithmBitmap - 0x%08x\n", TpmHashAlgorithmBitmap));\r
c1d93242 1814\r
33985e3b 1815 DEBUG ((EFI_D_INFO, "TrEE.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs));\r
c1d93242 1816 mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap;\r
33985e3b 1817 DEBUG ((EFI_D_INFO, "TrEE.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap));\r
c1d93242
JY
1818\r
1819 if (mTcgDxeData.BsCap.TrEEPresentFlag) {\r
1820 //\r
1821 // Setup the log area and copy event log from hob list to it\r
1822 //\r
1823 Status = SetupEventLog ();\r
1824 ASSERT_EFI_ERROR (Status);\r
1825\r
1826 //\r
1827 // Measure handoff tables, Boot#### variables etc.\r
1828 //\r
1829 Status = EfiCreateEventReadyToBootEx (\r
1830 TPL_CALLBACK,\r
1831 OnReadyToBoot,\r
1832 NULL,\r
1833 &Event\r
1834 );\r
1835\r
1836 Status = gBS->CreateEventEx (\r
1837 EVT_NOTIFY_SIGNAL,\r
1838 TPL_NOTIFY,\r
1839 OnExitBootServices,\r
1840 NULL,\r
1841 &gEfiEventExitBootServicesGuid,\r
1842 &Event\r
1843 );\r
1844\r
1845 //\r
1846 // Measure Exit Boot Service failed \r
1847 //\r
1848 Status = gBS->CreateEventEx (\r
1849 EVT_NOTIFY_SIGNAL,\r
1850 TPL_NOTIFY,\r
1851 OnExitBootServicesFailed,\r
1852 NULL,\r
1853 &gEventExitBootServicesFailedGuid,\r
1854 &Event\r
1855 );\r
1856\r
1857 //\r
1858 // Create event callback, because we need access variable on SecureBootPolicyVariable\r
1859 // We should use VariableWriteArch instead of VariableArch, because Variable driver\r
1860 // may update SecureBoot value based on last setting.\r
1861 //\r
1862 EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);\r
1863 }\r
1864\r
1865 //\r
1866 // Install ACPI Table\r
1867 //\r
1868 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
1869\r
1870 //\r
1871 // Install TrEEProtocol\r
1872 //\r
1873 Status = InstallTrEE ();\r
33985e3b 1874 DEBUG ((EFI_D_INFO, "InstallTrEE - %r\n", Status));\r
c1d93242
JY
1875\r
1876 return Status;\r
1877}\r