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