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