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