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