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