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