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