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