]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgDxe/TcgDxe.c
SecurityPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / SecurityPkg / Tcg / TcgDxe / TcgDxe.c
CommitLineData
b3548d32 1/** @file\r
0c18794e 2 This module implements TCG EFI Protocol.\r
b3548d32 3\r
be02dcee 4Caution: This module requires additional review when modified.\r
5This driver will have external input - TcgDxePassThroughToTpm\r
6This external input must be validated carefully to avoid security issue like\r
7buffer overflow, integer overflow.\r
8\r
9TcgDxePassThroughToTpm() will receive untrusted input and do basic validation.\r
10\r
b3548d32 11Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
730f8071 12(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
289b714b 13SPDX-License-Identifier: BSD-2-Clause-Patent\r
0c18794e 14\r
15**/\r
16\r
17#include <PiDxe.h>\r
18#include <IndustryStandard/Tpm12.h>\r
19#include <IndustryStandard/Acpi.h>\r
20#include <IndustryStandard/PeImage.h>\r
c1d93242 21#include <IndustryStandard/TcpaAcpi.h>\r
0c18794e 22\r
23#include <Guid/GlobalVariable.h>\r
0c18794e 24#include <Guid/HobList.h>\r
25#include <Guid/TcgEventHob.h>\r
26#include <Guid/EventGroup.h>\r
9e945f78 27#include <Guid/EventExitBootServiceFailed.h>\r
c1d93242
JY
28#include <Guid/TpmInstance.h>\r
29\r
0c18794e 30#include <Protocol/DevicePath.h>\r
31#include <Protocol/TcgService.h>\r
32#include <Protocol/AcpiTable.h>\r
b25380e3 33#include <Protocol/MpService.h>\r
0c18794e 34\r
35#include <Library/DebugLib.h>\r
36#include <Library/BaseMemoryLib.h>\r
37#include <Library/UefiRuntimeServicesTableLib.h>\r
38#include <Library/UefiDriverEntryPoint.h>\r
39#include <Library/HobLib.h>\r
40#include <Library/UefiBootServicesTableLib.h>\r
41#include <Library/BaseLib.h>\r
42#include <Library/MemoryAllocationLib.h>\r
43#include <Library/PrintLib.h>\r
7cb1b15b 44#include <Library/Tpm12DeviceLib.h>\r
0c18794e 45#include <Library/PcdLib.h>\r
46#include <Library/UefiLib.h>\r
6f785cfc 47#include <Library/ReportStatusCodeLib.h>\r
441a3678
MK
48#include <Library/Tpm12CommandLib.h>\r
49#include <Library/BaseCryptLib.h>\r
0c18794e 50\r
0c18794e 51#define TCG_DXE_DATA_FROM_THIS(this) \\r
52 BASE_CR (this, TCG_DXE_DATA, TcgProtocol)\r
53\r
54typedef struct _TCG_DXE_DATA {\r
55 EFI_TCG_PROTOCOL TcgProtocol;\r
56 TCG_EFI_BOOT_SERVICE_CAPABILITY BsCap;\r
57 EFI_TCG_CLIENT_ACPI_TABLE *TcgClientAcpiTable;\r
58 EFI_TCG_SERVER_ACPI_TABLE *TcgServerAcpiTable;\r
59 UINTN EventLogSize;\r
60 UINT8 *LastEvent;\r
0c18794e 61} TCG_DXE_DATA;\r
62\r
63\r
64\r
65EFI_TCG_CLIENT_ACPI_TABLE mTcgClientAcpiTemplate = {\r
66 {\r
67 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
68 sizeof (mTcgClientAcpiTemplate),\r
69 0x02 //Revision\r
70 //\r
71 // Compiler initializes the remaining bytes to 0\r
72 // These fields should be filled in in production\r
73 //\r
74 },\r
75 0, // 0 for PC Client Platform Class\r
76 0, // Log Area Max Length\r
77 (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1) // Log Area Start Address\r
78};\r
79\r
80//\r
81// The following EFI_TCG_SERVER_ACPI_TABLE default setting is just one example,\r
d6b926e7 82// the TPM device connects to LPC, and also defined the ACPI _UID as 0xFF,\r
b3548d32
LG
83// this _UID can be changed and should match with the _UID setting of the TPM\r
84// ACPI device object\r
0c18794e 85//\r
86EFI_TCG_SERVER_ACPI_TABLE mTcgServerAcpiTemplate = {\r
87 {\r
88 EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE,\r
89 sizeof (mTcgServerAcpiTemplate),\r
90 0x02 //Revision\r
91 //\r
92 // Compiler initializes the remaining bytes to 0\r
93 // These fields should be filled in in production\r
94 //\r
95 },\r
96 1, // 1 for Server Platform Class\r
97 0, // Reserved\r
98 0, // Log Area Max Length\r
99 (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1), // Log Area Start Address\r
730f8071
SEHM
100 0x0120, // TCG Specification revision 1.2\r
101 0, // Device Flags\r
0c18794e 102 0, // Interrupt Flags\r
103 0, // GPE\r
104 {0}, // Reserved 3 bytes\r
105 0, // Global System Interrupt\r
106 {\r
107 EFI_ACPI_3_0_SYSTEM_MEMORY,\r
108 0,\r
109 0,\r
110 EFI_ACPI_3_0_BYTE,\r
7cb1b15b 111 0 // Base Address\r
0c18794e 112 },\r
113 0, // Reserved\r
114 {0}, // Configuration Address\r
115 0xFF, // ACPI _UID value of the device, can be changed for different platforms\r
116 0, // ACPI _UID value of the device, can be changed for different platforms\r
117 0, // ACPI _UID value of the device, can be changed for different platforms\r
118 0 // ACPI _UID value of the device, can be changed for different platforms\r
119};\r
120\r
121UINTN mBootAttempts = 0;\r
122CHAR16 mBootVarName[] = L"BootOrder";\r
123\r
b25380e3 124/**\r
125 Get All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function\r
126 Caller is responsible to free LocationBuf.\r
127\r
128 @param[out] LocationBuf Returns Processor Location Buffer.\r
129 @param[out] Num Returns processor number.\r
130\r
131 @retval EFI_SUCCESS Operation completed successfully.\r
132 @retval EFI_UNSUPPORTED MpService protocol not found.\r
133\r
134**/\r
135EFI_STATUS\r
136GetProcessorsCpuLocation (\r
137 OUT EFI_CPU_PHYSICAL_LOCATION **LocationBuf,\r
138 OUT UINTN *Num\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
142 EFI_MP_SERVICES_PROTOCOL *MpProtocol;\r
143 UINTN ProcessorNum;\r
144 UINTN EnabledProcessorNum;\r
145 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
146 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
147 UINTN Index;\r
148\r
149 Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **) &MpProtocol);\r
150 if (EFI_ERROR (Status)) {\r
151 //\r
152 // MP protocol is not installed\r
153 //\r
154 return EFI_UNSUPPORTED;\r
155 }\r
156\r
157 Status = MpProtocol->GetNumberOfProcessors(\r
158 MpProtocol,\r
159 &ProcessorNum,\r
160 &EnabledProcessorNum\r
161 );\r
162 if (EFI_ERROR(Status)){\r
163 return Status;\r
164 }\r
165\r
166 Status = gBS->AllocatePool(\r
167 EfiBootServicesData,\r
168 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
bcb76672 169 (VOID **) &ProcessorLocBuf\r
b25380e3 170 );\r
171 if (EFI_ERROR(Status)){\r
172 return Status;\r
173 }\r
174\r
175 //\r
176 // Get each processor Location info\r
177 //\r
178 for (Index = 0; Index < ProcessorNum; Index++) {\r
179 Status = MpProtocol->GetProcessorInfo(\r
180 MpProtocol,\r
181 Index,\r
182 &ProcessorInfo\r
183 );\r
184 if (EFI_ERROR(Status)){\r
185 FreePool(ProcessorLocBuf);\r
186 return Status;\r
187 }\r
188\r
189 //\r
190 // Get all Processor Location info & measure\r
191 //\r
192 CopyMem(\r
193 &ProcessorLocBuf[Index],\r
194 &ProcessorInfo.Location,\r
195 sizeof(EFI_CPU_PHYSICAL_LOCATION)\r
196 );\r
197 }\r
198\r
199 *LocationBuf = ProcessorLocBuf;\r
200 *Num = ProcessorNum;\r
201\r
202 return Status;\r
203}\r
204\r
0c18794e 205/**\r
b3548d32 206 This service provides EFI protocol capability information, state information\r
0c18794e 207 about the TPM, and Event Log state information.\r
208\r
209 @param[in] This Indicates the calling context\r
b3548d32
LG
210 @param[out] ProtocolCapability The callee allocates memory for a TCG_BOOT_SERVICE_CAPABILITY\r
211 structure and fills in the fields with the EFI protocol\r
0c18794e 212 capability information and the current TPM state information.\r
b3548d32
LG
213 @param[out] TCGFeatureFlags This is a pointer to the feature flags. No feature\r
214 flags are currently defined so this parameter\r
215 MUST be set to 0. However, in the future,\r
216 feature flags may be defined that, for example,\r
0c18794e 217 enable hash algorithm agility.\r
218 @param[out] EventLogLocation This is a pointer to the address of the event log in memory.\r
b3548d32
LG
219 @param[out] EventLogLastEntry If the Event Log contains more than one entry,\r
220 this is a pointer to the address of the start of\r
221 the last entry in the event log in memory.\r
0c18794e 222\r
223 @retval EFI_SUCCESS Operation completed successfully.\r
224 @retval EFI_INVALID_PARAMETER ProtocolCapability does not match TCG capability.\r
b3548d32 225\r
0c18794e 226**/\r
227EFI_STATUS\r
228EFIAPI\r
229TcgDxeStatusCheck (\r
230 IN EFI_TCG_PROTOCOL *This,\r
231 OUT TCG_EFI_BOOT_SERVICE_CAPABILITY *ProtocolCapability,\r
232 OUT UINT32 *TCGFeatureFlags,\r
233 OUT EFI_PHYSICAL_ADDRESS *EventLogLocation,\r
234 OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry\r
235 )\r
236{\r
237 TCG_DXE_DATA *TcgData;\r
238\r
239 TcgData = TCG_DXE_DATA_FROM_THIS (This);\r
240\r
241 if (ProtocolCapability != NULL) {\r
242 *ProtocolCapability = TcgData->BsCap;\r
243 }\r
244\r
245 if (TCGFeatureFlags != NULL) {\r
246 *TCGFeatureFlags = 0;\r
247 }\r
248\r
249 if (EventLogLocation != NULL) {\r
250 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
251 *EventLogLocation = TcgData->TcgClientAcpiTable->Lasa;\r
252 } else {\r
253 *EventLogLocation = TcgData->TcgServerAcpiTable->Lasa;\r
254 }\r
255 }\r
256\r
257 if (EventLogLastEntry != NULL) {\r
5dbb6635 258 if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {\r
0c18794e 259 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)0;\r
260 } else {\r
261 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)TcgData->LastEvent;\r
262 }\r
263 }\r
264\r
265 return EFI_SUCCESS;\r
266}\r
267\r
441a3678
MK
268/**\r
269Single function calculates SHA1 digest value for all raw data. It\r
270combines Sha1Init(), Sha1Update() and Sha1Final().\r
271\r
272@param[in] Data Raw data to be digested.\r
273@param[in] DataLen Size of the raw data.\r
274@param[out] Digest Pointer to a buffer that stores the final digest.\r
275\r
276@retval EFI_SUCCESS Always successfully calculate the final digest.\r
277**/\r
278EFI_STATUS\r
279EFIAPI\r
280TpmCommHashAll (\r
281 IN CONST UINT8 *Data,\r
282 IN UINTN DataLen,\r
283 OUT TPM_DIGEST *Digest\r
284 )\r
285{\r
286 VOID *Sha1Ctx;\r
287 UINTN CtxSize;\r
288\r
289 CtxSize = Sha1GetContextSize ();\r
290 Sha1Ctx = AllocatePool (CtxSize);\r
291 ASSERT (Sha1Ctx != NULL);\r
292\r
293 Sha1Init (Sha1Ctx);\r
294 Sha1Update (Sha1Ctx, Data, DataLen);\r
295 Sha1Final (Sha1Ctx, (UINT8 *)Digest);\r
296\r
297 FreePool (Sha1Ctx);\r
298\r
299 return EFI_SUCCESS;\r
300}\r
301\r
0c18794e 302/**\r
303 This service abstracts the capability to do a hash operation on a data buffer.\r
b3548d32 304\r
0c18794e 305 @param[in] This Indicates the calling context\r
306 @param[in] HashData Pointer to the data buffer to be hashed\r
307 @param[in] HashDataLen Length of the data buffer to be hashed\r
308 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation\r
309 @param[in, out] HashedDataLen Resultant length of the hashed data\r
b3548d32
LG
310 @param[in, out] HashedDataResult Resultant buffer of the hashed data\r
311\r
0c18794e 312 @retval EFI_SUCCESS Operation completed successfully.\r
313 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.\r
314 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.\r
315 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.\r
316 @retval EFI_UNSUPPORTED AlgorithmId not supported.\r
317 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).\r
b3548d32 318\r
0c18794e 319**/\r
320EFI_STATUS\r
321EFIAPI\r
322TcgDxeHashAll (\r
323 IN EFI_TCG_PROTOCOL *This,\r
324 IN UINT8 *HashData,\r
325 IN UINT64 HashDataLen,\r
326 IN TCG_ALGORITHM_ID AlgorithmId,\r
327 IN OUT UINT64 *HashedDataLen,\r
328 IN OUT UINT8 **HashedDataResult\r
329 )\r
330{\r
331 if (HashedDataLen == NULL || HashedDataResult == NULL) {\r
332 return EFI_INVALID_PARAMETER;\r
333 }\r
334\r
335 switch (AlgorithmId) {\r
336 case TPM_ALG_SHA:\r
337 if (*HashedDataLen == 0) {\r
338 *HashedDataLen = sizeof (TPM_DIGEST);\r
339 *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);\r
340 if (*HashedDataResult == NULL) {\r
341 return EFI_OUT_OF_RESOURCES;\r
342 }\r
343 }\r
344\r
345 if (*HashedDataLen < sizeof (TPM_DIGEST)) {\r
346 *HashedDataLen = sizeof (TPM_DIGEST);\r
347 return EFI_BUFFER_TOO_SMALL;\r
348 }\r
349 *HashedDataLen = sizeof (TPM_DIGEST);\r
350\r
730f8071
SEHM
351 if (*HashedDataResult == NULL) {\r
352 *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);\r
b3548d32 353 }\r
f5af77a8 354\r
0c18794e 355 return TpmCommHashAll (\r
356 HashData,\r
357 (UINTN) HashDataLen,\r
358 (TPM_DIGEST*)*HashedDataResult\r
359 );\r
360 default:\r
361 return EFI_UNSUPPORTED;\r
362 }\r
363}\r
364\r
441a3678
MK
365/**\r
366Add a new entry to the Event Log.\r
367\r
368@param[in, out] EventLogPtr Pointer to the Event Log data.\r
369@param[in, out] LogSize Size of the Event Log.\r
370@param[in] MaxSize Maximum size of the Event Log.\r
371@param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
372@param[in] NewEventData Pointer to the new event data.\r
373\r
374@retval EFI_SUCCESS The new event log entry was added.\r
375@retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
376\r
377**/\r
378EFI_STATUS\r
379TpmCommLogEvent (\r
380 IN OUT UINT8 **EventLogPtr,\r
381 IN OUT UINTN *LogSize,\r
382 IN UINTN MaxSize,\r
383 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
384 IN UINT8 *NewEventData\r
385 )\r
386{\r
387 UINTN NewLogSize;\r
388\r
389 //\r
390 // Prevent Event Overflow\r
391 //\r
b35ace17 392 if ((UINTN) NewEventHdr->EventSize > MAX_UINTN - sizeof (*NewEventHdr)) {\r
441a3678
MK
393 return EFI_OUT_OF_RESOURCES;\r
394 }\r
395\r
396 NewLogSize = sizeof (*NewEventHdr) + NewEventHdr->EventSize;\r
397 if (NewLogSize > MaxSize - *LogSize) {\r
398 return EFI_OUT_OF_RESOURCES;\r
399 }\r
400\r
401 *EventLogPtr += *LogSize;\r
402 *LogSize += NewLogSize;\r
403 CopyMem (*EventLogPtr, NewEventHdr, sizeof (*NewEventHdr));\r
404 CopyMem (\r
405 *EventLogPtr + sizeof (*NewEventHdr),\r
406 NewEventData,\r
407 NewEventHdr->EventSize\r
408 );\r
409 return EFI_SUCCESS;\r
410}\r
411\r
0c18794e 412/**\r
413 Add a new entry to the Event Log.\r
414\r
415 @param[in] TcgData TCG_DXE_DATA structure.\r
b3548d32
LG
416 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
417 @param[in] NewEventData Pointer to the new event data.\r
418\r
0c18794e 419 @retval EFI_SUCCESS The new event log entry was added.\r
420 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
421\r
422**/\r
423EFI_STATUS\r
424EFIAPI\r
425TcgDxeLogEventI (\r
426 IN TCG_DXE_DATA *TcgData,\r
427 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
428 IN UINT8 *NewEventData\r
429 )\r
430{\r
431 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
432 TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgClientAcpiTable->Lasa;\r
433 return TpmCommLogEvent (\r
434 &TcgData->LastEvent,\r
435 &TcgData->EventLogSize,\r
436 (UINTN)TcgData->TcgClientAcpiTable->Laml,\r
437 NewEventHdr,\r
438 NewEventData\r
439 );\r
440 } else {\r
441 TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgServerAcpiTable->Lasa;\r
442 return TpmCommLogEvent (\r
443 &TcgData->LastEvent,\r
444 &TcgData->EventLogSize,\r
445 (UINTN)TcgData->TcgServerAcpiTable->Laml,\r
446 NewEventHdr,\r
447 NewEventData\r
448 );\r
449 }\r
450}\r
451\r
452/**\r
453 This service abstracts the capability to add an entry to the Event Log.\r
454\r
455 @param[in] This Indicates the calling context\r
b3548d32
LG
456 @param[in] TCGLogData Pointer to the start of the data buffer containing\r
457 the TCG_PCR_EVENT data structure. All fields in\r
0c18794e 458 this structure are properly filled by the caller.\r
459 @param[in, out] EventNumber The event number of the event just logged\r
b3548d32
LG
460 @param[in] Flags Indicate additional flags. Only one flag has been\r
461 defined at this time, which is 0x01 and means the\r
462 extend operation should not be performed. All\r
463 other bits are reserved.\r
464\r
0c18794e 465 @retval EFI_SUCCESS Operation completed successfully.\r
466 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.\r
b3548d32 467\r
0c18794e 468**/\r
469EFI_STATUS\r
470EFIAPI\r
471TcgDxeLogEvent (\r
472 IN EFI_TCG_PROTOCOL *This,\r
473 IN TCG_PCR_EVENT *TCGLogData,\r
474 IN OUT UINT32 *EventNumber,\r
475 IN UINT32 Flags\r
476 )\r
477{\r
478 TCG_DXE_DATA *TcgData;\r
479\r
677e5c0b 480 if (TCGLogData == NULL){\r
481 return EFI_INVALID_PARAMETER;\r
482 }\r
483\r
0c18794e 484 TcgData = TCG_DXE_DATA_FROM_THIS (This);\r
b3548d32 485\r
5dbb6635 486 if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {\r
0c18794e 487 return EFI_DEVICE_ERROR;\r
488 }\r
489 return TcgDxeLogEventI (\r
490 TcgData,\r
491 (TCG_PCR_EVENT_HDR*)TCGLogData,\r
492 TCGLogData->Event\r
493 );\r
494}\r
495\r
496/**\r
497 This service is a proxy for commands to the TPM.\r
498\r
499 @param[in] This Indicates the calling context\r
500 @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block\r
501 @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block\r
502 @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block\r
503 @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block\r
504\r
505 @retval EFI_SUCCESS Operation completed successfully.\r
506 @retval EFI_INVALID_PARAMETER Invalid ordinal.\r
507 @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.\r
508 @retval EFI_TIMEOUT The TIS timed-out.\r
b3548d32 509\r
0c18794e 510**/\r
511EFI_STATUS\r
512EFIAPI\r
513TcgDxePassThroughToTpm (\r
514 IN EFI_TCG_PROTOCOL *This,\r
515 IN UINT32 TpmInputParameterBlockSize,\r
516 IN UINT8 *TpmInputParameterBlock,\r
517 IN UINT32 TpmOutputParameterBlockSize,\r
518 IN UINT8 *TpmOutputParameterBlock\r
519 )\r
520{\r
b3548d32
LG
521 if (TpmInputParameterBlock == NULL ||\r
522 TpmOutputParameterBlock == NULL ||\r
be02dcee 523 TpmInputParameterBlockSize == 0 ||\r
524 TpmOutputParameterBlockSize == 0) {\r
525 return EFI_INVALID_PARAMETER;\r
526 }\r
527\r
441a3678
MK
528 return Tpm12SubmitCommand (\r
529 TpmInputParameterBlockSize,\r
0c18794e 530 TpmInputParameterBlock,\r
441a3678
MK
531 &TpmOutputParameterBlockSize,\r
532 TpmOutputParameterBlock\r
0c18794e 533 );\r
534}\r
535\r
536/**\r
537 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
538 and add an entry to the Event Log.\r
539\r
540 @param[in] TcgData TCG_DXE_DATA structure.\r
b3548d32 541 @param[in] HashData Physical address of the start of the data buffer\r
0c18794e 542 to be hashed, extended, and logged.\r
543 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
b3548d32
LG
544 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.\r
545 @param[in] NewEventData Pointer to the new event data.\r
0c18794e 546\r
547 @retval EFI_SUCCESS Operation completed successfully.\r
548 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
549 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
550\r
551**/\r
552EFI_STATUS\r
553EFIAPI\r
554TcgDxeHashLogExtendEventI (\r
555 IN TCG_DXE_DATA *TcgData,\r
556 IN UINT8 *HashData,\r
557 IN UINT64 HashDataLen,\r
558 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
559 IN UINT8 *NewEventData\r
560 )\r
561{\r
562 EFI_STATUS Status;\r
563\r
6f785cfc
JY
564 if (!TcgData->BsCap.TPMPresentFlag) {\r
565 return EFI_DEVICE_ERROR;\r
677e5c0b 566 }\r
567\r
568 if (HashDataLen > 0 || HashData != NULL) {\r
0c18794e 569 Status = TpmCommHashAll (\r
570 HashData,\r
571 (UINTN) HashDataLen,\r
572 &NewEventHdr->Digest\r
573 );\r
f7fe68db
CZ
574 if (EFI_ERROR(Status)) {\r
575 DEBUG ((DEBUG_ERROR, "TpmCommHashAll Failed. %x\n", Status));\r
6f785cfc 576 goto Done;\r
f7fe68db 577 }\r
0c18794e 578 }\r
579\r
441a3678 580 Status = Tpm12Extend (\r
0c18794e 581 &NewEventHdr->Digest,\r
582 NewEventHdr->PCRIndex,\r
583 NULL\r
584 );\r
585 if (!EFI_ERROR (Status)) {\r
586 Status = TcgDxeLogEventI (TcgData, NewEventHdr, NewEventData);\r
587 }\r
588\r
6f785cfc
JY
589Done:\r
590 if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {\r
e905fbb0 591 DEBUG ((DEBUG_ERROR, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status));\r
6f785cfc
JY
592 TcgData->BsCap.TPMPresentFlag = FALSE;\r
593 REPORT_STATUS_CODE (\r
594 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
595 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
596 );\r
597 Status = EFI_DEVICE_ERROR;\r
598 }\r
599\r
0c18794e 600 return Status;\r
601}\r
602\r
603/**\r
604 This service abstracts the capability to do a hash operation on a data buffer,\r
605 extend a specific TPM PCR with the hash result, and add an entry to the Event Log\r
606\r
607 @param[in] This Indicates the calling context\r
b3548d32 608 @param[in] HashData Physical address of the start of the data buffer\r
0c18794e 609 to be hashed, extended, and logged.\r
610 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
611 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation\r
b3548d32 612 @param[in, out] TCGLogData The physical address of the start of the data\r
0c18794e 613 buffer containing the TCG_PCR_EVENT data structure.\r
614 @param[in, out] EventNumber The event number of the event just logged.\r
b3548d32
LG
615 @param[out] EventLogLastEntry Physical address of the first byte of the entry\r
616 just placed in the Event Log. If the Event Log was\r
617 empty when this function was called then this physical\r
618 address will be the same as the physical address of\r
0c18794e 619 the start of the Event Log.\r
620\r
621 @retval EFI_SUCCESS Operation completed successfully.\r
622 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.\r
623 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.\r
624 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
b3548d32 625\r
0c18794e 626**/\r
627EFI_STATUS\r
628EFIAPI\r
629TcgDxeHashLogExtendEvent (\r
630 IN EFI_TCG_PROTOCOL *This,\r
631 IN EFI_PHYSICAL_ADDRESS HashData,\r
632 IN UINT64 HashDataLen,\r
633 IN TPM_ALGORITHM_ID AlgorithmId,\r
634 IN OUT TCG_PCR_EVENT *TCGLogData,\r
635 IN OUT UINT32 *EventNumber,\r
636 OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry\r
637 )\r
638{\r
639 TCG_DXE_DATA *TcgData;\r
15f2d739 640 EFI_STATUS Status;\r
0c18794e 641\r
677e5c0b 642 if (TCGLogData == NULL || EventLogLastEntry == NULL){\r
643 return EFI_INVALID_PARAMETER;\r
644 }\r
645\r
0c18794e 646 TcgData = TCG_DXE_DATA_FROM_THIS (This);\r
b3548d32 647\r
5dbb6635 648 if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {\r
0c18794e 649 return EFI_DEVICE_ERROR;\r
650 }\r
b3548d32 651\r
0c18794e 652 if (AlgorithmId != TPM_ALG_SHA) {\r
653 return EFI_UNSUPPORTED;\r
654 }\r
b3548d32 655\r
5dbb6635 656 if (HashData == 0 && HashDataLen > 0) {\r
6f785cfc
JY
657 return EFI_INVALID_PARAMETER;\r
658 }\r
0c18794e 659\r
15f2d739 660 Status = TcgDxeHashLogExtendEventI (\r
661 TcgData,\r
662 (UINT8 *) (UINTN) HashData,\r
663 HashDataLen,\r
664 (TCG_PCR_EVENT_HDR*)TCGLogData,\r
665 TCGLogData->Event\r
666 );\r
667\r
668 if (!EFI_ERROR(Status)){\r
669 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN) TcgData->LastEvent;\r
670 }\r
671\r
672 return Status;\r
0c18794e 673}\r
674\r
675TCG_DXE_DATA mTcgDxeData = {\r
676 {\r
677 TcgDxeStatusCheck,\r
678 TcgDxeHashAll,\r
679 TcgDxeLogEvent,\r
680 TcgDxePassThroughToTpm,\r
681 TcgDxeHashLogExtendEvent\r
682 },\r
683 {\r
684 sizeof (mTcgDxeData.BsCap),\r
685 { 1, 2, 0, 0 },\r
686 { 1, 2, 0, 0 },\r
687 1,\r
688 TRUE,\r
689 FALSE\r
690 },\r
691 &mTcgClientAcpiTemplate,\r
692 &mTcgServerAcpiTemplate,\r
693 0,\r
0c18794e 694 NULL\r
695};\r
696\r
697/**\r
698 Initialize the Event Log and log events passed from the PEI phase.\r
699\r
700 @retval EFI_SUCCESS Operation completed successfully.\r
701 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
702\r
703**/\r
704EFI_STATUS\r
705EFIAPI\r
706SetupEventLog (\r
707 VOID\r
708 )\r
709{\r
710 EFI_STATUS Status;\r
711 TCG_PCR_EVENT *TcgEvent;\r
712 EFI_PEI_HOB_POINTERS GuidHob;\r
713 EFI_PHYSICAL_ADDRESS Lasa;\r
b3548d32 714\r
0c18794e 715 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
716 Lasa = mTcgClientAcpiTemplate.Lasa;\r
b3548d32 717\r
0c18794e 718 Status = gBS->AllocatePages (\r
719 AllocateMaxAddress,\r
720 EfiACPIMemoryNVS,\r
91e914f5 721 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
0c18794e 722 &Lasa\r
723 );\r
724 if (EFI_ERROR (Status)) {\r
725 return Status;\r
726 }\r
727 mTcgClientAcpiTemplate.Lasa = Lasa;\r
728 //\r
b3548d32 729 // To initialize them as 0xFF is recommended\r
0c18794e 730 // because the OS can know the last entry for that.\r
731 //\r
91e914f5
CZ
732 SetMem ((VOID *)(UINTN)mTcgClientAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
733 mTcgClientAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
b3548d32 734\r
0c18794e 735 } else {\r
736 Lasa = mTcgServerAcpiTemplate.Lasa;\r
b3548d32 737\r
0c18794e 738 Status = gBS->AllocatePages (\r
739 AllocateMaxAddress,\r
740 EfiACPIMemoryNVS,\r
91e914f5 741 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
0c18794e 742 &Lasa\r
743 );\r
744 if (EFI_ERROR (Status)) {\r
745 return Status;\r
746 }\r
747 mTcgServerAcpiTemplate.Lasa = Lasa;\r
748 //\r
b3548d32 749 // To initialize them as 0xFF is recommended\r
0c18794e 750 // because the OS can know the last entry for that.\r
751 //\r
91e914f5
CZ
752 SetMem ((VOID *)(UINTN)mTcgServerAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
753 mTcgServerAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
0c18794e 754 }\r
755\r
756 GuidHob.Raw = GetHobList ();\r
b3548d32 757 while (!EFI_ERROR (Status) &&\r
0c18794e 758 (GuidHob.Raw = GetNextGuidHob (&gTcgEventEntryHobGuid, GuidHob.Raw)) != NULL) {\r
759 TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);\r
760 GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
761 Status = TcgDxeLogEventI (\r
762 &mTcgDxeData,\r
763 (TCG_PCR_EVENT_HDR*)TcgEvent,\r
764 TcgEvent->Event\r
765 );\r
766 }\r
767\r
768 return Status;\r
769}\r
770\r
771/**\r
772 Measure and log an action string, and extend the measurement result into PCR[5].\r
773\r
b3548d32
LG
774 @param[in] String A specific string that indicates an Action event.\r
775\r
0c18794e 776 @retval EFI_SUCCESS Operation completed successfully.\r
777 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
778\r
779**/\r
780EFI_STATUS\r
781EFIAPI\r
782TcgMeasureAction (\r
783 IN CHAR8 *String\r
784 )\r
785{\r
786 TCG_PCR_EVENT_HDR TcgEvent;\r
787\r
788 TcgEvent.PCRIndex = 5;\r
789 TcgEvent.EventType = EV_EFI_ACTION;\r
790 TcgEvent.EventSize = (UINT32)AsciiStrLen (String);\r
791 return TcgDxeHashLogExtendEventI (\r
792 &mTcgDxeData,\r
793 (UINT8*)String,\r
794 TcgEvent.EventSize,\r
795 &TcgEvent,\r
796 (UINT8 *) String\r
797 );\r
798}\r
799\r
800/**\r
801 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
802\r
803 @retval EFI_SUCCESS Operation completed successfully.\r
804 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
805\r
806**/\r
807EFI_STATUS\r
808EFIAPI\r
809MeasureHandoffTables (\r
810 VOID\r
811 )\r
812{\r
813 EFI_STATUS Status;\r
0c18794e 814 TCG_PCR_EVENT_HDR TcgEvent;\r
815 EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
b25380e3 816 UINTN ProcessorNum;\r
817 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
0c18794e 818\r
d4193108 819 ProcessorLocBuf = NULL;\r
d2de4483 820 Status = EFI_SUCCESS;\r
0c18794e 821\r
b25380e3 822 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
823 //\r
b3548d32 824 // Tcg Server spec.\r
b25380e3 825 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
826 //\r
827 Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);\r
828\r
829 if (!EFI_ERROR(Status)){\r
830 TcgEvent.PCRIndex = 1;\r
831 TcgEvent.EventType = EV_TABLE_OF_DEVICES;\r
832 TcgEvent.EventSize = sizeof (HandoffTables);\r
833\r
834 HandoffTables.NumberOfTables = 1;\r
835 HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
836 HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
837\r
838 Status = TcgDxeHashLogExtendEventI (\r
839 &mTcgDxeData,\r
840 (UINT8*)(UINTN)ProcessorLocBuf,\r
841 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
842 &TcgEvent,\r
843 (UINT8*)&HandoffTables\r
844 );\r
845\r
846 FreePool(ProcessorLocBuf);\r
847 }\r
848 }\r
849\r
0c18794e 850 return Status;\r
851}\r
852\r
853/**\r
854 Measure and log Separator event, and extend the measurement result into a specific PCR.\r
855\r
b3548d32 856 @param[in] PCRIndex PCR index.\r
0c18794e 857\r
858 @retval EFI_SUCCESS Operation completed successfully.\r
859 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
860\r
861**/\r
862EFI_STATUS\r
863EFIAPI\r
864MeasureSeparatorEvent (\r
865 IN TPM_PCRINDEX PCRIndex\r
866 )\r
867{\r
868 TCG_PCR_EVENT_HDR TcgEvent;\r
869 UINT32 EventData;\r
870\r
871 EventData = 0;\r
872 TcgEvent.PCRIndex = PCRIndex;\r
873 TcgEvent.EventType = EV_SEPARATOR;\r
874 TcgEvent.EventSize = (UINT32)sizeof (EventData);\r
875 return TcgDxeHashLogExtendEventI (\r
876 &mTcgDxeData,\r
877 (UINT8 *)&EventData,\r
878 sizeof (EventData),\r
879 &TcgEvent,\r
880 (UINT8 *)&EventData\r
881 );\r
882}\r
883\r
884/**\r
885 Read an EFI Variable.\r
886\r
887 This function allocates a buffer to return the contents of the variable. The caller is\r
888 responsible for freeing the buffer.\r
889\r
890 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
891 @param[in] VendorGuid A unique identifier for the vendor.\r
b3548d32 892 @param[out] VarSize The size of the variable data.\r
0c18794e 893\r
894 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.\r
895\r
896**/\r
897VOID *\r
898EFIAPI\r
899ReadVariable (\r
900 IN CHAR16 *VarName,\r
901 IN EFI_GUID *VendorGuid,\r
902 OUT UINTN *VarSize\r
903 )\r
904{\r
905 EFI_STATUS Status;\r
906 VOID *VarData;\r
907\r
908 *VarSize = 0;\r
909 Status = gRT->GetVariable (\r
910 VarName,\r
911 VendorGuid,\r
912 NULL,\r
913 VarSize,\r
914 NULL\r
915 );\r
916 if (Status != EFI_BUFFER_TOO_SMALL) {\r
917 return NULL;\r
918 }\r
919\r
920 VarData = AllocatePool (*VarSize);\r
921 if (VarData != NULL) {\r
922 Status = gRT->GetVariable (\r
923 VarName,\r
924 VendorGuid,\r
925 NULL,\r
926 VarSize,\r
927 VarData\r
928 );\r
929 if (EFI_ERROR (Status)) {\r
930 FreePool (VarData);\r
931 VarData = NULL;\r
932 *VarSize = 0;\r
933 }\r
934 }\r
935 return VarData;\r
936}\r
937\r
938/**\r
939 Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
940\r
b3548d32
LG
941 @param[in] PCRIndex PCR Index.\r
942 @param[in] EventType Event type.\r
0c18794e 943 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
944 @param[in] VendorGuid A unique identifier for the vendor.\r
b3548d32
LG
945 @param[in] VarData The content of the variable data.\r
946 @param[in] VarSize The size of the variable data.\r
947\r
0c18794e 948 @retval EFI_SUCCESS Operation completed successfully.\r
949 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
950 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
951\r
952**/\r
953EFI_STATUS\r
954EFIAPI\r
955MeasureVariable (\r
956 IN TPM_PCRINDEX PCRIndex,\r
957 IN TCG_EVENTTYPE EventType,\r
958 IN CHAR16 *VarName,\r
959 IN EFI_GUID *VendorGuid,\r
960 IN VOID *VarData,\r
961 IN UINTN VarSize\r
962 )\r
963{\r
964 EFI_STATUS Status;\r
965 TCG_PCR_EVENT_HDR TcgEvent;\r
966 UINTN VarNameLength;\r
967 EFI_VARIABLE_DATA *VarLog;\r
968\r
969 VarNameLength = StrLen (VarName);\r
970 TcgEvent.PCRIndex = PCRIndex;\r
971 TcgEvent.EventType = EventType;\r
972 TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
973 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
974\r
975 VarLog = (EFI_VARIABLE_DATA*)AllocatePool (TcgEvent.EventSize);\r
976 if (VarLog == NULL) {\r
977 return EFI_OUT_OF_RESOURCES;\r
978 }\r
979\r
980 VarLog->VariableName = *VendorGuid;\r
981 VarLog->UnicodeNameLength = VarNameLength;\r
982 VarLog->VariableDataLength = VarSize;\r
983 CopyMem (\r
984 VarLog->UnicodeName,\r
985 VarName,\r
986 VarNameLength * sizeof (*VarName)\r
987 );\r
988 CopyMem (\r
989 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
990 VarData,\r
991 VarSize\r
992 );\r
993\r
994 Status = TcgDxeHashLogExtendEventI (\r
995 &mTcgDxeData,\r
36811012
CZ
996 (UINT8*)VarLog,\r
997 TcgEvent.EventSize,\r
0c18794e 998 &TcgEvent,\r
999 (UINT8*)VarLog\r
1000 );\r
1001 FreePool (VarLog);\r
1002 return Status;\r
1003}\r
1004\r
1005/**\r
1006 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].\r
1007\r
1008 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
1009 @param[in] VendorGuid A unique identifier for the vendor.\r
b3548d32
LG
1010 @param[out] VarSize The size of the variable data.\r
1011 @param[out] VarData Pointer to the content of the variable.\r
1012\r
0c18794e 1013 @retval EFI_SUCCESS Operation completed successfully.\r
1014 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1015 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1016\r
1017**/\r
1018EFI_STATUS\r
1019EFIAPI\r
1020ReadAndMeasureBootVariable (\r
1021 IN CHAR16 *VarName,\r
1022 IN EFI_GUID *VendorGuid,\r
1023 OUT UINTN *VarSize,\r
1024 OUT VOID **VarData\r
1025 )\r
1026{\r
1027 EFI_STATUS Status;\r
1028\r
1029 *VarData = ReadVariable (VarName, VendorGuid, VarSize);\r
1030 if (*VarData == NULL) {\r
1031 return EFI_NOT_FOUND;\r
1032 }\r
1033\r
1034 Status = MeasureVariable (\r
1035 5,\r
1036 EV_EFI_VARIABLE_BOOT,\r
1037 VarName,\r
1038 VendorGuid,\r
1039 *VarData,\r
1040 *VarSize\r
1041 );\r
1042 return Status;\r
1043}\r
1044\r
1045/**\r
1046 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
1047\r
1048 The EFI boot variables are BootOrder and Boot#### variables.\r
1049\r
1050 @retval EFI_SUCCESS Operation completed successfully.\r
1051 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
1052 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1053\r
1054**/\r
1055EFI_STATUS\r
1056EFIAPI\r
1057MeasureAllBootVariables (\r
1058 VOID\r
1059 )\r
1060{\r
1061 EFI_STATUS Status;\r
1062 UINT16 *BootOrder;\r
1063 UINTN BootCount;\r
1064 UINTN Index;\r
1065 VOID *BootVarData;\r
1066 UINTN Size;\r
1067\r
1068 Status = ReadAndMeasureBootVariable (\r
1069 mBootVarName,\r
1070 &gEfiGlobalVariableGuid,\r
1071 &BootCount,\r
1072 (VOID **) &BootOrder\r
1073 );\r
61959fa9 1074 if (Status == EFI_NOT_FOUND || BootOrder == NULL) {\r
0c18794e 1075 return EFI_SUCCESS;\r
1076 }\r
0c18794e 1077\r
1078 if (EFI_ERROR (Status)) {\r
f7fe68db
CZ
1079 //\r
1080 // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
1081 //\r
0c18794e 1082 FreePool (BootOrder);\r
1083 return Status;\r
1084 }\r
1085\r
1086 BootCount /= sizeof (*BootOrder);\r
1087 for (Index = 0; Index < BootCount; Index++) {\r
1088 UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
1089 Status = ReadAndMeasureBootVariable (\r
1090 mBootVarName,\r
1091 &gEfiGlobalVariableGuid,\r
1092 &Size,\r
1093 &BootVarData\r
1094 );\r
1095 if (!EFI_ERROR (Status)) {\r
1096 FreePool (BootVarData);\r
1097 }\r
1098 }\r
1099\r
1100 FreePool (BootOrder);\r
1101 return EFI_SUCCESS;\r
1102}\r
1103\r
1104/**\r
1105 Ready to Boot Event notification handler.\r
1106\r
1107 Sequence of OS boot events is measured in this event notification handler.\r
1108\r
1109 @param[in] Event Event whose notification function is being invoked\r
1110 @param[in] Context Pointer to the notification function's context\r
1111\r
1112**/\r
1113VOID\r
1114EFIAPI\r
1115OnReadyToBoot (\r
1116 IN EFI_EVENT Event,\r
1117 IN VOID *Context\r
1118 )\r
1119{\r
1120 EFI_STATUS Status;\r
1121 TPM_PCRINDEX PcrIndex;\r
1122\r
1123 if (mBootAttempts == 0) {\r
1124\r
1125 //\r
1126 // Measure handoff tables.\r
1127 //\r
1128 Status = MeasureHandoffTables ();\r
1129 if (EFI_ERROR (Status)) {\r
e905fbb0 1130 DEBUG ((DEBUG_ERROR, "HOBs not Measured. Error!\n"));\r
0c18794e 1131 }\r
1132\r
1133 //\r
1134 // Measure BootOrder & Boot#### variables.\r
1135 //\r
1136 Status = MeasureAllBootVariables ();\r
1137 if (EFI_ERROR (Status)) {\r
e905fbb0 1138 DEBUG ((DEBUG_ERROR, "Boot Variables not Measured. Error!\n"));\r
0c18794e 1139 }\r
1140\r
1141 //\r
1142 // 1. This is the first boot attempt.\r
1143 //\r
1144 Status = TcgMeasureAction (\r
1145 EFI_CALLING_EFI_APPLICATION\r
1146 );\r
f7fe68db 1147 if (EFI_ERROR (Status)) {\r
e905fbb0 1148 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
f7fe68db 1149 }\r
0c18794e 1150\r
1151 //\r
1152 // 2. Draw a line between pre-boot env and entering post-boot env.\r
1153 //\r
1154 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {\r
1155 Status = MeasureSeparatorEvent (PcrIndex);\r
f7fe68db 1156 if (EFI_ERROR (Status)) {\r
0ab475c9 1157 DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n"));\r
f7fe68db 1158 }\r
0c18794e 1159 }\r
1160\r
1161 //\r
1162 // 3. Measure GPT. It would be done in SAP driver.\r
1163 //\r
1164\r
1165 //\r
1166 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
1167 //\r
1168\r
1169 //\r
1170 // 5. Read & Measure variable. BootOrder already measured.\r
1171 //\r
1172 } else {\r
1173 //\r
1174 // 6. Not first attempt, meaning a return from last attempt\r
1175 //\r
1176 Status = TcgMeasureAction (\r
5f3b0250 1177 EFI_RETURNING_FROM_EFI_APPLICATION\r
0c18794e 1178 );\r
f7fe68db 1179 if (EFI_ERROR (Status)) {\r
e905fbb0 1180 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATION));\r
f7fe68db 1181 }\r
0c18794e 1182 }\r
1183\r
e905fbb0 1184 DEBUG ((DEBUG_INFO, "TPM TcgDxe Measure Data when ReadyToBoot\n"));\r
0c18794e 1185 //\r
1186 // Increase boot attempt counter.\r
1187 //\r
1188 mBootAttempts++;\r
1189}\r
1190\r
1191/**\r
1192 Install TCG ACPI Table when ACPI Table Protocol is available.\r
1193\r
b3548d32
LG
1194 A system's firmware uses an ACPI table to identify the system's TCG capabilities\r
1195 to the Post-Boot environment. The information in this ACPI table is not guaranteed\r
1196 to be valid until the Host Platform transitions from pre-boot state to post-boot state.\r
0c18794e 1197\r
1198 @param[in] Event Event whose notification function is being invoked\r
1199 @param[in] Context Pointer to the notification function's context\r
1200**/\r
1201VOID\r
1202EFIAPI\r
1203InstallAcpiTable (\r
1204 IN EFI_EVENT Event,\r
1205 IN VOID* Context\r
1206 )\r
1207{\r
1208 UINTN TableKey;\r
1209 EFI_STATUS Status;\r
1210 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
1211 UINT8 Checksum;\r
e84f07b5 1212 UINT64 OemTableId;\r
0c18794e 1213\r
1214 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
1215 if (EFI_ERROR (Status)) {\r
1216 return;\r
1217 }\r
1218\r
1219 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
e84f07b5
SZ
1220 CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));\r
1221 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1222 CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1223 mTcgClientAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1224 mTcgClientAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1225 mTcgClientAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
0c18794e 1226 //\r
d6b926e7 1227 // The ACPI table must be checksummed before calling the InstallAcpiTable()\r
0c18794e 1228 // service of the ACPI table protocol to install it.\r
1229 //\r
1230 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));\r
1231 mTcgClientAcpiTemplate.Header.Checksum = Checksum;\r
1232\r
1233 Status = AcpiTable->InstallAcpiTable (\r
1234 AcpiTable,\r
1235 &mTcgClientAcpiTemplate,\r
1236 sizeof (mTcgClientAcpiTemplate),\r
1237 &TableKey\r
1238 );\r
1239 } else {\r
e84f07b5
SZ
1240 CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));\r
1241 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1242 CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1243 mTcgServerAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1244 mTcgServerAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1245 mTcgServerAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
0c18794e 1246 //\r
d6b926e7 1247 // The ACPI table must be checksummed before calling the InstallAcpiTable()\r
0c18794e 1248 // service of the ACPI table protocol to install it.\r
1249 //\r
1250 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));\r
1251 mTcgServerAcpiTemplate.Header.Checksum = Checksum;\r
1252\r
7cb1b15b 1253 mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress);\r
0c18794e 1254 Status = AcpiTable->InstallAcpiTable (\r
1255 AcpiTable,\r
1256 &mTcgServerAcpiTemplate,\r
1257 sizeof (mTcgServerAcpiTemplate),\r
1258 &TableKey\r
1259 );\r
1260 }\r
f7fe68db
CZ
1261\r
1262 if (EFI_ERROR (Status)) {\r
e905fbb0 1263 DEBUG((DEBUG_ERROR, "Tcg Acpi Table installation failure"));\r
f7fe68db 1264 }\r
0c18794e 1265}\r
1266\r
1267/**\r
1268 Exit Boot Services Event notification handler.\r
1269\r
1270 Measure invocation and success of ExitBootServices.\r
1271\r
1272 @param[in] Event Event whose notification function is being invoked\r
1273 @param[in] Context Pointer to the notification function's context\r
1274\r
1275**/\r
1276VOID\r
1277EFIAPI\r
1278OnExitBootServices (\r
1279 IN EFI_EVENT Event,\r
1280 IN VOID *Context\r
1281 )\r
1282{\r
1283 EFI_STATUS Status;\r
1284\r
1285 //\r
1286 // Measure invocation of ExitBootServices,\r
1287 //\r
1288 Status = TcgMeasureAction (\r
1289 EFI_EXIT_BOOT_SERVICES_INVOCATION\r
1290 );\r
f7fe68db 1291 if (EFI_ERROR (Status)) {\r
e905fbb0 1292 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
f7fe68db 1293 }\r
0c18794e 1294\r
1295 //\r
1296 // Measure success of ExitBootServices\r
1297 //\r
1298 Status = TcgMeasureAction (\r
1299 EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
1300 );\r
f7fe68db 1301 if (EFI_ERROR (Status)){\r
e905fbb0 1302 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
f7fe68db 1303 }\r
0c18794e 1304}\r
1305\r
9e945f78 1306/**\r
1307 Exit Boot Services Failed Event notification handler.\r
1308\r
1309 Measure Failure of ExitBootServices.\r
1310\r
1311 @param[in] Event Event whose notification function is being invoked\r
1312 @param[in] Context Pointer to the notification function's context\r
1313\r
1314**/\r
1315VOID\r
1316EFIAPI\r
1317OnExitBootServicesFailed (\r
1318 IN EFI_EVENT Event,\r
1319 IN VOID *Context\r
1320 )\r
1321{\r
1322 EFI_STATUS Status;\r
1323\r
1324 //\r
1325 // Measure Failure of ExitBootServices,\r
1326 //\r
1327 Status = TcgMeasureAction (\r
1328 EFI_EXIT_BOOT_SERVICES_FAILED\r
1329 );\r
f7fe68db 1330 if (EFI_ERROR (Status)){\r
e905fbb0 1331 DEBUG ((DEBUG_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
f7fe68db 1332 }\r
9e945f78 1333}\r
1334\r
0c18794e 1335/**\r
1336 Get TPM Deactivated state.\r
1337\r
b3548d32 1338 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state.\r
0c18794e 1339\r
1340 @retval EFI_SUCCESS Operation completed successfully.\r
1341 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1342\r
1343**/\r
1344EFI_STATUS\r
1345GetTpmStatus (\r
441a3678 1346 OUT BOOLEAN *TPMDeactivatedFlag\r
0c18794e 1347 )\r
1348{\r
441a3678
MK
1349 EFI_STATUS Status;\r
1350 TPM_STCLEAR_FLAGS VolatileFlags;\r
0c18794e 1351\r
441a3678 1352 Status = Tpm12GetCapabilityFlagVolatile (&VolatileFlags);\r
0c18794e 1353 if (!EFI_ERROR (Status)) {\r
441a3678 1354 *TPMDeactivatedFlag = VolatileFlags.deactivated;\r
0c18794e 1355 }\r
1356\r
1357 return Status;\r
1358}\r
1359\r
1360/**\r
1361 The driver's entry point.\r
1362\r
1363 It publishes EFI TCG Protocol.\r
1364\r
b3548d32 1365 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
0c18794e 1366 @param[in] SystemTable A pointer to the EFI System Table.\r
b3548d32 1367\r
0c18794e 1368 @retval EFI_SUCCESS The entry point is executed successfully.\r
1369 @retval other Some error occurs when executing this entry point.\r
1370\r
1371**/\r
1372EFI_STATUS\r
1373EFIAPI\r
1374DriverEntry (\r
1375 IN EFI_HANDLE ImageHandle,\r
1376 IN EFI_SYSTEM_TABLE *SystemTable\r
1377 )\r
1378{\r
1379 EFI_STATUS Status;\r
1380 EFI_EVENT Event;\r
1381 VOID *Registration;\r
1382\r
c1d93242 1383 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
e905fbb0 1384 DEBUG ((DEBUG_ERROR, "No TPM12 instance required!\n"));\r
c1d93242
JY
1385 return EFI_UNSUPPORTED;\r
1386 }\r
1387\r
3dd05ac3 1388 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
e905fbb0 1389 DEBUG ((DEBUG_ERROR, "TPM error!\n"));\r
3dd05ac3
JY
1390 return EFI_DEVICE_ERROR;\r
1391 }\r
1392\r
7cb1b15b 1393 Status = Tpm12RequestUseTpm ();\r
0c18794e 1394 if (EFI_ERROR (Status)) {\r
e905fbb0 1395 DEBUG ((DEBUG_ERROR, "TPM not detected!\n"));\r
0c18794e 1396 return Status;\r
1397 }\r
1398\r
1399 Status = GetTpmStatus (&mTcgDxeData.BsCap.TPMDeactivatedFlag);\r
1400 if (EFI_ERROR (Status)) {\r
1401 DEBUG ((\r
e905fbb0 1402 DEBUG_ERROR,\r
ec4910cd 1403 "DriverEntry: TPM not working properly\n"\r
0c18794e 1404 ));\r
1405 return Status;\r
1406 }\r
1407\r
1408 Status = gBS->InstallProtocolInterface (\r
1409 &ImageHandle,\r
1410 &gEfiTcgProtocolGuid,\r
1411 EFI_NATIVE_INTERFACE,\r
1412 &mTcgDxeData.TcgProtocol\r
1413 );\r
5dbb6635 1414 if (!EFI_ERROR (Status) && (!mTcgDxeData.BsCap.TPMDeactivatedFlag) && mTcgDxeData.BsCap.TPMPresentFlag) {\r
0c18794e 1415 //\r
1416 // Setup the log area and copy event log from hob list to it\r
1417 //\r
1418 Status = SetupEventLog ();\r
1419 ASSERT_EFI_ERROR (Status);\r
1420\r
1421 //\r
1422 // Measure handoff tables, Boot#### variables etc.\r
1423 //\r
1424 Status = EfiCreateEventReadyToBootEx (\r
1425 TPL_CALLBACK,\r
1426 OnReadyToBoot,\r
1427 NULL,\r
1428 &Event\r
1429 );\r
1430\r
1431 Status = gBS->CreateEventEx (\r
1432 EVT_NOTIFY_SIGNAL,\r
1433 TPL_NOTIFY,\r
1434 OnExitBootServices,\r
1435 NULL,\r
1436 &gEfiEventExitBootServicesGuid,\r
1437 &Event\r
1438 );\r
9e945f78 1439\r
1440 //\r
b3548d32 1441 // Measure Exit Boot Service failed\r
9e945f78 1442 //\r
1443 Status = gBS->CreateEventEx (\r
1444 EVT_NOTIFY_SIGNAL,\r
1445 TPL_NOTIFY,\r
1446 OnExitBootServicesFailed,\r
1447 NULL,\r
1448 &gEventExitBootServicesFailedGuid,\r
1449 &Event\r
1450 );\r
0c18794e 1451 }\r
1452\r
627c3961 1453 //\r
1454 // Install ACPI Table\r
1455 //\r
1456 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
b3548d32 1457\r
0c18794e 1458 return Status;\r
1459}\r