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