]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/TcgDxe/TcgDxe.c
SecurityPkg: TcgDxe,Tcg2Dxe,TrEEDxe: New PCD for TCG event log and TCG2 final event...
[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
49#include <Library/TpmCommLib.h>\r
50#include <Library/PcdLib.h>\r
51#include <Library/UefiLib.h>\r
6f785cfc 52#include <Library/ReportStatusCodeLib.h>\r
0c18794e 53\r
54#include "TpmComm.h"\r
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
66 TIS_TPM_HANDLE TpmHandle;\r
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
106 0x0100, // TCG Specification revision 1.0\r
107 2, // Device Flags\r
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
117 TPM_BASE_ADDRESS // Base Address\r
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
274/**\r
275 This service abstracts the capability to do a hash operation on a data buffer.\r
276 \r
277 @param[in] This Indicates the calling context\r
278 @param[in] HashData Pointer to the data buffer to be hashed\r
279 @param[in] HashDataLen Length of the data buffer to be hashed\r
280 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation\r
281 @param[in, out] HashedDataLen Resultant length of the hashed data\r
282 @param[in, out] HashedDataResult Resultant buffer of the hashed data \r
283 \r
284 @retval EFI_SUCCESS Operation completed successfully.\r
285 @retval EFI_INVALID_PARAMETER HashDataLen is NULL.\r
286 @retval EFI_INVALID_PARAMETER HashDataLenResult is NULL.\r
287 @retval EFI_OUT_OF_RESOURCES Cannot allocate buffer of size *HashedDataLen.\r
288 @retval EFI_UNSUPPORTED AlgorithmId not supported.\r
289 @retval EFI_BUFFER_TOO_SMALL *HashedDataLen < sizeof (TCG_DIGEST).\r
290 \r
291**/\r
292EFI_STATUS\r
293EFIAPI\r
294TcgDxeHashAll (\r
295 IN EFI_TCG_PROTOCOL *This,\r
296 IN UINT8 *HashData,\r
297 IN UINT64 HashDataLen,\r
298 IN TCG_ALGORITHM_ID AlgorithmId,\r
299 IN OUT UINT64 *HashedDataLen,\r
300 IN OUT UINT8 **HashedDataResult\r
301 )\r
302{\r
303 if (HashedDataLen == NULL || HashedDataResult == NULL) {\r
304 return EFI_INVALID_PARAMETER;\r
305 }\r
306\r
307 switch (AlgorithmId) {\r
308 case TPM_ALG_SHA:\r
309 if (*HashedDataLen == 0) {\r
310 *HashedDataLen = sizeof (TPM_DIGEST);\r
311 *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);\r
312 if (*HashedDataResult == NULL) {\r
313 return EFI_OUT_OF_RESOURCES;\r
314 }\r
315 }\r
316\r
317 if (*HashedDataLen < sizeof (TPM_DIGEST)) {\r
318 *HashedDataLen = sizeof (TPM_DIGEST);\r
319 return EFI_BUFFER_TOO_SMALL;\r
320 }\r
321 *HashedDataLen = sizeof (TPM_DIGEST);\r
322\r
f5af77a8 323 if (*HashedDataResult == NULL) {\r
324 *HashedDataResult = AllocatePool ((UINTN) *HashedDataLen);\r
325 } \r
326\r
0c18794e 327 return TpmCommHashAll (\r
328 HashData,\r
329 (UINTN) HashDataLen,\r
330 (TPM_DIGEST*)*HashedDataResult\r
331 );\r
332 default:\r
333 return EFI_UNSUPPORTED;\r
334 }\r
335}\r
336\r
337/**\r
338 Add a new entry to the Event Log.\r
339\r
340 @param[in] TcgData TCG_DXE_DATA structure.\r
341 @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
342 @param[in] NewEventData Pointer to the new event data. \r
343 \r
344 @retval EFI_SUCCESS The new event log entry was added.\r
345 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
346\r
347**/\r
348EFI_STATUS\r
349EFIAPI\r
350TcgDxeLogEventI (\r
351 IN TCG_DXE_DATA *TcgData,\r
352 IN TCG_PCR_EVENT_HDR *NewEventHdr,\r
353 IN UINT8 *NewEventData\r
354 )\r
355{\r
356 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
357 TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgClientAcpiTable->Lasa;\r
358 return TpmCommLogEvent (\r
359 &TcgData->LastEvent,\r
360 &TcgData->EventLogSize,\r
361 (UINTN)TcgData->TcgClientAcpiTable->Laml,\r
362 NewEventHdr,\r
363 NewEventData\r
364 );\r
365 } else {\r
366 TcgData->LastEvent = (UINT8*)(UINTN)TcgData->TcgServerAcpiTable->Lasa;\r
367 return TpmCommLogEvent (\r
368 &TcgData->LastEvent,\r
369 &TcgData->EventLogSize,\r
370 (UINTN)TcgData->TcgServerAcpiTable->Laml,\r
371 NewEventHdr,\r
372 NewEventData\r
373 );\r
374 }\r
375}\r
376\r
377/**\r
378 This service abstracts the capability to add an entry to the Event Log.\r
379\r
380 @param[in] This Indicates the calling context\r
381 @param[in] TCGLogData Pointer to the start of the data buffer containing \r
382 the TCG_PCR_EVENT data structure. All fields in \r
383 this structure are properly filled by the caller.\r
384 @param[in, out] EventNumber The event number of the event just logged\r
385 @param[in] Flags Indicate additional flags. Only one flag has been \r
386 defined at this time, which is 0x01 and means the \r
387 extend operation should not be performed. All \r
388 other bits are reserved. \r
389 \r
390 @retval EFI_SUCCESS Operation completed successfully.\r
391 @retval EFI_OUT_OF_RESOURCES Insufficient memory in the event log to complete this action.\r
392 \r
393**/\r
394EFI_STATUS\r
395EFIAPI\r
396TcgDxeLogEvent (\r
397 IN EFI_TCG_PROTOCOL *This,\r
398 IN TCG_PCR_EVENT *TCGLogData,\r
399 IN OUT UINT32 *EventNumber,\r
400 IN UINT32 Flags\r
401 )\r
402{\r
403 TCG_DXE_DATA *TcgData;\r
404\r
677e5c0b 405 if (TCGLogData == NULL){\r
406 return EFI_INVALID_PARAMETER;\r
407 }\r
408\r
0c18794e 409 TcgData = TCG_DXE_DATA_FROM_THIS (This);\r
410 \r
5dbb6635 411 if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {\r
0c18794e 412 return EFI_DEVICE_ERROR;\r
413 }\r
414 return TcgDxeLogEventI (\r
415 TcgData,\r
416 (TCG_PCR_EVENT_HDR*)TCGLogData,\r
417 TCGLogData->Event\r
418 );\r
419}\r
420\r
421/**\r
422 This service is a proxy for commands to the TPM.\r
423\r
424 @param[in] This Indicates the calling context\r
425 @param[in] TpmInputParameterBlockSize Size of the TPM input parameter block\r
426 @param[in] TpmInputParameterBlock Pointer to the TPM input parameter block\r
427 @param[in] TpmOutputParameterBlockSize Size of the TPM output parameter block\r
428 @param[in] TpmOutputParameterBlock Pointer to the TPM output parameter block\r
429\r
430 @retval EFI_SUCCESS Operation completed successfully.\r
431 @retval EFI_INVALID_PARAMETER Invalid ordinal.\r
432 @retval EFI_UNSUPPORTED Current Task Priority Level >= EFI_TPL_CALLBACK.\r
433 @retval EFI_TIMEOUT The TIS timed-out.\r
434 \r
435**/\r
436EFI_STATUS\r
437EFIAPI\r
438TcgDxePassThroughToTpm (\r
439 IN EFI_TCG_PROTOCOL *This,\r
440 IN UINT32 TpmInputParameterBlockSize,\r
441 IN UINT8 *TpmInputParameterBlock,\r
442 IN UINT32 TpmOutputParameterBlockSize,\r
443 IN UINT8 *TpmOutputParameterBlock\r
444 )\r
445{\r
446 TCG_DXE_DATA *TcgData;\r
447\r
be02dcee 448 if (TpmInputParameterBlock == NULL || \r
449 TpmOutputParameterBlock == NULL || \r
450 TpmInputParameterBlockSize == 0 ||\r
451 TpmOutputParameterBlockSize == 0) {\r
452 return EFI_INVALID_PARAMETER;\r
453 }\r
454\r
0c18794e 455 TcgData = TCG_DXE_DATA_FROM_THIS (This);\r
456\r
457 return TisPcExecute (\r
458 TcgData->TpmHandle,\r
459 "%r%/%r",\r
460 TpmInputParameterBlock,\r
461 (UINTN) TpmInputParameterBlockSize,\r
462 TpmOutputParameterBlock,\r
463 (UINTN) TpmOutputParameterBlockSize\r
464 );\r
465}\r
466\r
467/**\r
468 Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,\r
469 and add an entry to the Event Log.\r
470\r
471 @param[in] TcgData TCG_DXE_DATA structure.\r
472 @param[in] HashData Physical address of the start of the data buffer \r
473 to be hashed, extended, and logged.\r
474 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
475 @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. \r
476 @param[in] NewEventData Pointer to the new event data. \r
477\r
478 @retval EFI_SUCCESS Operation completed successfully.\r
479 @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.\r
480 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
481\r
482**/\r
483EFI_STATUS\r
484EFIAPI\r
485TcgDxeHashLogExtendEventI (\r
486 IN TCG_DXE_DATA *TcgData,\r
487 IN UINT8 *HashData,\r
488 IN UINT64 HashDataLen,\r
489 IN OUT TCG_PCR_EVENT_HDR *NewEventHdr,\r
490 IN UINT8 *NewEventData\r
491 )\r
492{\r
493 EFI_STATUS Status;\r
494\r
6f785cfc
JY
495 if (!TcgData->BsCap.TPMPresentFlag) {\r
496 return EFI_DEVICE_ERROR;\r
677e5c0b 497 }\r
498\r
499 if (HashDataLen > 0 || HashData != NULL) {\r
0c18794e 500 Status = TpmCommHashAll (\r
501 HashData,\r
502 (UINTN) HashDataLen,\r
503 &NewEventHdr->Digest\r
504 );\r
f7fe68db
CZ
505 if (EFI_ERROR(Status)) {\r
506 DEBUG ((DEBUG_ERROR, "TpmCommHashAll Failed. %x\n", Status));\r
6f785cfc 507 goto Done;\r
f7fe68db 508 }\r
0c18794e 509 }\r
510\r
511 Status = TpmCommExtend (\r
512 TcgData->TpmHandle,\r
513 &NewEventHdr->Digest,\r
514 NewEventHdr->PCRIndex,\r
515 NULL\r
516 );\r
517 if (!EFI_ERROR (Status)) {\r
518 Status = TcgDxeLogEventI (TcgData, NewEventHdr, NewEventData);\r
519 }\r
520\r
6f785cfc
JY
521Done:\r
522 if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_TIMEOUT)) {\r
523 DEBUG ((EFI_D_ERROR, "TcgDxeHashLogExtendEventI - %r. Disable TPM.\n", Status));\r
524 TcgData->BsCap.TPMPresentFlag = FALSE;\r
525 REPORT_STATUS_CODE (\r
526 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
527 (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)\r
528 );\r
529 Status = EFI_DEVICE_ERROR;\r
530 }\r
531\r
0c18794e 532 return Status;\r
533}\r
534\r
535/**\r
536 This service abstracts the capability to do a hash operation on a data buffer,\r
537 extend a specific TPM PCR with the hash result, and add an entry to the Event Log\r
538\r
539 @param[in] This Indicates the calling context\r
540 @param[in] HashData Physical address of the start of the data buffer \r
541 to be hashed, extended, and logged.\r
542 @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData\r
543 @param[in] AlgorithmId Identification of the Algorithm to use for the hashing operation\r
544 @param[in, out] TCGLogData The physical address of the start of the data \r
545 buffer containing the TCG_PCR_EVENT data structure.\r
546 @param[in, out] EventNumber The event number of the event just logged.\r
547 @param[out] EventLogLastEntry Physical address of the first byte of the entry \r
548 just placed in the Event Log. If the Event Log was \r
549 empty when this function was called then this physical \r
550 address will be the same as the physical address of \r
551 the start of the Event Log.\r
552\r
553 @retval EFI_SUCCESS Operation completed successfully.\r
554 @retval EFI_UNSUPPORTED AlgorithmId != TPM_ALG_SHA.\r
555 @retval EFI_UNSUPPORTED Current TPL >= EFI_TPL_CALLBACK.\r
556 @retval EFI_DEVICE_ERROR The command was unsuccessful.\r
557 \r
558**/\r
559EFI_STATUS\r
560EFIAPI\r
561TcgDxeHashLogExtendEvent (\r
562 IN EFI_TCG_PROTOCOL *This,\r
563 IN EFI_PHYSICAL_ADDRESS HashData,\r
564 IN UINT64 HashDataLen,\r
565 IN TPM_ALGORITHM_ID AlgorithmId,\r
566 IN OUT TCG_PCR_EVENT *TCGLogData,\r
567 IN OUT UINT32 *EventNumber,\r
568 OUT EFI_PHYSICAL_ADDRESS *EventLogLastEntry\r
569 )\r
570{\r
571 TCG_DXE_DATA *TcgData;\r
15f2d739 572 EFI_STATUS Status;\r
0c18794e 573\r
677e5c0b 574 if (TCGLogData == NULL || EventLogLastEntry == NULL){\r
575 return EFI_INVALID_PARAMETER;\r
576 }\r
577\r
0c18794e 578 TcgData = TCG_DXE_DATA_FROM_THIS (This);\r
579 \r
5dbb6635 580 if (TcgData->BsCap.TPMDeactivatedFlag || (!TcgData->BsCap.TPMPresentFlag)) {\r
0c18794e 581 return EFI_DEVICE_ERROR;\r
582 }\r
583 \r
584 if (AlgorithmId != TPM_ALG_SHA) {\r
585 return EFI_UNSUPPORTED;\r
586 }\r
6f785cfc 587 \r
5dbb6635 588 if (HashData == 0 && HashDataLen > 0) {\r
6f785cfc
JY
589 return EFI_INVALID_PARAMETER;\r
590 }\r
0c18794e 591\r
15f2d739 592 Status = TcgDxeHashLogExtendEventI (\r
593 TcgData,\r
594 (UINT8 *) (UINTN) HashData,\r
595 HashDataLen,\r
596 (TCG_PCR_EVENT_HDR*)TCGLogData,\r
597 TCGLogData->Event\r
598 );\r
599\r
600 if (!EFI_ERROR(Status)){\r
601 *EventLogLastEntry = (EFI_PHYSICAL_ADDRESS)(UINTN) TcgData->LastEvent;\r
602 }\r
603\r
604 return Status;\r
0c18794e 605}\r
606\r
607TCG_DXE_DATA mTcgDxeData = {\r
608 {\r
609 TcgDxeStatusCheck,\r
610 TcgDxeHashAll,\r
611 TcgDxeLogEvent,\r
612 TcgDxePassThroughToTpm,\r
613 TcgDxeHashLogExtendEvent\r
614 },\r
615 {\r
616 sizeof (mTcgDxeData.BsCap),\r
617 { 1, 2, 0, 0 },\r
618 { 1, 2, 0, 0 },\r
619 1,\r
620 TRUE,\r
621 FALSE\r
622 },\r
623 &mTcgClientAcpiTemplate,\r
624 &mTcgServerAcpiTemplate,\r
625 0,\r
626 NULL,\r
627 NULL\r
628};\r
629\r
630/**\r
631 Initialize the Event Log and log events passed from the PEI phase.\r
632\r
633 @retval EFI_SUCCESS Operation completed successfully.\r
634 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
635\r
636**/\r
637EFI_STATUS\r
638EFIAPI\r
639SetupEventLog (\r
640 VOID\r
641 )\r
642{\r
643 EFI_STATUS Status;\r
644 TCG_PCR_EVENT *TcgEvent;\r
645 EFI_PEI_HOB_POINTERS GuidHob;\r
646 EFI_PHYSICAL_ADDRESS Lasa;\r
647 \r
648 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
649 Lasa = mTcgClientAcpiTemplate.Lasa;\r
650 \r
651 Status = gBS->AllocatePages (\r
652 AllocateMaxAddress,\r
653 EfiACPIMemoryNVS,\r
91e914f5 654 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
0c18794e 655 &Lasa\r
656 );\r
657 if (EFI_ERROR (Status)) {\r
658 return Status;\r
659 }\r
660 mTcgClientAcpiTemplate.Lasa = Lasa;\r
661 //\r
662 // To initialize them as 0xFF is recommended \r
663 // because the OS can know the last entry for that.\r
664 //\r
91e914f5
CZ
665 SetMem ((VOID *)(UINTN)mTcgClientAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
666 mTcgClientAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
0c18794e 667 \r
668 } else {\r
669 Lasa = mTcgServerAcpiTemplate.Lasa;\r
670 \r
671 Status = gBS->AllocatePages (\r
672 AllocateMaxAddress,\r
673 EfiACPIMemoryNVS,\r
91e914f5 674 EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)),\r
0c18794e 675 &Lasa\r
676 );\r
677 if (EFI_ERROR (Status)) {\r
678 return Status;\r
679 }\r
680 mTcgServerAcpiTemplate.Lasa = Lasa;\r
681 //\r
682 // To initialize them as 0xFF is recommended \r
683 // because the OS can know the last entry for that.\r
684 //\r
91e914f5
CZ
685 SetMem ((VOID *)(UINTN)mTcgServerAcpiTemplate.Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF);\r
686 mTcgServerAcpiTemplate.Laml = PcdGet32 (PcdTcgLogAreaMinLen);\r
0c18794e 687 }\r
688\r
689 GuidHob.Raw = GetHobList ();\r
690 while (!EFI_ERROR (Status) && \r
691 (GuidHob.Raw = GetNextGuidHob (&gTcgEventEntryHobGuid, GuidHob.Raw)) != NULL) {\r
692 TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid);\r
693 GuidHob.Raw = GET_NEXT_HOB (GuidHob);\r
694 Status = TcgDxeLogEventI (\r
695 &mTcgDxeData,\r
696 (TCG_PCR_EVENT_HDR*)TcgEvent,\r
697 TcgEvent->Event\r
698 );\r
699 }\r
700\r
701 return Status;\r
702}\r
703\r
704/**\r
705 Measure and log an action string, and extend the measurement result into PCR[5].\r
706\r
707 @param[in] String A specific string that indicates an Action event. \r
708 \r
709 @retval EFI_SUCCESS Operation completed successfully.\r
710 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
711\r
712**/\r
713EFI_STATUS\r
714EFIAPI\r
715TcgMeasureAction (\r
716 IN CHAR8 *String\r
717 )\r
718{\r
719 TCG_PCR_EVENT_HDR TcgEvent;\r
720\r
721 TcgEvent.PCRIndex = 5;\r
722 TcgEvent.EventType = EV_EFI_ACTION;\r
723 TcgEvent.EventSize = (UINT32)AsciiStrLen (String);\r
724 return TcgDxeHashLogExtendEventI (\r
725 &mTcgDxeData,\r
726 (UINT8*)String,\r
727 TcgEvent.EventSize,\r
728 &TcgEvent,\r
729 (UINT8 *) String\r
730 );\r
731}\r
732\r
733/**\r
734 Measure and log EFI handoff tables, and extend the measurement result into PCR[1].\r
735\r
736 @retval EFI_SUCCESS Operation completed successfully.\r
737 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
738\r
739**/\r
740EFI_STATUS\r
741EFIAPI\r
742MeasureHandoffTables (\r
743 VOID\r
744 )\r
745{\r
746 EFI_STATUS Status;\r
0c18794e 747 TCG_PCR_EVENT_HDR TcgEvent;\r
748 EFI_HANDOFF_TABLE_POINTERS HandoffTables;\r
b25380e3 749 UINTN ProcessorNum;\r
750 EFI_CPU_PHYSICAL_LOCATION *ProcessorLocBuf;\r
0c18794e 751\r
d4193108 752 ProcessorLocBuf = NULL;\r
d2de4483 753 Status = EFI_SUCCESS;\r
0c18794e 754\r
b25380e3 755 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) {\r
756 //\r
757 // Tcg Server spec. \r
758 // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1]\r
759 //\r
760 Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum);\r
761\r
762 if (!EFI_ERROR(Status)){\r
763 TcgEvent.PCRIndex = 1;\r
764 TcgEvent.EventType = EV_TABLE_OF_DEVICES;\r
765 TcgEvent.EventSize = sizeof (HandoffTables);\r
766\r
767 HandoffTables.NumberOfTables = 1;\r
768 HandoffTables.TableEntry[0].VendorGuid = gEfiMpServiceProtocolGuid;\r
769 HandoffTables.TableEntry[0].VendorTable = ProcessorLocBuf;\r
770\r
771 Status = TcgDxeHashLogExtendEventI (\r
772 &mTcgDxeData,\r
773 (UINT8*)(UINTN)ProcessorLocBuf,\r
774 sizeof(EFI_CPU_PHYSICAL_LOCATION) * ProcessorNum,\r
775 &TcgEvent,\r
776 (UINT8*)&HandoffTables\r
777 );\r
778\r
779 FreePool(ProcessorLocBuf);\r
780 }\r
781 }\r
782\r
0c18794e 783 return Status;\r
784}\r
785\r
786/**\r
787 Measure and log Separator event, and extend the measurement result into a specific PCR.\r
788\r
789 @param[in] PCRIndex PCR index. \r
790\r
791 @retval EFI_SUCCESS Operation completed successfully.\r
792 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
793\r
794**/\r
795EFI_STATUS\r
796EFIAPI\r
797MeasureSeparatorEvent (\r
798 IN TPM_PCRINDEX PCRIndex\r
799 )\r
800{\r
801 TCG_PCR_EVENT_HDR TcgEvent;\r
802 UINT32 EventData;\r
803\r
804 EventData = 0;\r
805 TcgEvent.PCRIndex = PCRIndex;\r
806 TcgEvent.EventType = EV_SEPARATOR;\r
807 TcgEvent.EventSize = (UINT32)sizeof (EventData);\r
808 return TcgDxeHashLogExtendEventI (\r
809 &mTcgDxeData,\r
810 (UINT8 *)&EventData,\r
811 sizeof (EventData),\r
812 &TcgEvent,\r
813 (UINT8 *)&EventData\r
814 );\r
815}\r
816\r
817/**\r
818 Read an EFI Variable.\r
819\r
820 This function allocates a buffer to return the contents of the variable. The caller is\r
821 responsible for freeing the buffer.\r
822\r
823 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
824 @param[in] VendorGuid A unique identifier for the vendor.\r
825 @param[out] VarSize The size of the variable data. \r
826\r
827 @return A pointer to the buffer to return the contents of the variable.Otherwise NULL.\r
828\r
829**/\r
830VOID *\r
831EFIAPI\r
832ReadVariable (\r
833 IN CHAR16 *VarName,\r
834 IN EFI_GUID *VendorGuid,\r
835 OUT UINTN *VarSize\r
836 )\r
837{\r
838 EFI_STATUS Status;\r
839 VOID *VarData;\r
840\r
841 *VarSize = 0;\r
842 Status = gRT->GetVariable (\r
843 VarName,\r
844 VendorGuid,\r
845 NULL,\r
846 VarSize,\r
847 NULL\r
848 );\r
849 if (Status != EFI_BUFFER_TOO_SMALL) {\r
850 return NULL;\r
851 }\r
852\r
853 VarData = AllocatePool (*VarSize);\r
854 if (VarData != NULL) {\r
855 Status = gRT->GetVariable (\r
856 VarName,\r
857 VendorGuid,\r
858 NULL,\r
859 VarSize,\r
860 VarData\r
861 );\r
862 if (EFI_ERROR (Status)) {\r
863 FreePool (VarData);\r
864 VarData = NULL;\r
865 *VarSize = 0;\r
866 }\r
867 }\r
868 return VarData;\r
869}\r
870\r
871/**\r
872 Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
873\r
874 @param[in] PCRIndex PCR Index. \r
875 @param[in] EventType Event type. \r
876 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
877 @param[in] VendorGuid A unique identifier for the vendor.\r
878 @param[in] VarData The content of the variable data. \r
879 @param[in] VarSize The size of the variable data. \r
880 \r
881 @retval EFI_SUCCESS Operation completed successfully.\r
882 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
883 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
884\r
885**/\r
886EFI_STATUS\r
887EFIAPI\r
888MeasureVariable (\r
889 IN TPM_PCRINDEX PCRIndex,\r
890 IN TCG_EVENTTYPE EventType,\r
891 IN CHAR16 *VarName,\r
892 IN EFI_GUID *VendorGuid,\r
893 IN VOID *VarData,\r
894 IN UINTN VarSize\r
895 )\r
896{\r
897 EFI_STATUS Status;\r
898 TCG_PCR_EVENT_HDR TcgEvent;\r
899 UINTN VarNameLength;\r
900 EFI_VARIABLE_DATA *VarLog;\r
901\r
902 VarNameLength = StrLen (VarName);\r
903 TcgEvent.PCRIndex = PCRIndex;\r
904 TcgEvent.EventType = EventType;\r
905 TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
906 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
907\r
908 VarLog = (EFI_VARIABLE_DATA*)AllocatePool (TcgEvent.EventSize);\r
909 if (VarLog == NULL) {\r
910 return EFI_OUT_OF_RESOURCES;\r
911 }\r
912\r
913 VarLog->VariableName = *VendorGuid;\r
914 VarLog->UnicodeNameLength = VarNameLength;\r
915 VarLog->VariableDataLength = VarSize;\r
916 CopyMem (\r
917 VarLog->UnicodeName,\r
918 VarName,\r
919 VarNameLength * sizeof (*VarName)\r
920 );\r
921 CopyMem (\r
922 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
923 VarData,\r
924 VarSize\r
925 );\r
926\r
927 Status = TcgDxeHashLogExtendEventI (\r
928 &mTcgDxeData,\r
36811012
CZ
929 (UINT8*)VarLog,\r
930 TcgEvent.EventSize,\r
0c18794e 931 &TcgEvent,\r
932 (UINT8*)VarLog\r
933 );\r
934 FreePool (VarLog);\r
935 return Status;\r
936}\r
937\r
938/**\r
939 Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5].\r
940\r
941 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
942 @param[in] VendorGuid A unique identifier for the vendor.\r
943 @param[out] VarSize The size of the variable data. \r
944 @param[out] VarData Pointer to the content of the variable. \r
945 \r
946 @retval EFI_SUCCESS Operation completed successfully.\r
947 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
948 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
949\r
950**/\r
951EFI_STATUS\r
952EFIAPI\r
953ReadAndMeasureBootVariable (\r
954 IN CHAR16 *VarName,\r
955 IN EFI_GUID *VendorGuid,\r
956 OUT UINTN *VarSize,\r
957 OUT VOID **VarData\r
958 )\r
959{\r
960 EFI_STATUS Status;\r
961\r
962 *VarData = ReadVariable (VarName, VendorGuid, VarSize);\r
963 if (*VarData == NULL) {\r
964 return EFI_NOT_FOUND;\r
965 }\r
966\r
967 Status = MeasureVariable (\r
968 5,\r
969 EV_EFI_VARIABLE_BOOT,\r
970 VarName,\r
971 VendorGuid,\r
972 *VarData,\r
973 *VarSize\r
974 );\r
975 return Status;\r
976}\r
977\r
978/**\r
979 Measure and log all EFI boot variables, and extend the measurement result into a specific PCR.\r
980\r
981 The EFI boot variables are BootOrder and Boot#### variables.\r
982\r
983 @retval EFI_SUCCESS Operation completed successfully.\r
984 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
985 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
986\r
987**/\r
988EFI_STATUS\r
989EFIAPI\r
990MeasureAllBootVariables (\r
991 VOID\r
992 )\r
993{\r
994 EFI_STATUS Status;\r
995 UINT16 *BootOrder;\r
996 UINTN BootCount;\r
997 UINTN Index;\r
998 VOID *BootVarData;\r
999 UINTN Size;\r
1000\r
1001 Status = ReadAndMeasureBootVariable (\r
1002 mBootVarName,\r
1003 &gEfiGlobalVariableGuid,\r
1004 &BootCount,\r
1005 (VOID **) &BootOrder\r
1006 );\r
61959fa9 1007 if (Status == EFI_NOT_FOUND || BootOrder == NULL) {\r
0c18794e 1008 return EFI_SUCCESS;\r
1009 }\r
0c18794e 1010\r
1011 if (EFI_ERROR (Status)) {\r
f7fe68db
CZ
1012 //\r
1013 // BootOrder can't be NULL if status is not EFI_NOT_FOUND\r
1014 //\r
0c18794e 1015 FreePool (BootOrder);\r
1016 return Status;\r
1017 }\r
1018\r
1019 BootCount /= sizeof (*BootOrder);\r
1020 for (Index = 0; Index < BootCount; Index++) {\r
1021 UnicodeSPrint (mBootVarName, sizeof (mBootVarName), L"Boot%04x", BootOrder[Index]);\r
1022 Status = ReadAndMeasureBootVariable (\r
1023 mBootVarName,\r
1024 &gEfiGlobalVariableGuid,\r
1025 &Size,\r
1026 &BootVarData\r
1027 );\r
1028 if (!EFI_ERROR (Status)) {\r
1029 FreePool (BootVarData);\r
1030 }\r
1031 }\r
1032\r
1033 FreePool (BootOrder);\r
1034 return EFI_SUCCESS;\r
1035}\r
1036\r
1037/**\r
1038 Ready to Boot Event notification handler.\r
1039\r
1040 Sequence of OS boot events is measured in this event notification handler.\r
1041\r
1042 @param[in] Event Event whose notification function is being invoked\r
1043 @param[in] Context Pointer to the notification function's context\r
1044\r
1045**/\r
1046VOID\r
1047EFIAPI\r
1048OnReadyToBoot (\r
1049 IN EFI_EVENT Event,\r
1050 IN VOID *Context\r
1051 )\r
1052{\r
1053 EFI_STATUS Status;\r
1054 TPM_PCRINDEX PcrIndex;\r
1055\r
1056 if (mBootAttempts == 0) {\r
1057\r
1058 //\r
1059 // Measure handoff tables.\r
1060 //\r
1061 Status = MeasureHandoffTables ();\r
1062 if (EFI_ERROR (Status)) {\r
1063 DEBUG ((EFI_D_ERROR, "HOBs not Measured. Error!\n"));\r
1064 }\r
1065\r
1066 //\r
1067 // Measure BootOrder & Boot#### variables.\r
1068 //\r
1069 Status = MeasureAllBootVariables ();\r
1070 if (EFI_ERROR (Status)) {\r
1071 DEBUG ((EFI_D_ERROR, "Boot Variables not Measured. Error!\n"));\r
1072 }\r
1073\r
1074 //\r
1075 // 1. This is the first boot attempt.\r
1076 //\r
1077 Status = TcgMeasureAction (\r
1078 EFI_CALLING_EFI_APPLICATION\r
1079 );\r
f7fe68db 1080 if (EFI_ERROR (Status)) {\r
655dabe3 1081 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION));\r
f7fe68db 1082 }\r
0c18794e 1083\r
1084 //\r
1085 // 2. Draw a line between pre-boot env and entering post-boot env.\r
1086 //\r
1087 for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) {\r
1088 Status = MeasureSeparatorEvent (PcrIndex);\r
f7fe68db
CZ
1089 if (EFI_ERROR (Status)) {\r
1090 DEBUG ((EFI_D_ERROR, "Seperator Event not Measured. Error!\n"));\r
1091 }\r
0c18794e 1092 }\r
1093\r
1094 //\r
1095 // 3. Measure GPT. It would be done in SAP driver.\r
1096 //\r
1097\r
1098 //\r
1099 // 4. Measure PE/COFF OS loader. It would be done in SAP driver.\r
1100 //\r
1101\r
1102 //\r
1103 // 5. Read & Measure variable. BootOrder already measured.\r
1104 //\r
1105 } else {\r
1106 //\r
1107 // 6. Not first attempt, meaning a return from last attempt\r
1108 //\r
1109 Status = TcgMeasureAction (\r
1110 EFI_RETURNING_FROM_EFI_APPLICATOIN\r
1111 );\r
f7fe68db 1112 if (EFI_ERROR (Status)) {\r
655dabe3 1113 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN));\r
f7fe68db 1114 }\r
0c18794e 1115 }\r
1116\r
1117 DEBUG ((EFI_D_INFO, "TPM TcgDxe Measure Data when ReadyToBoot\n"));\r
1118 //\r
1119 // Increase boot attempt counter.\r
1120 //\r
1121 mBootAttempts++;\r
1122}\r
1123\r
1124/**\r
1125 Install TCG ACPI Table when ACPI Table Protocol is available.\r
1126\r
0f7f6d23 1127 A system's firmware uses an ACPI table to identify the system's TCG capabilities \r
0c18794e 1128 to the Post-Boot environment. The information in this ACPI table is not guaranteed \r
1129 to be valid until the Host Platform transitions from pre-boot state to post-boot state. \r
1130\r
1131 @param[in] Event Event whose notification function is being invoked\r
1132 @param[in] Context Pointer to the notification function's context\r
1133**/\r
1134VOID\r
1135EFIAPI\r
1136InstallAcpiTable (\r
1137 IN EFI_EVENT Event,\r
1138 IN VOID* Context\r
1139 )\r
1140{\r
1141 UINTN TableKey;\r
1142 EFI_STATUS Status;\r
1143 EFI_ACPI_TABLE_PROTOCOL *AcpiTable;\r
1144 UINT8 Checksum;\r
e84f07b5 1145 UINT64 OemTableId;\r
0c18794e 1146\r
1147 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable);\r
1148 if (EFI_ERROR (Status)) {\r
1149 return;\r
1150 }\r
1151\r
1152 if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) {\r
e84f07b5
SZ
1153 CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId));\r
1154 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1155 CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1156 mTcgClientAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1157 mTcgClientAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1158 mTcgClientAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
0c18794e 1159 //\r
1160 // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
1161 // service of the ACPI table protocol to install it.\r
1162 //\r
1163 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate));\r
1164 mTcgClientAcpiTemplate.Header.Checksum = Checksum;\r
1165\r
1166 Status = AcpiTable->InstallAcpiTable (\r
1167 AcpiTable,\r
1168 &mTcgClientAcpiTemplate,\r
1169 sizeof (mTcgClientAcpiTemplate),\r
1170 &TableKey\r
1171 );\r
1172 } else {\r
e84f07b5
SZ
1173 CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId));\r
1174 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
1175 CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
1176 mTcgServerAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
1177 mTcgServerAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
1178 mTcgServerAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
0c18794e 1179 //\r
1180 // The ACPI table must be checksumed before calling the InstallAcpiTable() \r
1181 // service of the ACPI table protocol to install it.\r
1182 //\r
1183 Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate));\r
1184 mTcgServerAcpiTemplate.Header.Checksum = Checksum;\r
1185\r
1186 Status = AcpiTable->InstallAcpiTable (\r
1187 AcpiTable,\r
1188 &mTcgServerAcpiTemplate,\r
1189 sizeof (mTcgServerAcpiTemplate),\r
1190 &TableKey\r
1191 );\r
1192 }\r
f7fe68db
CZ
1193\r
1194 if (EFI_ERROR (Status)) {\r
1195 DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure"));\r
1196 }\r
0c18794e 1197}\r
1198\r
1199/**\r
1200 Exit Boot Services Event notification handler.\r
1201\r
1202 Measure invocation and success of ExitBootServices.\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
1207**/\r
1208VOID\r
1209EFIAPI\r
1210OnExitBootServices (\r
1211 IN EFI_EVENT Event,\r
1212 IN VOID *Context\r
1213 )\r
1214{\r
1215 EFI_STATUS Status;\r
1216\r
1217 //\r
1218 // Measure invocation of ExitBootServices,\r
1219 //\r
1220 Status = TcgMeasureAction (\r
1221 EFI_EXIT_BOOT_SERVICES_INVOCATION\r
1222 );\r
f7fe68db 1223 if (EFI_ERROR (Status)) {\r
655dabe3 1224 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_INVOCATION));\r
f7fe68db 1225 }\r
0c18794e 1226\r
1227 //\r
1228 // Measure success of ExitBootServices\r
1229 //\r
1230 Status = TcgMeasureAction (\r
1231 EFI_EXIT_BOOT_SERVICES_SUCCEEDED\r
1232 );\r
f7fe68db 1233 if (EFI_ERROR (Status)){\r
655dabe3 1234 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_SUCCEEDED));\r
f7fe68db 1235 }\r
0c18794e 1236}\r
1237\r
9e945f78 1238/**\r
1239 Exit Boot Services Failed Event notification handler.\r
1240\r
1241 Measure Failure of ExitBootServices.\r
1242\r
1243 @param[in] Event Event whose notification function is being invoked\r
1244 @param[in] Context Pointer to the notification function's context\r
1245\r
1246**/\r
1247VOID\r
1248EFIAPI\r
1249OnExitBootServicesFailed (\r
1250 IN EFI_EVENT Event,\r
1251 IN VOID *Context\r
1252 )\r
1253{\r
1254 EFI_STATUS Status;\r
1255\r
1256 //\r
1257 // Measure Failure of ExitBootServices,\r
1258 //\r
1259 Status = TcgMeasureAction (\r
1260 EFI_EXIT_BOOT_SERVICES_FAILED\r
1261 );\r
f7fe68db 1262 if (EFI_ERROR (Status)){\r
655dabe3 1263 DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_EXIT_BOOT_SERVICES_FAILED));\r
f7fe68db 1264 }\r
9e945f78 1265}\r
1266\r
0c18794e 1267/**\r
1268 Get TPM Deactivated state.\r
1269\r
1270 @param[out] TPMDeactivatedFlag Returns TPM Deactivated state. \r
1271\r
1272 @retval EFI_SUCCESS Operation completed successfully.\r
1273 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
1274\r
1275**/\r
1276EFI_STATUS\r
1277GetTpmStatus (\r
1278 OUT BOOLEAN *TPMDeactivatedFlag\r
1279 )\r
1280{\r
1281 EFI_STATUS Status;\r
1282 TPM_STCLEAR_FLAGS VFlags;\r
1283\r
1284 Status = TpmCommGetFlags (\r
1285 mTcgDxeData.TpmHandle,\r
1286 TPM_CAP_FLAG_VOLATILE,\r
1287 &VFlags,\r
1288 sizeof (VFlags)\r
1289 );\r
1290 if (!EFI_ERROR (Status)) {\r
1291 *TPMDeactivatedFlag = VFlags.deactivated;\r
1292 }\r
1293\r
1294 return Status;\r
1295}\r
1296\r
1297/**\r
1298 The driver's entry point.\r
1299\r
1300 It publishes EFI TCG Protocol.\r
1301\r
1302 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
1303 @param[in] SystemTable A pointer to the EFI System Table.\r
1304 \r
1305 @retval EFI_SUCCESS The entry point is executed successfully.\r
1306 @retval other Some error occurs when executing this entry point.\r
1307\r
1308**/\r
1309EFI_STATUS\r
1310EFIAPI\r
1311DriverEntry (\r
1312 IN EFI_HANDLE ImageHandle,\r
1313 IN EFI_SYSTEM_TABLE *SystemTable\r
1314 )\r
1315{\r
1316 EFI_STATUS Status;\r
1317 EFI_EVENT Event;\r
1318 VOID *Registration;\r
1319\r
c1d93242
JY
1320 if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){\r
1321 DEBUG ((EFI_D_ERROR, "No TPM12 instance required!\n"));\r
1322 return EFI_UNSUPPORTED;\r
1323 }\r
1324\r
3dd05ac3
JY
1325 if (GetFirstGuidHob (&gTpmErrorHobGuid) != NULL) {\r
1326 DEBUG ((EFI_D_ERROR, "TPM error!\n"));\r
1327 return EFI_DEVICE_ERROR;\r
1328 }\r
1329\r
0c18794e 1330 mTcgDxeData.TpmHandle = (TIS_TPM_HANDLE)(UINTN)TPM_BASE_ADDRESS;\r
1331 Status = TisPcRequestUseTpm (mTcgDxeData.TpmHandle);\r
1332 if (EFI_ERROR (Status)) {\r
1333 DEBUG ((EFI_D_ERROR, "TPM not detected!\n"));\r
1334 return Status;\r
1335 }\r
1336\r
1337 Status = GetTpmStatus (&mTcgDxeData.BsCap.TPMDeactivatedFlag);\r
1338 if (EFI_ERROR (Status)) {\r
1339 DEBUG ((\r
1340 EFI_D_ERROR,\r
1341 "Line %d in file " __FILE__ ":\n "\r
1342 "DriverEntry: TPM not working properly\n",\r
1343 __LINE__\r
1344 ));\r
1345 return Status;\r
1346 }\r
1347\r
1348 Status = gBS->InstallProtocolInterface (\r
1349 &ImageHandle,\r
1350 &gEfiTcgProtocolGuid,\r
1351 EFI_NATIVE_INTERFACE,\r
1352 &mTcgDxeData.TcgProtocol\r
1353 );\r
5dbb6635 1354 if (!EFI_ERROR (Status) && (!mTcgDxeData.BsCap.TPMDeactivatedFlag) && mTcgDxeData.BsCap.TPMPresentFlag) {\r
0c18794e 1355 //\r
1356 // Setup the log area and copy event log from hob list to it\r
1357 //\r
1358 Status = SetupEventLog ();\r
1359 ASSERT_EFI_ERROR (Status);\r
1360\r
1361 //\r
1362 // Measure handoff tables, Boot#### variables etc.\r
1363 //\r
1364 Status = EfiCreateEventReadyToBootEx (\r
1365 TPL_CALLBACK,\r
1366 OnReadyToBoot,\r
1367 NULL,\r
1368 &Event\r
1369 );\r
1370\r
1371 Status = gBS->CreateEventEx (\r
1372 EVT_NOTIFY_SIGNAL,\r
1373 TPL_NOTIFY,\r
1374 OnExitBootServices,\r
1375 NULL,\r
1376 &gEfiEventExitBootServicesGuid,\r
1377 &Event\r
1378 );\r
9e945f78 1379\r
1380 //\r
1381 // Measure Exit Boot Service failed \r
1382 //\r
1383 Status = gBS->CreateEventEx (\r
1384 EVT_NOTIFY_SIGNAL,\r
1385 TPL_NOTIFY,\r
1386 OnExitBootServicesFailed,\r
1387 NULL,\r
1388 &gEventExitBootServicesFailedGuid,\r
1389 &Event\r
1390 );\r
0c18794e 1391 }\r
1392\r
627c3961 1393 //\r
1394 // Install ACPI Table\r
1395 //\r
1396 EfiCreateProtocolNotifyEvent (&gEfiAcpiTableProtocolGuid, TPL_CALLBACK, InstallAcpiTable, NULL, &Registration);\r
1397 \r
0c18794e 1398 return Status;\r
1399}\r