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