]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TrEEDxe/TrEEDxe.c
Move Smbios measurement from TCG driver to Smbios driver.
[mirror_edk2.git] / SecurityPkg / Tcg / TrEEDxe / TrEEDxe.c
CommitLineData
c1d93242
JY
1/** @file\r
2 This module implements TrEE Protocol.\r
3 \r
6f785cfc 4Copyright (c) 2013 - 2015, 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
58#define EFI_TCG_LOG_AREA_SIZE 0x10000\r
59\r
60#define TREE_DEFAULT_MAX_COMMAND_SIZE 0x1000\r
61#define TREE_DEFAULT_MAX_RESPONSE_SIZE 0x1000\r
62\r
63typedef struct {\r
64 EFI_GUID *EventGuid;\r
65 TREE_EVENT_LOG_FORMAT LogFormat;\r
c1d93242
JY
66} TREE_EVENT_INFO_STRUCT;\r
67\r
68TREE_EVENT_INFO_STRUCT mTreeEventInfo[] = {\r
6f785cfc 69 {&gTcgEventEntryHobGuid, TREE_EVENT_LOG_FORMAT_TCG_1_2},\r
c1d93242
JY
70};\r
71\r
6f785cfc 72#define TCG_EVENT_LOG_AREA_COUNT_MAX 2\r
c1d93242
JY
73\r
74typedef struct {\r
75 TREE_EVENT_LOG_FORMAT EventLogFormat;\r
76 EFI_PHYSICAL_ADDRESS Lasa;\r
77 UINT64 Laml;\r
78 UINTN EventLogSize;\r
79 UINT8 *LastEvent;\r
80 BOOLEAN EventLogStarted;\r
81 BOOLEAN EventLogTruncated;\r
82} TCG_EVENT_LOG_AREA_STRUCT;\r
83\r
84typedef struct _TCG_DXE_DATA {\r
85 TREE_BOOT_SERVICE_CAPABILITY BsCap;\r
86 EFI_TCG_CLIENT_ACPI_TABLE *TcgClientAcpiTable;\r
87 EFI_TCG_SERVER_ACPI_TABLE *TcgServerAcpiTable;\r
88 TCG_EVENT_LOG_AREA_STRUCT EventLogAreaStruct[TCG_EVENT_LOG_AREA_COUNT_MAX];\r
89} TCG_DXE_DATA;\r
90\r
91EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate = {\r
92 {\r
93 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
94 sizeof (mTcgClientAcpiTemplate),\r
95 0x02 //Revision\r
96 //\r
97 // Compiler initializes the remaining bytes to 0\r
98 // These fields should be filled in in production\r
99 //\r
100 },\r
101 0, // 0 for PC Client Platform Class\r
102 0, // Log Area Max Length\r
103 (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1) // Log Area Start Address\r
104};\r
105\r
106//\r
107// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,\r
108// the TPM device connectes to LPC, and also defined the ACPI _UID as 0xFF,\r
109// this _UID can be changed and should match with the _UID setting of the TPM \r
110// ACPI device object \r
111//\r
112EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate = {\r
113 {\r
114 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
115 sizeof (mTcgServerAcpiTemplate),\r
116 0x02 //Revision\r
117 //\r
118 // Compiler initializes the remaining bytes to 0\r
119 // These fields should be filled in in production\r
120 //\r
121 },\r
122 1, // 1 for Server Platform Class\r
123 0, // Reserved\r
124 0, // Log Area Max Length\r
125 (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address\r
126 0x0100, // TCG Specification revision 1.0\r
127 2, // Device Flags\r
128 0, // Interrupt Flags\r
129 0, // GPE\r
130 {0}, // Reserved 3 bytes\r
131 0, // Global System Interrupt\r
132 {\r
133 EFI_ACPI_3_0_SYSTEM_MEMORY,\r
134 0,\r
135 0,\r
136 EFI_ACPI_3_0_BYTE,\r
137 0x0 // Base Address\r
138 },\r
139 0, // Reserved\r
140 {0}, // Configuration Address\r
141 0xFF, // 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 0, // ACPI _UID value of the device, can be changed for different platforms\r
144 0 // ACPI _UID value of the device, can be changed for different platforms\r
145};\r
146\r
147TCG_DXE_DATA mTcgDxeData = {\r
148 {\r
149 sizeof (TREE_BOOT_SERVICE_CAPABILITY_1_0), // Size\r
150 { 1, 0 }, // StructureVersion\r
151 { 1, 0 }, // ProtocolVersion\r
152 TREE_BOOT_HASH_ALG_SHA1, // HashAlgorithmBitmap\r
153 TREE_EVENT_LOG_FORMAT_TCG_1_2, // SupportedEventLogs\r
154 TRUE, // TrEEPresentFlag\r
155 TREE_DEFAULT_MAX_COMMAND_SIZE, // MaxCommandSize\r
156 TREE_DEFAULT_MAX_RESPONSE_SIZE, // MaxResponseSize\r
157 0 // ManufacturerID\r
158 },\r
159 &mTcgClientAcpiTemplate,\r
160 &mTcgServerAcpiTemplate,\r
161};\r
162\r
163UINTN mBootAttempts = 0;\r
164CHAR16 mBootVarName[] = L"BootOrder";\r
165\r
166VARIABLE_TYPE mVariableType[] = {\r
167 {EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid},\r
168 {EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid},\r
169 {EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid},\r
170 {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid},\r
171 {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},\r
172};\r
173\r
174EFI_HANDLE mImageHandle;\r
175\r
176/**\r
177 Measure PE image into TPM log based on the authenticode image hashing in\r
178 PE/COFF Specification 8.0 Appendix A.\r
179\r
180 Caution: This function may receive untrusted input.\r
181 PE/COFF image is external input, so this function will validate its data structure\r
182 within this image buffer before use.\r
183\r
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 This function get digest from digest list.\r
629\r
630 @param HashAlg digest algorithm\r
631 @param DigestList digest list\r
632 @param Digest digest\r
633\r
634 @retval EFI_SUCCESS Sha1Digest is found and returned.\r
635 @retval EFI_NOT_FOUND Sha1Digest is not found.\r
636**/\r
637EFI_STATUS\r
638Tpm2GetDigestFromDigestList (\r
639 IN TPMI_ALG_HASH HashAlg,\r
640 IN TPML_DIGEST_VALUES *DigestList,\r
641 IN VOID *Digest\r
642 )\r
643{\r
644 UINTN Index;\r
645 UINT16 DigestSize;\r
646\r
647 DigestSize = GetHashSizeFromAlgo (HashAlg);\r
648 for (Index = 0; Index < DigestList->count; Index++) {\r
649 if (DigestList->digests[Index].hashAlg == HashAlg) {\r
650 CopyMem (\r
651 Digest,\r
652 &DigestList->digests[Index].digest,\r
653 DigestSize\r
654 );\r
655 return EFI_SUCCESS;\r
656 }\r
657 }\r
658\r
659 return EFI_NOT_FOUND;\r
660}\r
661\r
662/**\r
663 Add a new entry to the Event Log.\r
664\r
665 @param[in] DigestList A list of digest.\r
666 @param[in,out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
667 @param[in] NewEventData Pointer to the new event data.\r
668\r
669 @retval EFI_SUCCESS The new event log entry was added.\r
670 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
671**/\r
672EFI_STATUS\r
673TcgDxeLogHashEvent (\r
674 IN TPML_DIGEST_VALUES *DigestList,\r
675 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
676 IN UINT8 *NewEventData\r
677 )\r
678{\r
679 EFI_STATUS Status;\r
680 EFI_TPL OldTpl;\r
681 UINTN Index;\r
682 EFI_STATUS RetStatus;\r
683\r
684 RetStatus = EFI_SUCCESS;\r
685 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
686 DEBUG ((EFI_D_INFO, " LogFormat - 0x%08x\n", mTreeEventInfo[Index].LogFormat));\r
687 switch (mTreeEventInfo[Index].LogFormat) {\r
688 case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
689 Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);\r
690 if (!EFI_ERROR (Status)) {\r
691 //\r
692 // Enter critical region\r
693 //\r
694 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
695 Status = TcgDxeLogEvent (\r
696 mTreeEventInfo[Index].LogFormat,\r
697 NewEventHdr,\r
698 sizeof(TCG_PCR_EVENT_HDR),\r
699 NewEventData,\r
700 NewEventHdr->EventSize\r
701 );\r
702 if (Status != EFI_SUCCESS) {\r
703 RetStatus = Status;\r
704 }\r
705 gBS->RestoreTPL (OldTpl);\r
706 //\r
707 // Exit critical region\r
708 //\r
709 }\r
710 break;\r
711 }\r
712 }\r
713\r
714 return RetStatus;\r
715}\r
716\r
717/**\r
718 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
719 and add an entry to the Event Log.\r
720\r
721 @param[in] Flags Bitmap providing additional information.\r
722 @param[in] HashData Physical address of the start of the data buffer \r
723 to be hashed, extended, and logged.\r
724 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
725 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
726 @param[in] NewEventData Pointer to the new event data. \r
727\r
728 @retval EFI_SUCCESS Operation completed successfully.\r
729 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
730 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
731\r
732**/\r
733EFI_STATUS\r
734TcgDxeHashLogExtendEvent (\r
735 IN UINT64 Flags,\r
736 IN UINT8 *HashData,\r
737 IN UINT64 HashDataLen,\r
738 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
739 IN UINT8 *NewEventData\r
740 )\r
741{\r
742 EFI_STATUS Status;\r
743 TPML_DIGEST_VALUES DigestList;\r
6f785cfc
JY
744 \r
745 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
746 return EFI_DEVICE_ERROR;\r
747 }\r
c1d93242
JY
748\r
749 Status = HashAndExtend (\r
750 NewEventHdr->PCRIndex,\r
751 HashData,\r
752 (UINTN)HashDataLen,\r
753 &DigestList\r
754 );\r
755 if (!EFI_ERROR (Status)) {\r
756 if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
757 Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);\r
758 }\r
759 }\r
760\r
6f785cfc
JY
761 if (Status == EFI_DEVICE_ERROR) {\r
762 DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEvent - %r. Disable TPM.\n", Status));\r
763 mTcgDxeData.BsCap.TrEEPresentFlag = FALSE;\r
764 REPORT_STATUS_CODE (\r
765 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
766 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
767 );\r
768 }\r
769\r
c1d93242
JY
770 return Status;\r
771}\r
772\r
773/**\r
774 The EFI_TREE_PROTOCOL HashLogExtendEvent function call provides callers with\r
775 an opportunity to extend and optionally log events without requiring\r
776 knowledge of actual TPM commands. \r
777 The extend operation will occur even if this function cannot create an event\r
778 log entry (e.g. due to the event log being full). \r
779\r
780 @param[in] This Indicates the calling context\r
781 @param[in] Flags Bitmap providing additional information.\r
782 @param[in] DataToHash Physical address of the start of the data buffer to be hashed. \r
783 @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash.\r
784 @param[in] Event Pointer to data buffer containing information about the event.\r
785\r
786 @retval EFI_SUCCESS Operation completed successfully.\r
787 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
788 @retval EFI_VOLUME_FULL The extend operation occurred, but the event could not be written to one or more event logs.\r
789 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
790 @retval EFI_UNSUPPORTED The PE/COFF image type is not supported.\r
791**/\r
792EFI_STATUS\r
793EFIAPI\r
794TreeHashLogExtendEvent (\r
795 IN EFI_TREE_PROTOCOL *This,\r
796 IN UINT64 Flags,\r
797 IN EFI_PHYSICAL_ADDRESS DataToHash,\r
798 IN UINT64 DataToHashLen,\r
799 IN TrEE_EVENT *Event\r
800 )\r
801{\r
802 EFI_STATUS Status;\r
803 TCG_PCR_EVENT_HDR NewEventHdr;\r
804 TPML_DIGEST_VALUES DigestList;\r
805\r
33985e3b 806 DEBUG ((EFI_D_INFO, "TreeHashLogExtendEvent ...\n"));\r
c1d93242
JY
807\r
808 if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) {\r
809 return EFI_INVALID_PARAMETER;\r
810 }\r
811\r
812 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
813 return EFI_UNSUPPORTED;\r
814 }\r
815\r
816 if (Event->Size < Event->Header.HeaderSize + sizeof(UINT32)) {\r
817 return EFI_INVALID_PARAMETER;\r
818 }\r
819\r
820 if (Event->Header.PCRIndex > MAX_PCR_INDEX) {\r
821 return EFI_INVALID_PARAMETER;\r
822 }\r
823\r
824 NewEventHdr.PCRIndex = Event->Header.PCRIndex;\r
825 NewEventHdr.EventType = Event->Header.EventType;\r
826 NewEventHdr.EventSize = Event->Size - sizeof(UINT32) - Event->Header.HeaderSize;\r
827 if ((Flags & PE_COFF_IMAGE) != 0) {\r
828 Status = MeasurePeImageAndExtend (\r
829 NewEventHdr.PCRIndex,\r
830 DataToHash,\r
831 (UINTN)DataToHashLen,\r
832 &DigestList\r
833 );\r
834 if (!EFI_ERROR (Status)) {\r
835 if ((Flags & TREE_EXTEND_ONLY) == 0) {\r
836 Status = TcgDxeLogHashEvent (&DigestList, &NewEventHdr, Event->Event);\r
837 }\r
838 }\r
6f785cfc
JY
839 if (Status == EFI_DEVICE_ERROR) {\r
840 DEBUG ((EFI_D_ERROR, "MeasurePeImageAndExtend - %r. Disable TPM.\n", Status));\r
841 mTcgDxeData.BsCap.TrEEPresentFlag = FALSE;\r
842 REPORT_STATUS_CODE (\r
843 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
844 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
845 );\r
846 }\r
c1d93242
JY
847 } else {\r
848 Status = TcgDxeHashLogExtendEvent (\r
849 Flags,\r
850 (UINT8 *) (UINTN) DataToHash,\r
851 DataToHashLen,\r
852 &NewEventHdr,\r
853 Event->Event\r
854 );\r
855 }\r
33985e3b 856 DEBUG ((EFI_D_INFO, "TreeHashLogExtendEvent - %r\n", Status));\r
c1d93242
JY
857 return Status;\r
858}\r
859\r
860/**\r
861 This service enables the sending of commands to the TrEE.\r
862\r
863 @param[in] This Indicates the calling context\r
864 @param[in] InputParameterBlockSize Size of the TrEE input parameter block.\r
865 @param[in] InputParameterBlock Pointer to the TrEE input parameter block.\r
866 @param[in] OutputParameterBlockSize Size of the TrEE output parameter block.\r
867 @param[in] OutputParameterBlock Pointer to the TrEE output parameter block.\r
868\r
869 @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received.\r
870 @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device.\r
871 @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.\r
872 @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. \r
873**/\r
874EFI_STATUS\r
875EFIAPI\r
876TreeSubmitCommand (\r
877 IN EFI_TREE_PROTOCOL *This,\r
878 IN UINT32 InputParameterBlockSize,\r
879 IN UINT8 *InputParameterBlock,\r
880 IN UINT32 OutputParameterBlockSize,\r
881 IN UINT8 *OutputParameterBlock\r
882 )\r
883{\r
884 EFI_STATUS Status;\r
885\r
33985e3b 886 DEBUG ((EFI_D_INFO, "TreeSubmitCommand ...\n"));\r
c1d93242
JY
887\r
888 if ((This == NULL) ||\r
889 (InputParameterBlockSize == 0) || (InputParameterBlock == NULL) ||\r
890 (OutputParameterBlockSize == 0) || (OutputParameterBlock == NULL)) {\r
891 return EFI_INVALID_PARAMETER;\r
892 }\r
893\r
894 if (!mTcgDxeData.BsCap.TrEEPresentFlag) {\r
895 return EFI_UNSUPPORTED;\r
896 }\r
897\r
898 if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) {\r
899 return EFI_INVALID_PARAMETER;\r
900 }\r
901 if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) {\r
902 return EFI_INVALID_PARAMETER;\r
903 }\r
904\r
905 Status = Tpm2SubmitCommand (\r
906 InputParameterBlockSize,\r
907 InputParameterBlock,\r
908 &OutputParameterBlockSize,\r
909 OutputParameterBlock\r
910 );\r
33985e3b 911 DEBUG ((EFI_D_INFO, "TreeSubmitCommand - %r\n", Status));\r
c1d93242
JY
912 return Status;\r
913}\r
914\r
915\r
916EFI_TREE_PROTOCOL mTreeProtocol = {\r
917 TreeGetCapability,\r
918 TreeGetEventLog,\r
919 TreeHashLogExtendEvent,\r
920 TreeSubmitCommand\r
921};\r
922\r
923/**\r
924 Initialize the Event Log and log events passed from the PEI phase.\r
925\r
926 @retval EFI_SUCCESS Operation completed successfully.\r
927 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
928\r
929**/\r
930EFI_STATUS\r
931SetupEventLog (\r
932 VOID\r
933 )\r
934{\r
935 EFI_STATUS Status;\r
936 VOID *TcgEvent;\r
937 EFI_PEI_HOB_POINTERS GuidHob;\r
938 EFI_PHYSICAL_ADDRESS Lasa;\r
939 UINTN Index;\r
940\r
941 DEBUG ((EFI_D_INFO, "SetupEventLog\n"));\r
942\r
943 //\r
944 // 1. Create Log Area\r
945 //\r
946 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
947 mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTreeEventInfo[Index].LogFormat;\r
948 Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1);\r
949 Status = gBS->AllocatePages (\r
950 AllocateMaxAddress,\r
951 EfiACPIMemoryNVS,\r
952 EFI_SIZE_TO_PAGES (EFI_TCG_LOG_AREA_SIZE),\r
953 &Lasa\r
954 );\r
955 if (EFI_ERROR (Status)) {\r
956 return Status;\r
957 }\r
958 mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa;\r
959 mTcgDxeData.EventLogAreaStruct[Index].Laml = EFI_TCG_LOG_AREA_SIZE;\r
960 //\r
961 // To initialize them as 0xFF is recommended \r
962 // because the OS can know the last entry for that.\r
963 //\r
964 SetMem ((VOID *)(UINTN)Lasa, EFI_TCG_LOG_AREA_SIZE, 0xFF);\r
965 }\r
966\r
967 //\r
968 // 2. Create ACPI table for TCG1.2 only\r
969 //\r
970 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
971 mTcgClientAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
972 mTcgClientAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;\r
973 } else {\r
974 mTcgServerAcpiTemplate.Lasa = mTcgDxeData.EventLogAreaStruct[0].Lasa;\r
975 mTcgServerAcpiTemplate.Laml = EFI_TCG_LOG_AREA_SIZE;\r
976 }\r
977\r
978 //\r
979 // 3. Sync data from PEI to DXE\r
980 //\r
981 Status = EFI_SUCCESS;\r
982 for (Index = 0; Index < sizeof(mTreeEventInfo)/sizeof(mTreeEventInfo[0]); Index++) {\r
983 GuidHob.Raw = GetHobList ();\r
984 Status = EFI_SUCCESS;\r
985 while (!EFI_ERROR (Status) && \r
986 (GuidHob.Raw = GetNextGuidHob (mTreeEventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) {\r
987 TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);\r
988 GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
989 switch (mTreeEventInfo[Index].LogFormat) {\r
990 case TREE_EVENT_LOG_FORMAT_TCG_1_2:\r
991 Status = TcgDxeLogEvent (\r
992 mTreeEventInfo[Index].LogFormat,\r
993 TcgEvent,\r
994 sizeof(TCG_PCR_EVENT_HDR),\r
995 ((TCG_PCR_EVENT*)TcgEvent)->Event,\r
996 ((TCG_PCR_EVENT_HDR*)TcgEvent)->EventSize\r
997 );\r
998 break;\r
999 }\r
1000 }\r
1001 }\r
1002\r
1003 return Status;\r
1004}\r
1005\r
1006/**\r
1007 Measure and log an action string, and extend the measurement result into PCR[5].\r
1008\r
1009 @param[in] String A specific string that indicates an Action event. \r
1010 \r
1011 @retval EFI_SUCCESS Operation completed successfully.\r
1012 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1013\r
1014**/\r
1015EFI_STATUS\r
1016TcgMeasureAction (\r
1017 IN CHAR8 *String\r
1018 )\r
1019{\r
1020 TCG_PCR_EVENT_HDR TcgEvent;\r
1021\r
1022 TcgEvent.PCRIndex = 5;\r
1023 TcgEvent.EventType = EV_EFI_ACTION;\r
1024 TcgEvent.EventSize = (UINT32)AsciiStrLen (String);\r
1025 return TcgDxeHashLogExtendEvent (\r
1026 0,\r
1027 (UINT8*)String,\r
1028 TcgEvent.EventSize,\r
1029 &TcgEvent,\r
1030 (UINT8 *) String\r
1031 );\r
1032}\r
1033\r
1034/**\r
1035 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
1036\r
1037 @retval EFI_SUCCESS Operation completed successfully.\r
1038 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1039\r
1040**/\r
1041EFI_STATUS\r
1042MeasureHandoffTables (\r
1043 VOID\r
1044 )\r
1045{\r
1046 EFI_STATUS Status;\r
c1d93242
JY
1047 TCG_PCR_EVENT_HDR TcgEvent;\r
1048 EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
1049 UINTN ProcessorNum;\r
1050 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
1051\r
d4193108 1052 ProcessorLocBuf = NULL;\r
d2de4483 1053 Status = EFI_SUCCESS;\r
c1d93242
JY
1054\r
1055 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
1056 //\r
1057 // Tcg Server spec. \r
1058 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
1059 //\r
1060 Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);\r
1061\r
1062 if (!EFI_ERROR(Status)){\r
1063 TcgEvent.PCRIndex = 1;\r
1064 TcgEvent.EventType = EV_TABLE_OF_DEVICES;\r
1065 TcgEvent.EventSize = sizeof (HandoffTables);\r
1066\r
1067 HandoffTables.NumberOfTables = 1;\r
1068 HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
1069 HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
1070\r
1071 Status = TcgDxeHashLogExtendEvent (\r
1072 0,\r
1073 (UINT8*)(UINTN)ProcessorLocBuf,\r
1074 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
1075 &TcgEvent,\r
1076 (UINT8*)&HandoffTables\r
1077 );\r
1078\r
1079 FreePool(ProcessorLocBuf);\r
1080 }\r
1081 }\r
1082\r
1083 return Status;\r
1084}\r
1085\r
1086/**\r
1087 Measure and log Separator event, and extend the measurement result into a specific PCR.\r
1088\r
1089 @param[in] PCRIndex PCR index. \r
1090\r
1091 @retval EFI_SUCCESS Operation completed successfully.\r
1092 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1093\r
1094**/\r
1095EFI_STATUS\r
1096MeasureSeparatorEvent (\r
1097 IN TPM_PCRINDEX PCRIndex\r
1098 )\r
1099{\r
1100 TCG_PCR_EVENT_HDR TcgEvent;\r
1101 UINT32 EventData;\r
1102\r
33985e3b 1103 DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent Pcr - %x\n", PCRIndex));\r
c1d93242
JY
1104\r
1105 EventData = 0;\r
1106 TcgEvent.PCRIndex = PCRIndex;\r
1107 TcgEvent.EventType = EV_SEPARATOR;\r
1108 TcgEvent.EventSize = (UINT32)sizeof (EventData);\r
1109 return TcgDxeHashLogExtendEvent (\r
1110 0,\r
1111 (UINT8 *)&EventData,\r
1112 sizeof (EventData),\r
1113 &TcgEvent,\r
1114 (UINT8 *)&EventData\r
1115 );\r
1116}\r
1117\r
1118/**\r
1119 Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
1120\r
1121 @param[in] PCRIndex PCR Index. \r
1122 @param[in] EventType Event type. \r
1123 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1124 @param[in] VendorGuid A unique identifier for the vendor.\r
1125 @param[in] VarData The content of the variable data. \r
1126 @param[in] VarSize The size of the variable data. \r
1127 \r
1128 @retval EFI_SUCCESS Operation completed successfully.\r
1129 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1130 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1131\r
1132**/\r
1133EFI_STATUS\r
1134MeasureVariable (\r
1135 IN TPM_PCRINDEX PCRIndex,\r
1136 IN TCG_EVENTTYPE EventType,\r
1137 IN CHAR16 *VarName,\r
1138 IN EFI_GUID *VendorGuid,\r
1139 IN VOID *VarData,\r
1140 IN UINTN VarSize\r
1141 )\r
1142{\r
1143 EFI_STATUS Status;\r
1144 TCG_PCR_EVENT_HDR TcgEvent;\r
1145 UINTN VarNameLength;\r
1146 EFI_VARIABLE_DATA_TREE *VarLog;\r
1147\r
33985e3b
CZ
1148 DEBUG ((EFI_D_INFO, "TrEEDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType));\r
1149 DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
c1d93242
JY
1150\r
1151 VarNameLength = StrLen (VarName);\r
1152 TcgEvent.PCRIndex = PCRIndex;\r
1153 TcgEvent.EventType = EventType;\r
1154 TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
1155 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
1156\r
1157 VarLog = (EFI_VARIABLE_DATA_TREE*)AllocatePool (TcgEvent.EventSize);\r
1158 if (VarLog == NULL) {\r
1159 return EFI_OUT_OF_RESOURCES;\r
1160 }\r
1161\r
1162 VarLog->VariableName = *VendorGuid;\r
1163 VarLog->UnicodeNameLength = VarNameLength;\r
1164 VarLog->VariableDataLength = VarSize;\r
1165 CopyMem (\r
1166 VarLog->UnicodeName,\r
1167 VarName,\r
1168 VarNameLength * sizeof (*VarName)\r
1169 );\r
61959fa9 1170 if (VarSize != 0 && VarData != NULL) {\r
c1d93242
JY
1171 CopyMem (\r
1172 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
1173 VarData,\r
1174 VarSize\r
1175 );\r
1176 }\r
1177\r
36811012
CZ
1178 Status = TcgDxeHashLogExtendEvent (\r
1179 0,\r
1180 (UINT8*)VarLog,\r
1181 TcgEvent.EventSize,\r
1182 &TcgEvent,\r
1183 (UINT8*)VarLog\r
1184 );\r
1185\r
c1d93242
JY
1186 FreePool (VarLog);\r
1187 return Status;\r
1188}\r
1189\r
1190/**\r
1191 Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
1192\r
1193 @param[in] PCRIndex PCR Index. \r
1194 @param[in] EventType Event type. \r
1195 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1196 @param[in] VendorGuid A unique identifier for the vendor.\r
1197 @param[out] VarSize The size of the variable data. \r
1198 @param[out] VarData Pointer to the content of the variable. \r
1199 \r
1200 @retval EFI_SUCCESS Operation completed successfully.\r
1201 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1202 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1203\r
1204**/\r
1205EFI_STATUS\r
1206ReadAndMeasureVariable (\r
1207 IN TPM_PCRINDEX PCRIndex,\r
1208 IN TCG_EVENTTYPE EventType,\r
1209 IN CHAR16 *VarName,\r
1210 IN EFI_GUID *VendorGuid,\r
1211 OUT UINTN *VarSize,\r
1212 OUT VOID **VarData\r
1213 )\r
1214{\r
1215 EFI_STATUS Status;\r
1216\r
1217 Status = GetVariable2 (VarName, VendorGuid, VarData, VarSize);\r
1218 if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {\r
1219 if (EFI_ERROR (Status)) {\r
1220 //\r
1221 // It is valid case, so we need handle it.\r
1222 //\r
1223 *VarData = NULL;\r
1224 *VarSize = 0;\r
1225 }\r
1226 } else {\r
f7fe68db
CZ
1227 //\r
1228 // if status error, VarData is freed and set NULL by GetVariable2\r
1229 //\r
c1d93242 1230 if (EFI_ERROR (Status)) {\r
f7fe68db 1231 return EFI_NOT_FOUND;\r
c1d93242 1232 }\r
c1d93242
JY
1233 }\r
1234\r
1235 Status = MeasureVariable (\r
1236 PCRIndex,\r
1237 EventType,\r
1238 VarName,\r
1239 VendorGuid,\r
1240 *VarData,\r
1241 *VarSize\r
1242 );\r
1243 return Status;\r
1244}\r
1245\r
1246/**\r
1247 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].\r
1248\r
1249 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1250 @param[in] VendorGuid A unique identifier for the vendor.\r
1251 @param[out] VarSize The size of the variable data. \r
1252 @param[out] VarData Pointer to the content of the variable. \r
1253 \r
1254 @retval EFI_SUCCESS Operation completed successfully.\r
1255 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1256 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1257\r
1258**/\r
1259EFI_STATUS\r
1260ReadAndMeasureBootVariable (\r
1261 IN CHAR16 *VarName,\r
1262 IN EFI_GUID *VendorGuid,\r
1263 OUT UINTN *VarSize,\r
1264 OUT VOID **VarData\r
1265 )\r
1266{\r
1267 return ReadAndMeasureVariable (\r
1268 5,\r
1269 EV_EFI_VARIABLE_BOOT,\r
1270 VarName,\r
1271 VendorGuid,\r
1272 VarSize,\r
1273 VarData\r
1274 );\r
1275}\r
1276\r
1277/**\r
1278 Read then Measure and log an EFI Secure variable, and extend the measurement result into PCR[7].\r
1279\r
1280 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1281 @param[in] VendorGuid A unique identifier for the vendor.\r
1282 @param[out] VarSize The size of the variable data. \r
1283 @param[out] VarData Pointer to the content of the variable. \r
1284 \r
1285 @retval EFI_SUCCESS Operation completed successfully.\r
1286 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1287 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1288\r
1289**/\r
1290EFI_STATUS\r
1291ReadAndMeasureSecureVariable (\r
1292 IN CHAR16 *VarName,\r
1293 IN EFI_GUID *VendorGuid,\r
1294 OUT UINTN *VarSize,\r
1295 OUT VOID **VarData\r
1296 )\r
1297{\r
1298 return ReadAndMeasureVariable (\r
1299 7,\r
1300 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
1301 VarName,\r
1302 VendorGuid,\r
1303 VarSize,\r
1304 VarData\r
1305 );\r
1306}\r
1307\r
1308/**\r
1309 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
1310\r
1311 The EFI boot variables are BootOrder and Boot#### variables.\r
1312\r
1313 @retval EFI_SUCCESS Operation completed successfully.\r
1314 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1315 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1316\r
1317**/\r
1318EFI_STATUS\r
1319MeasureAllBootVariables (\r
1320 VOID\r
1321 )\r
1322{\r
1323 EFI_STATUS Status;\r
1324 UINT16 *BootOrder;\r
1325 UINTN BootCount;\r
1326 UINTN Index;\r
1327 VOID *BootVarData;\r
1328 UINTN Size;\r
1329\r
1330 Status = ReadAndMeasureBootVariable (\r
1331 mBootVarName,\r
1332 &gEfiGlobalVariableGuid,\r
1333 &BootCount,\r
1334 (VOID **) &BootOrder\r
1335 );\r
61959fa9 1336 if (Status == EFI_NOT_FOUND || BootOrder == NULL) {\r
c1d93242
JY
1337 return EFI_SUCCESS;\r
1338 }\r
c1d93242
JY
1339\r
1340 if (EFI_ERROR (Status)) {\r
f7fe68db
CZ
1341 //\r
1342 // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
1343 //\r
c1d93242
JY
1344 FreePool (BootOrder);\r
1345 return Status;\r
1346 }\r
1347\r
1348 BootCount /= sizeof (*BootOrder);\r
1349 for (Index = 0; Index < BootCount; Index++) {\r
1350 UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
1351 Status = ReadAndMeasureBootVariable (\r
1352 mBootVarName,\r
1353 &gEfiGlobalVariableGuid,\r
1354 &Size,\r
1355 &BootVarData\r
1356 );\r
1357 if (!EFI_ERROR (Status)) {\r
1358 FreePool (BootVarData);\r
1359 }\r
1360 }\r
1361\r
1362 FreePool (BootOrder);\r
1363 return EFI_SUCCESS;\r
1364}\r
1365\r
1366/**\r
1367 Measure and log all EFI Secure variables, and extend the measurement result into a specific PCR.\r
1368\r
1369 The EFI boot variables are BootOrder and Boot#### variables.\r
1370\r
1371 @retval EFI_SUCCESS Operation completed successfully.\r
1372 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1373 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1374\r
1375**/\r
1376EFI_STATUS\r
1377MeasureAllSecureVariables (\r
1378 VOID\r
1379 )\r
1380{\r
1381 EFI_STATUS Status;\r
1382 VOID *Data;\r
1383 UINTN DataSize;\r
1384 UINTN Index;\r
1385\r
1386 Status = EFI_NOT_FOUND;\r
1387 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
1388 Status = ReadAndMeasureSecureVariable (\r
1389 mVariableType[Index].VariableName,\r
1390 mVariableType[Index].VendorGuid,\r
1391 &DataSize,\r
1392 &Data\r
1393 );\r
1394 if (!EFI_ERROR (Status)) {\r
1395 if (Data != NULL) {\r
1396 FreePool (Data);\r
1397 }\r
1398 }\r
1399 }\r
1400\r
1401 return EFI_SUCCESS;\r
1402}\r
1403\r
1404/**\r
1405 Measure and log launch of FirmwareDebugger, and extend the measurement result into a specific PCR.\r
1406\r
1407 @retval EFI_SUCCESS Operation completed successfully.\r
1408 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1409 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1410\r
1411**/\r
1412EFI_STATUS\r
1413MeasureLaunchOfFirmwareDebugger (\r
1414 VOID\r
1415 )\r
1416{\r
1417 TCG_PCR_EVENT_HDR TcgEvent;\r
1418\r
1419 TcgEvent.PCRIndex = 7;\r
1420 TcgEvent.EventType = EV_EFI_ACTION;\r
1421 TcgEvent.EventSize = sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1;\r
1422 return TcgDxeHashLogExtendEvent (\r
1423 0,\r
1424 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING,\r
1425 sizeof(FIRMWARE_DEBUGGER_EVENT_STRING) - 1,\r
1426 &TcgEvent,\r
1427 (UINT8 *)FIRMWARE_DEBUGGER_EVENT_STRING\r
1428 );\r
1429}\r
1430\r
1431/**\r
1432 Measure and log all Secure Boot Policy, and extend the measurement result into a specific PCR.\r
1433\r
1434 Platform firmware adhering to the policy must therefore measure the following values into PCR[7]: (in order listed)\r
1435 - The contents of the SecureBoot variable\r
1436 - The contents of the PK variable\r
1437 - The contents of the KEK variable\r
1438 - The contents of the EFI_IMAGE_SECURITY_DATABASE variable\r
1439 - The contents of the EFI_IMAGE_SECURITY_DATABASE1 variable\r
1440 - Separator\r
1441 - Entries in the EFI_IMAGE_SECURITY_DATABASE that are used to validate EFI Drivers or EFI Boot Applications in the boot path\r
1442\r
1443 NOTE: Because of the above, UEFI variables PK, KEK, EFI_IMAGE_SECURITY_DATABASE,\r
1444 EFI_IMAGE_SECURITY_DATABASE1 and SecureBoot SHALL NOT be measured into PCR[3].\r
1445\r
1446 @param[in] Event Event whose notification function is being invoked\r
1447 @param[in] Context Pointer to the notification function's context\r
1448**/\r
1449VOID\r
1450EFIAPI\r
1451MeasureSecureBootPolicy (\r
1452 IN EFI_EVENT Event,\r
1453 IN VOID *Context\r
1454 )\r
1455{\r
1456 EFI_STATUS Status;\r
1457 VOID *Protocol;\r
1458\r
1459 Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol);\r
1460 if (EFI_ERROR (Status)) {\r
1461 return;\r
1462 }\r
1463\r
1464 if (PcdGetBool (PcdFirmwareDebuggerInitialized)) {\r
1465 Status = MeasureLaunchOfFirmwareDebugger ();\r
33985e3b 1466 DEBUG ((EFI_D_INFO, "MeasureLaunchOfFirmwareDebugger - %r\n", Status));\r
c1d93242
JY
1467 }\r
1468\r
1469 Status = MeasureAllSecureVariables ();\r
33985e3b 1470 DEBUG ((EFI_D_INFO, "MeasureAllSecureVariables - %r\n", Status));\r
c1d93242
JY
1471\r
1472 //\r
1473 // We need measure Separator(7) here, because this event must be between SecureBootPolicy (Configure)\r
1474 // and ImageVerification (Authority)\r
1475 // There might be a case that we need measure UEFI image from DriverOrder, besides BootOrder. So\r
1476 // the Authority measurement happen before ReadToBoot event.\r
1477 //\r
1478 Status = MeasureSeparatorEvent (7);\r
33985e3b 1479 DEBUG ((EFI_D_INFO, "MeasureSeparatorEvent - %r\n", Status));\r
c1d93242
JY
1480 return ;\r
1481}\r
1482\r
1483/**\r
1484 Ready to Boot Event notification handler.\r
1485\r
1486 Sequence of OS boot events is measured in this event notification handler.\r
1487\r
1488 @param[in] Event Event whose notification function is being invoked\r
1489 @param[in] Context Pointer to the notification function's context\r
1490\r
1491**/\r
1492VOID\r
1493EFIAPI\r
1494OnReadyToBoot (\r
1495 IN EFI_EVENT Event,\r
1496 IN VOID *Context\r
1497 )\r
1498{\r
1499 EFI_STATUS Status;\r
1500 TPM_PCRINDEX PcrIndex;\r
1501\r
1502 PERF_START_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE);\r
1503 if (mBootAttempts == 0) {\r
1504\r
1505 //\r
1506 // Measure handoff tables.\r
1507 //\r
1508 Status = MeasureHandoffTables ();\r
1509 if (EFI_ERROR (Status)) {\r
1510 DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));\r
1511 }\r
1512\r
1513 //\r
1514 // Measure BootOrder & Boot#### variables.\r
1515 //\r
1516 Status = MeasureAllBootVariables ();\r
1517 if (EFI_ERROR (Status)) {\r
1518 DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));\r
1519 }\r
1520\r
1521 //\r
1522 // 1. This is the first boot attempt.\r
1523 //\r
1524 Status = TcgMeasureAction (\r
1525 EFI_CALLING_EFI_APPLICATION\r
1526 );\r
6f785cfc
JY
1527 if (EFI_ERROR (Status)) {\r
1528 DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
1529 }\r
c1d93242
JY
1530\r
1531 //\r
1532 // 2. Draw a line between pre-boot env and entering post-boot env.\r
1533 // PCR[7] is already done.\r
1534 //\r
1535 for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) {\r
1536 Status = MeasureSeparatorEvent (PcrIndex);\r
6f785cfc
JY
1537 if (EFI_ERROR (Status)) {\r
1538 DEBUG ((EFI_D_ERROR, "Seperator Event not Measured. Error!\n"));\r
1539 }\r
c1d93242
JY
1540 }\r
1541\r
1542 //\r
1543 // 3. Measure GPT. It would be done in SAP driver.\r
1544 //\r
1545\r
1546 //\r
1547 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
1548 //\r
1549\r
1550 //\r
1551 // 5. Read & Measure variable. BootOrder already measured.\r
1552 //\r
1553 } else {\r
1554 //\r
1555 // 6. Not first attempt, meaning a return from last attempt\r
1556 //\r
1557 Status = TcgMeasureAction (\r
1558 EFI_RETURNING_FROM_EFI_APPLICATOIN\r
1559 );\r
6f785cfc
JY
1560 if (EFI_ERROR (Status)) {\r
1561 DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN));\r
1562 }\r
c1d93242
JY
1563 }\r
1564\r
1565 DEBUG ((EFI_D_INFO, "TPM2 TrEEDxe Measure Data when ReadyToBoot\n"));\r
1566 //\r
1567 // Increase boot attempt counter.\r
1568 //\r
1569 mBootAttempts++;\r
1570 PERF_END_EX (mImageHandle, "EventRec", "TrEEDxe", 0, PERF_ID_TREE_DXE + 1);\r
1571}\r
1572\r
1573/**\r
1574 Install TCG ACPI Table when ACPI Table Protocol is available.\r
1575\r
1576 A system's firmware uses an ACPI table to identify the system's TCG capabilities \r
1577 to the Post-Boot environment. The information in this ACPI table is not guaranteed \r
1578 to be valid until the Host Platform transitions from pre-boot state to post-boot state. \r
1579\r
1580 @param[in] Event Event whose notification function is being invoked\r
1581 @param[in] Context Pointer to the notification function's context\r
1582**/\r
1583VOID\r
1584EFIAPI\r
1585InstallAcpiTable (\r
1586 IN EFI_EVENT Event,\r
1587 IN VOID *Context\r
1588 )\r
1589{\r
1590 UINTN TableKey;\r
1591 EFI_STATUS Status;\r
1592 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
1593 UINT8 Checksum;\r
1594 UINT64 OemTableId;\r
1595\r
1596 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
1597 if (EFI_ERROR (Status)) {\r
1598 return;\r
1599 }\r
1600\r
1601 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
1602 CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));\r
1603 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1604 CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1605 mTcgClientAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1606 mTcgClientAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1607 mTcgClientAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
1608 //\r
1609 // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
1610 // service of the ACPI table protocol to install it.\r
1611 //\r
1612 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));\r
1613 mTcgClientAcpiTemplate.Header.Checksum = Checksum;\r
1614\r
1615 Status = AcpiTable->InstallAcpiTable (\r
1616 AcpiTable,\r
1617 &mTcgClientAcpiTemplate,\r
1618 sizeof (mTcgClientAcpiTemplate),\r
1619 &TableKey\r
1620 );\r
1621 } else {\r
1622 CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));\r
1623 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1624 CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1625 mTcgServerAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1626 mTcgServerAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1627 mTcgServerAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
1628 //\r
1629 // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
1630 // service of the ACPI table protocol to install it.\r
1631 //\r
1632 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));\r
1633 mTcgServerAcpiTemplate.Header.Checksum = Checksum;\r
1634\r
1635 mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);\r
1636 Status = AcpiTable->InstallAcpiTable (\r
1637 AcpiTable,\r
1638 &mTcgServerAcpiTemplate,\r
1639 sizeof (mTcgServerAcpiTemplate),\r
1640 &TableKey\r
1641 );\r
1642 }\r
f7fe68db
CZ
1643\r
1644 if (EFI_ERROR (Status)) {\r
1645 DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure"));\r
1646 }\r
c1d93242
JY
1647}\r
1648\r
1649/**\r
1650 Exit Boot Services Event notification handler.\r
1651\r
1652 Measure invocation and success of ExitBootServices.\r
1653\r
1654 @param[in] Event Event whose notification function is being invoked\r
1655 @param[in] Context Pointer to the notification function's context\r
1656\r
1657**/\r
1658VOID\r
1659EFIAPI\r
1660OnExitBootServices (\r
1661 IN EFI_EVENT Event,\r
1662 IN VOID *Context\r
1663 )\r
1664{\r
1665 EFI_STATUS Status;\r
1666\r
1667 //\r
1668 // Measure invocation of ExitBootServices,\r
1669 //\r
1670 Status = TcgMeasureAction (\r
1671 EFI_EXIT_BOOT_SERVICES_INVOCATION\r
1672 );\r
f7fe68db
CZ
1673 if (EFI_ERROR (Status)) {\r
1674 DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
1675 }\r
c1d93242
JY
1676\r
1677 //\r
1678 // Measure success of ExitBootServices\r
1679 //\r
1680 Status = TcgMeasureAction (\r
1681 EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
1682 );\r
f7fe68db
CZ
1683 if (EFI_ERROR (Status)) {\r
1684 DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
1685 }\r
c1d93242
JY
1686}\r
1687\r
1688/**\r
1689 Exit Boot Services Failed Event notification handler.\r
1690\r
1691 Measure Failure of ExitBootServices.\r
1692\r
1693 @param[in] Event Event whose notification function is being invoked\r
1694 @param[in] Context Pointer to the notification function's context\r
1695\r
1696**/\r
1697VOID\r
1698EFIAPI\r
1699OnExitBootServicesFailed (\r
1700 IN EFI_EVENT Event,\r
1701 IN VOID *Context\r
1702 )\r
1703{\r
1704 EFI_STATUS Status;\r
1705\r
1706 //\r
1707 // Measure Failure of ExitBootServices,\r
1708 //\r
1709 Status = TcgMeasureAction (\r
1710 EFI_EXIT_BOOT_SERVICES_FAILED\r
1711 );\r
f7fe68db
CZ
1712 if (EFI_ERROR (Status)) {\r
1713 DEBUG ((EFI_D_ERROR, "%s not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
1714 }\r
c1d93242
JY
1715\r
1716}\r
1717\r
1718/**\r
1719 The function install TrEE protocol.\r
1720 \r
1721 @retval EFI_SUCCESS TrEE protocol is installed.\r
1722 @retval other Some error occurs.\r
1723**/\r
1724EFI_STATUS\r
1725InstallTrEE (\r
1726 VOID\r
1727 )\r
1728{\r
1729 EFI_STATUS Status;\r
1730 EFI_HANDLE Handle;\r
1731\r
1732 Handle = NULL;\r
1733 Status = gBS->InstallMultipleProtocolInterfaces (\r
1734 &Handle,\r
1735 &gEfiTrEEProtocolGuid,\r
1736 &mTreeProtocol,\r
1737 NULL\r
1738 );\r
1739 return Status;\r
1740}\r
1741\r
1742/**\r
1743 The driver's entry point. It publishes EFI TrEE Protocol.\r
1744\r
1745 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
1746 @param[in] SystemTable A pointer to the EFI System Table.\r
1747 \r
1748 @retval EFI_SUCCESS The entry point is executed successfully.\r
1749 @retval other Some error occurs when executing this entry point.\r
1750**/\r
1751EFI_STATUS\r
1752EFIAPI\r
1753DriverEntry (\r
1754 IN EFI_HANDLE ImageHandle,\r
1755 IN EFI_SYSTEM_TABLE *SystemTable\r
1756 )\r
1757{\r
1758 EFI_STATUS Status;\r
1759 EFI_EVENT Event;\r
1760 VOID *Registration;\r
1761 UINT32 MaxCommandSize;\r
1762 UINT32 MaxResponseSize;\r
1763 TPML_PCR_SELECTION Pcrs;\r
1764 UINTN Index;\r
1765 UINT32 TpmHashAlgorithmBitmap;\r
1766\r
1767 mImageHandle = ImageHandle;\r
1768\r
1769 if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) ||\r
1770 CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
1771 DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n"));\r
1772 return EFI_UNSUPPORTED;\r
1773 }\r
1774\r
3dd05ac3
JY
1775 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
1776 DEBUG ((EFI_D_ERROR, "TPM2 error!\n"));\r
1777 return EFI_DEVICE_ERROR;\r
1778 }\r
1779 \r
c1d93242
JY
1780 Status = Tpm2RequestUseTpm ();\r
1781 if (EFI_ERROR (Status)) {\r
3dd05ac3 1782 DEBUG ((EFI_D_ERROR, "TPM2 not detected!\n"));\r
c1d93242
JY
1783 return Status;\r
1784 }\r
6f785cfc 1785 \r
c1d93242
JY
1786 //\r
1787 // Fill information\r
1788 //\r
33985e3b
CZ
1789 DEBUG ((EFI_D_INFO, "TrEE.ProtocolVersion - %02x.%02x\n", mTcgDxeData.BsCap.ProtocolVersion.Major, mTcgDxeData.BsCap.ProtocolVersion.Minor));\r
1790 DEBUG ((EFI_D_INFO, "TrEE.StructureVersion - %02x.%02x\n", mTcgDxeData.BsCap.StructureVersion.Major, mTcgDxeData.BsCap.StructureVersion.Minor));\r
c1d93242
JY
1791\r
1792 Status = Tpm2GetCapabilityManufactureID (&mTcgDxeData.BsCap.ManufacturerID);\r
1793 if (EFI_ERROR (Status)) {\r
1794 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityManufactureID fail!\n"));\r
1795 } else {\r
33985e3b 1796 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityManufactureID - %08x\n", mTcgDxeData.BsCap.ManufacturerID));\r
c1d93242
JY
1797 }\r
1798\r
1799 DEBUG_CODE (\r
1800 UINT32 FirmwareVersion1;\r
1801 UINT32 FirmwareVersion2;\r
1802\r
1803 Status = Tpm2GetCapabilityFirmwareVersion (&FirmwareVersion1, &FirmwareVersion2);\r
1804 if (EFI_ERROR (Status)) {\r
1805 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityFirmwareVersion fail!\n"));\r
1806 } else {\r
33985e3b 1807 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityFirmwareVersion - %08x %08x\n", FirmwareVersion1, FirmwareVersion2));\r
c1d93242
JY
1808 }\r
1809 );\r
1810\r
1811 Status = Tpm2GetCapabilityMaxCommandResponseSize (&MaxCommandSize, &MaxResponseSize);\r
1812 if (EFI_ERROR (Status)) {\r
1813 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityMaxCommandResponseSize fail!\n"));\r
1814 } else {\r
1815 mTcgDxeData.BsCap.MaxCommandSize = (UINT16)MaxCommandSize;\r
1816 mTcgDxeData.BsCap.MaxResponseSize = (UINT16)MaxResponseSize;\r
33985e3b 1817 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityMaxCommandResponseSize - %08x, %08x\n", MaxCommandSize, MaxResponseSize));\r
c1d93242
JY
1818 }\r
1819\r
1820 Status = Tpm2GetCapabilityPcrs (&Pcrs);\r
1821 if (EFI_ERROR (Status)) {\r
1822 DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));\r
1823 TpmHashAlgorithmBitmap = TREE_BOOT_HASH_ALG_SHA1;\r
1824 } else {\r
33985e3b 1825 DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));\r
c1d93242
JY
1826 TpmHashAlgorithmBitmap = 0;\r
1827 for (Index = 0; Index < Pcrs.count; Index++) {\r
33985e3b 1828 DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash));\r
c1d93242
JY
1829 switch (Pcrs.pcrSelections[Index].hash) {\r
1830 case TPM_ALG_SHA1:\r
1831 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA1;\r
1832 break;\r
1833 case TPM_ALG_SHA256:\r
1834 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA256;\r
1835 break;\r
1836 case TPM_ALG_SHA384:\r
1837 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA384;\r
1838 break;\r
1839 case TPM_ALG_SHA512:\r
1840 TpmHashAlgorithmBitmap |= TREE_BOOT_HASH_ALG_SHA512;\r
1841 break;\r
1842 case TPM_ALG_SM3_256:\r
1843 // TBD: Spec not define TREE_BOOT_HASH_ALG_SM3_256 yet\r
1844 break;\r
1845 }\r
1846 }\r
1847 }\r
33985e3b 1848 DEBUG ((EFI_D_INFO, "TPM.HashAlgorithmBitmap - 0x%08x\n", TpmHashAlgorithmBitmap));\r
c1d93242 1849\r
33985e3b 1850 DEBUG ((EFI_D_INFO, "TrEE.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs));\r
c1d93242 1851 mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap;\r
33985e3b 1852 DEBUG ((EFI_D_INFO, "TrEE.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap));\r
c1d93242
JY
1853\r
1854 if (mTcgDxeData.BsCap.TrEEPresentFlag) {\r
1855 //\r
1856 // Setup the log area and copy event log from hob list to it\r
1857 //\r
1858 Status = SetupEventLog ();\r
1859 ASSERT_EFI_ERROR (Status);\r
1860\r
1861 //\r
1862 // Measure handoff tables, Boot#### variables etc.\r
1863 //\r
1864 Status = EfiCreateEventReadyToBootEx (\r
1865 TPL_CALLBACK,\r
1866 OnReadyToBoot,\r
1867 NULL,\r
1868 &Event\r
1869 );\r
1870\r
1871 Status = gBS->CreateEventEx (\r
1872 EVT_NOTIFY_SIGNAL,\r
1873 TPL_NOTIFY,\r
1874 OnExitBootServices,\r
1875 NULL,\r
1876 &gEfiEventExitBootServicesGuid,\r
1877 &Event\r
1878 );\r
1879\r
1880 //\r
1881 // Measure Exit Boot Service failed \r
1882 //\r
1883 Status = gBS->CreateEventEx (\r
1884 EVT_NOTIFY_SIGNAL,\r
1885 TPL_NOTIFY,\r
1886 OnExitBootServicesFailed,\r
1887 NULL,\r
1888 &gEventExitBootServicesFailedGuid,\r
1889 &Event\r
1890 );\r
1891\r
1892 //\r
1893 // Create event callback, because we need access variable on SecureBootPolicyVariable\r
1894 // We should use VariableWriteArch instead of VariableArch, because Variable driver\r
1895 // may update SecureBoot value based on last setting.\r
1896 //\r
1897 EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration);\r
1898 }\r
1899\r
1900 //\r
1901 // Install ACPI Table\r
1902 //\r
1903 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
1904\r
1905 //\r
1906 // Install TrEEProtocol\r
1907 //\r
1908 Status = InstallTrEE ();\r
33985e3b 1909 DEBUG ((EFI_D_INFO, "InstallTrEE - %r\n", Status));\r
c1d93242
JY
1910\r
1911 return Status;\r
1912}\r