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