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