diff options
Diffstat (limited to 'Board/EM/TCG2/Common/Tpm20PlatformDxe.c')
-rw-r--r-- | Board/EM/TCG2/Common/Tpm20PlatformDxe.c | 2508 |
1 files changed, 2508 insertions, 0 deletions
diff --git a/Board/EM/TCG2/Common/Tpm20PlatformDxe.c b/Board/EM/TCG2/Common/Tpm20PlatformDxe.c new file mode 100644 index 0000000..cf35e7f --- /dev/null +++ b/Board/EM/TCG2/Common/Tpm20PlatformDxe.c @@ -0,0 +1,2508 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//************************************************************************* +// $Header: /Alaska/SOURCE/Modules/TCG2/Common/Tpm20PlatformDxe/Tpm20PlatformDxe.c 4 6/14/14 12:39a Fredericko $ +// +// $Revision: 4 $ +// +// $Date: 6/14/14 12:39a $ +//************************************************************************* +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/TCG2/Common/Tpm20PlatformDxe/Tpm20PlatformDxe.c $ +// +// 4 6/14/14 12:39a Fredericko +// +// 3 6/09/14 5:02p Fredericko +// Changes for SetVariable vulnerability during Runtime +// +// 2 4/25/14 4:44p Fredericko +// when secureboot is disabled +// +// 1 4/21/14 2:18p Fredericko +// +// 5 3/17/14 3:26p Fredericko +// +// 4 3/14/14 3:48p Fredericko +// +// 3 3/11/14 6:49p Fredericko +// [TAG] EIP151925 +// [Category] New Feature +// [Description] Changes for TcgGeneric Regression Testing +// +// 2 10/09/13 6:32p Fredericko +// +// 1 10/08/13 12:06p Fredericko +// Initial Check-In for Tpm-Next module +// +// 5 10/03/13 2:52p Fredericko +// +// 4 9/16/13 1:37p Fredericko +// TPM 2.0 UEFI preboot fixes. +// +// 3 8/30/13 11:03p Fredericko +// +// 2 7/11/13 6:16p Fredericko +// [TAG] EIP120969 +// [Category] New Feature +// [Description] TCG (TPM20). +// +// 1 7/10/13 5:57p Fredericko +// [TAG] EIP120969 +// [Category] New Feature +// [Description] TCG (TPM20) +// +//************************************************************************* +//<AMI_FHDR_START> +// +// Name: +// +// Description: +// +//<AMI_FHDR_END> +//************************************************************************* +#include "Tpm20PlatformDxe.h" +#include <ImageAuthentication.h> +#include <EfiImage.h> +#include <DevicePath.h> +#include <Smbios.h> +#include <DiskIo.h> +#include <BlockIo.h> +#include "Protocol/CpuIo.h" +#include "Protocol/FirmwareVolume.h" +#include "Protocol/DevicePath.h" +#include "AMIPostMgr.h" +#include "Tpm20PlatformDxeStrTokens.h" +#include "TcgPlatformSetupPolicy.h" + +#pragma optimize("",off) + +#if (defined(TCGMeasureSecureBootVariables) && (TCGMeasureSecureBootVariables != 0)) +EFI_GUID gEfiImageSecurityDatabaseguid = EFI_IMAGE_SECURITY_DATABASE_GUID; +#endif +EFI_GUID AmitcgefiOsVariableGuid = AMI_TCG_EFI_OS_VARIABLE_GUID; + +#define AMI_VALID_BOOT_IMAGE_CERT_TBL_GUID \ + { 0x6683D10C, 0xCF6E, 0x4914, 0xB5, 0xB4, 0xAB, 0x8E, 0xD7, 0x37, 0x0E, 0xD7 } + +#define BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID \ + {0xdbc9fd21, 0xfad8, 0x45b0, 0x9e, 0x78, 0x27, 0x15, 0x88, 0x67, 0xcc, 0x93} + +EFI_GUID gBdsAllDriversConnectedProtocolGuid = BDS_ALL_DRIVERS_CONNECTED_PROTOCOL_GUID; +EFI_GUID gAmiPostManagerProtocolGuid = AMI_POST_MANAGER_PROTOCOL_GUID; + +EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; + +EFI_GUID ZeroGuid = {0,0,0,0,0,0,0,0,0,0,0}; + +EFI_GUID gEfiSmbiosTableGuid = EFI_SMBIOS_TABLE_GUID; +EFI_GUID FlagsStatusguid = AMI_TCG_CONFIRMATION_FLAGS_GUID; + +UINTN mMeasureGptCount = 0; +EFI_TREE_PROTOCOL *TrEEProtocolInstance = NULL; +static UINT8 PpiRequest; + +EFI_HII_HANDLE gHiiHandle; +AMI_POST_MANAGER_PROTOCOL *pAmiPostMgr = NULL; +EFI_HANDLE PlatformProtocolHandle; +static PERSISTENT_BIOS_TPM_FLAGS TpmNvflags; + +#pragma pack (1) +typedef struct +{ + EFI_PHYSICAL_ADDRESS PostCodeAddress; + #if x64_BUILD + UINT64 PostCodeLength; + #else + UINTN PostCodeLength; + #endif +} EFI_TCG_EV_POST_CODE; + +typedef struct +{ + EFI_TCG_PCR_EVENT_HEADER Header; + EFI_TCG_EV_POST_CODE Event; +} PEI_EFI_POST_CODE; +#pragma pack() + +BOOLEAN CompareGuid( + EFI_GUID *G1, + EFI_GUID *G2 ); + +// +// +// Data Table definition +// +typedef struct _AMI_VALID_CERT_IN_SIG_DB { + UINT32 SigOffset; + UINT32 SigLength; +} AMI_VALID_CERT_IN_SIG_DB; + + +typedef struct _AMI_INTERNAL_HLXE_PROTOCOL AMI_INTERNAL_HLXE_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI * INTERNAL_HASH_LOG_EXTEND_EVENT) ( + IN UINT8 *DataToHash, + IN UINT64 Flags, + IN UINTN DataSize, + IN OUT TCG_PCR_EVENT_HDR *NewEventHdr, + IN UINT8 *NewEventData +); + + +struct _AMI_INTERNAL_HLXE_PROTOCOL { + INTERNAL_HASH_LOG_EXTEND_EVENT InternalHashLogExtend; +}; + +EFI_STATUS EfiGetSystemConfigurationTable( + IN EFI_GUID *TableGuid, + OUT VOID **Table) +{ + *Table = GetEfiConfigurationTable(pST, TableGuid); + return (*Table == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +GetRandomAuthPassword( + IN UINT16 RNGValueLength, + IN OUT UINT8 *RNGValue + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + return Status; +} + + +EFI_STATUS +EFIAPI +TpmRevokeTrust ( + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + return Status; +} + + +#define GET_HOB_TYPE( Hob ) ((Hob).Header->HobType) +#define GET_HOB_LENGTH( Hob ) ((Hob).Header->HobLength) +#define GET_NEXT_HOB( Hob ) ((Hob).Raw + GET_HOB_LENGTH( Hob )) +#define END_OF_HOB_LIST( Hob ) (GET_HOB_TYPE( Hob ) == \ + EFI_HOB_TYPE_END_OF_HOB_LIST) + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: GetHob +// +// Description: Find instance of a HOB type in a HOB list +// +// +// Input: IN UINT16 Type, +// IN VOID *HobStart +// +// Output: VOID* +// +// Modified: +// +// Referrals: +// +// Notes: +//<AMI_PHDR_END> +//********************************************************************** +VOID* GetHob( + IN UINT16 Type, + IN VOID *HobStart ) +{ + EFI_PEI_HOB_POINTERS Hob; + + Hob.Raw = HobStart; + + // + // Return input if not found + // + if ( HobStart == NULL ) + { + return HobStart; + } + + // + // Parse the HOB list, stop if end of list or matching type found. + // + while ( !END_OF_HOB_LIST( Hob )) + { + if ( Hob.Header->HobType == Type ) + { + break; + } + + Hob.Raw = GET_NEXT_HOB( Hob ); + } + + // + // Return input if not found + // + if ( END_OF_HOB_LIST( Hob )) + { + return HobStart; + } + + return (VOID*)(Hob.Raw); +} + + + +EFI_STATUS +MeasureSeparatorEvent ( + IN UINT32 PCRIndex +) +{ + UINT32 EventData; + TrEE_EVENT *Tpm20Event=NULL; + UINT64 Flags = 0; + EFI_STATUS Status; + + if(TrEEProtocolInstance == NULL) return EFI_NOT_FOUND; + + pBS->AllocatePool(EfiBootServicesData, (sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + sizeof(UINT32)), &Tpm20Event); + + if(Tpm20Event==NULL) return EFI_OUT_OF_RESOURCES; + + EventData = 0; + Tpm20Event->Size = sizeof(TrEE_EVENT_HEADER) + sizeof(UINT32) + sizeof(EventData); + Tpm20Event->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); + Tpm20Event->Header.HeaderVersion = 1; + Tpm20Event->Header.PCRIndex = PCRIndex; + Tpm20Event->Header.EventType = EV_SEPARATOR; + + pBS->CopyMem ((UINT32 *)((UINTN)&Tpm20Event->Event[0]), + &EventData, + sizeof(UINT32)); + + Status = TrEEProtocolInstance->HashLogExtendEvent(TrEEProtocolInstance, + Flags, (EFI_PHYSICAL_ADDRESS)&EventData, (UINT64)sizeof(EventData), + Tpm20Event); + + pBS->FreePool(Tpm20Event); + + return Status; +} + + + +#if (defined(TCGMeasureSecureBootVariables) && (TCGMeasureSecureBootVariables != 0)) +EFI_STATUS +MeasureCertificate(UINTN sizeOfCertificate, + UINT8 *pterCertificate) +{ + EFI_STATUS Status; + TrEE_EVENT *Tcg20Event; + EFI_VARIABLE_DATA *VarLog = NULL; + BOOLEAN AlreadyMeasuredCert = FALSE; + UINTN i=0; + UINTN VarNameLength; + static BOOLEAN initialized = 0; + static TPM_DIGEST digestTrackingArray[5]; + static TPM_DIGEST zeroDigest; + UINT8 *tempDigest = NULL; + UINT64 HashedDataLen = 20; + SHA1_CTX Sha1Ctx; + TCG_DIGEST *Sha1Digest = NULL; + UINT64 Flags = 0; + UINT32 EventSize = 0; + UINT8 *EventDataPtr; + + if(TrEEProtocolInstance == NULL) return EFI_NOT_FOUND; + + VarNameLength = Wcslen(L"db"); + + EventSize = (UINT32)( sizeof (*VarLog) + VarNameLength + * sizeof (CHAR16) + sizeOfCertificate) - 3; + + pBS->AllocatePool(EfiBootServicesData, (sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + EventSize), &Tcg20Event); + + if(Tcg20Event==NULL) return EFI_OUT_OF_RESOURCES; + + if(!initialized) + { + for(i=0;i<5; i++) + { + pBS->SetMem(digestTrackingArray[i].digest,20, 0); + } + pBS->SetMem(zeroDigest.digest,20, 0); + initialized = TRUE; + } + + Tcg20Event->Size = sizeof(TrEE_EVENT_HEADER) + sizeof(UINT32) + EventSize; + Tcg20Event->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); + Tcg20Event->Header.HeaderVersion = 1; + Tcg20Event->Header.PCRIndex = 7; + Tcg20Event->Header.EventType = 0x800000E0; + + Status = pBS->AllocatePool(EfiBootServicesData, EventSize, &VarLog); + + if ( VarLog == NULL ){ + return EFI_OUT_OF_RESOURCES; + } + + VarLog->VariableName = gEfiImageSecurityDatabaseGuid; + VarLog->UnicodeNameLength = VarNameLength; + VarLog->VariableDataLength = sizeOfCertificate; + + pBS->CopyMem((CHAR16*)(VarLog->UnicodeName), + L"db", + VarNameLength * sizeof (CHAR16)); + + pBS->CopyMem((CHAR16*)(VarLog->UnicodeName) + VarNameLength, + pterCertificate, + sizeOfCertificate); + + //before extending verify if we have already measured it. + SHA1Init(&Sha1Ctx); + + SHA1Update(&Sha1Ctx, + VarLog, + (u32)EventSize); + + SHA1Final((unsigned char *)&Sha1Digest->digest, &Sha1Ctx); + + for(i=0; i<5; i++) + { + //tempDigest + if(!MemCmp(digestTrackingArray[i].digest, Sha1Digest, 20)) + return EFI_SUCCESS; //already measured + + if(!MemCmp(digestTrackingArray[i].digest, zeroDigest.digest, 20)) + break; //we need to measure + } + + pBS->CopyMem(digestTrackingArray[i].digest, Sha1Digest, 20); + + EventDataPtr = (UINT8 *)Tcg20Event; + + EventDataPtr += sizeof(TrEE_EVENT_HEADER) + sizeof(UINT32); + + pBS->CopyMem(EventDataPtr, VarLog, EventSize); + + Status = TrEEProtocolInstance->HashLogExtendEvent(TrEEProtocolInstance, + Flags, (EFI_PHYSICAL_ADDRESS)(UINT8 *)(UINTN)VarLog, (UINT64)EventSize, + Tcg20Event); + return Status; +} +#endif + + + +#if (defined(TCGMeasureSecureBootVariables) && (TCGMeasureSecureBootVariables != 0)) +EFI_STATUS FindandMeasureSecureBootCertificate() +{ + EFI_STATUS Status; + UINTN VarSize = 0; + UINTN i=0; + UINT8 *SecureDBBuffer = NULL; + UINT8 *CertificateBuffer = NULL; + UINTN SizeofCerificate = 0; + EFI_GUID Certificateguid = AMI_VALID_BOOT_IMAGE_CERT_TBL_GUID; + AMI_VALID_CERT_IN_SIG_DB *CertInfo; + UINT8 *CertOffsetPtr = NULL; + + VarSize = 0; + + Status = pRS->GetVariable(L"db", + &gEfiImageSecurityDatabaseGuid, + NULL, + &VarSize, + NULL); + + if ( Status != EFI_BUFFER_TOO_SMALL ) + { + return EFI_NOT_FOUND; + } + + Status = pBS->AllocatePool(EfiBootServicesData, VarSize, &SecureDBBuffer); + + if ( SecureDBBuffer != NULL ) + { + Status = pRS->GetVariable(L"db", + &gEfiImageSecurityDatabaseGuid, + NULL, + &VarSize, + SecureDBBuffer); + + if ( EFI_ERROR( Status )) + { + pBS->FreePool( SecureDBBuffer ); + SecureDBBuffer = NULL; + return EFI_NOT_FOUND; + } + }else{ + return EFI_OUT_OF_RESOURCES; + } + + //we need to find the pointer in the EFI system table and work from + //there + CertInfo = NULL; + EfiGetSystemConfigurationTable(&Certificateguid, &CertInfo ); + if(CertInfo == NULL){ + return EFI_NOT_FOUND; + } + if(CertInfo->SigLength == 0){ + return EFI_NOT_READY; + } + + CertOffsetPtr = NULL; + CertOffsetPtr = (SecureDBBuffer + CertInfo->SigOffset); + MeasureCertificate((UINTN)CertInfo->SigLength,CertOffsetPtr); + + if(SecureDBBuffer!=NULL){ + pBS->FreePool( SecureDBBuffer ); + } + + return Status; +} +#endif + + +UINTN Tpm20AsciiStrLen ( + IN CHAR8 *String) +{ + UINTN Length; + for (Length = 0; *String != '\0'; String++, Length++); + return Length; +} + + + +EFI_STATUS +EFIAPI +MeasureAction ( + IN CHAR8 *String +) +{ + TCG_PCR_EVENT_HDR TcgEvent; + AMI_INTERNAL_HLXE_PROTOCOL *InternalHLXE = NULL; + EFI_GUID gEfiAmiHLXEGuid = AMI_PROTOCOL_INTERNAL_HLXE_GUID; + EFI_STATUS Status; + + TcgEvent.PCRIndex = 5; + TcgEvent.EventType = EV_EFI_ACTION; + TcgEvent.EventSize = (UINT32)Tpm20AsciiStrLen (String); + + Status = pBS->LocateProtocol(&gEfiAmiHLXEGuid, NULL, &InternalHLXE); + if(EFI_ERROR(Status))return Status; + + Status = InternalHLXE->InternalHashLogExtend((UINT8*)String, 0, TcgEvent.EventSize, &TcgEvent, (UINT8*)String); + return Status; +} + + + + + +EFI_STATUS +EFIAPI +TreeMeasurePeImage ( + IN BOOLEAN BootPolicy, + IN EFI_PHYSICAL_ADDRESS ImageAddress, + IN UINTN ImageSize, + IN UINTN LinkTimeBase, + IN UINT16 ImageType, + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + + EFI_STATUS Status; + TCG_PCR_EVENT_HDR TcgEvent; + UINT8 *EventData = NULL; + EFI_IMAGE_LOAD_EVENT *ImageLoad; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FullPath; + UINT32 FullPathSize; + SHA1_CTX Sha1Ctx; + EFI_IMAGE_DOS_HEADER *DosHdr; + UINT32 PeCoffHeaderOffset; + EFI_IMAGE_NT_HEADERS64 *Hdr; + EFI_IMAGE_SECTION_HEADER *Section; + UINT8 *HashBase; + UINTN HashSize; + UINTN SumOfBytesHashed; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN Index, iPos; + TCG_DIGEST Sha1Digest; + AMI_INTERNAL_HLXE_PROTOCOL *InternalHLXE = NULL; + EFI_GUID gEfiAmiHLXEGuid = AMI_PROTOCOL_INTERNAL_HLXE_GUID; + TCG_PLATFORM_SETUP_PROTOCOL *ProtocolInstance; + EFI_GUID Policyguid = TCG_PLATFORM_SETUP_POLICY_GUID; + SHA2_CTX Sha2Ctx; +// unsigned char Sha2DigestArray[32]; + UINT8 HashPolicy; + + + Status = pBS->LocateProtocol (&Policyguid, NULL, &ProtocolInstance); + if (EFI_ERROR (Status)) { + return 0; + } + + HashPolicy = ProtocolInstance->ConfigFlags.Reserved1; + + + ImageLoad = NULL; + FullPath = NULL; + SectionHeader = NULL; + FullPathSize = 0; + + TRACE ((TRACE_ALWAYS, "TreeMeasurePeImage Entry\n")); + + if (DeviceHandle != NULL) { + // + // Skip images loaded from FVs + // + Status = pBS->OpenProtocol ( + DeviceHandle, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + goto Done; + } + ASSERT (Status == EFI_UNSUPPORTED); + + // + // Get device path for the device handle + // + Status = pBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + &DevicePath + ); + if (EFI_ERROR (Status)) { + FullPathSize = (UINT32)DPLength (FullPath); + }else{ + FullPath = DPAdd (DevicePath, FilePath); + FullPathSize = (UINT32)DPLength (FullPath); + } + } + + //Allocate Event log memory + Status = pBS ->AllocatePool(EfiBootServicesData, ((sizeof (*ImageLoad) + - sizeof (ImageLoad->DevicePath)) + FullPathSize), &EventData); + + if(EFI_ERROR(Status))return Status; + // + // Determine destination PCR by BootPolicy + // + TcgEvent.EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath); + TcgEvent.EventSize += FullPathSize; + + switch (ImageType) { + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + TcgEvent.PCRIndex = 4; + TcgEvent.EventType = EV_EFI_BOOT_SERVICES_APPLICATION; + break; + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + TcgEvent.PCRIndex = 2; + TcgEvent.EventType = EV_EFI_BOOT_SERVICES_DRIVER; + goto Done; + break; + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + TcgEvent.PCRIndex = 2; + TcgEvent.EventType = EV_EFI_RUNTIME_SERVICES_DRIVER; + goto Done; + break; + default: + TcgEvent.EventType = ImageType; + Status = EFI_UNSUPPORTED; + goto Done; + } + + PERF_START(0,L"MeasurePeImg",NULL,0); + + Status = pBS ->AllocatePool(EfiBootServicesData,TcgEvent.EventSize, &ImageLoad); + + if (ImageLoad == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + ImageLoad->ImageLocationInMemory = ImageAddress; + ImageLoad->ImageLengthInMemory = ImageSize; + ImageLoad->ImageLinkTimeAddress = LinkTimeBase; + ImageLoad->LengthOfDevicePath = FullPathSize; + pBS->CopyMem( ImageLoad->DevicePath, FullPath, FullPathSize ); + + // + // Check PE/COFF image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress; + PeCoffHeaderOffset = 0; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + PeCoffHeaderOffset = DosHdr->e_lfanew; + } + if (((EFI_TE_IMAGE_HEADER *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset))->Signature + == EFI_TE_IMAGE_HEADER_SIGNATURE) { + goto Done; + } + + // + // PE/COFF Image Measurement + // + // NOTE: The following codes/steps are based upon the authenticode image hashing in + // PE/COFF Specification 8.0 Appendix A. + // + // + + // 1. Load the image header into memory. + + // 2. Initialize a SHA hash context. + if(HashPolicy == 0){ SHA1Init(&Sha1Ctx);} + else if(HashPolicy == 1){sha256_init( &Sha2Ctx );}; + + + // + // Measuring PE/COFF Image Header; + // But CheckSum field and SECURITY data directory (certificate) are excluded + // + Hdr = (EFI_IMAGE_NT_HEADERS *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset); + + // + // 3. Calculate the distance from the base of the image header to the image checksum address. + // 4. Hash the image header from its base to beginning of the image checksum. + // + HashBase = (UINT8 *)(UINTN)ImageAddress; + HashSize = (UINTN) ((UINT8 *)(&Hdr->OptionalHeader.CheckSum) - HashBase); + if(HashPolicy == 0){ + SHA1Update(&Sha1Ctx, + HashBase, + (u32)HashSize); + }else if(HashPolicy == 1){ + sha256_process( &Sha2Ctx, HashBase, (u32)HashSize ); + } + + + + // + // 5. Skip over the image checksum (it occupies a single ULONG). + // 6. Get the address of the beginning of the Cert Directory. + // 7. Hash everything from the end of the checksum to the start of the Cert Directory. + // + HashBase = (UINT8 *) &Hdr->OptionalHeader.CheckSum + sizeof (UINT32); + HashSize = (UINTN) ((UINT8 *)(&Hdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + + if(HashPolicy == 0){ + SHA1Update(&Sha1Ctx, + HashBase, + (u32)HashSize); + }else if(HashPolicy == 1){ + sha256_process( &Sha2Ctx, HashBase, (u32)HashSize ); + } + + // + // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) + // 9. Hash everything from the end of the Cert Directory to the end of image header. + // + HashBase = (UINT8 *) &Hdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; + HashSize = Hdr->OptionalHeader.SizeOfHeaders - + (UINTN) ((UINT8 *)(&Hdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *)(UINTN)ImageAddress); + + if(HashPolicy == 0){ + SHA1Update(&Sha1Ctx, + HashBase, + (u32)HashSize); + }else if(HashPolicy == 1){ + sha256_process( &Sha2Ctx, HashBase, (u32)HashSize ); + } + + + // + // 10. Set the SUM_OF_BYTES_HASHED to the size of the header + // + SumOfBytesHashed = Hdr->OptionalHeader.SizeOfHeaders; + + // + // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER + // structures in the image. The 'NumberOfSections' field of the image + // header indicates how big the table should be. Do not include any + // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero. + // + pBS ->AllocatePool(EfiBootServicesData,sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr->FileHeader.NumberOfSections, &SectionHeader); + + if(SectionHeader==NULL)return EFI_OUT_OF_RESOURCES; + pBS->SetMem(SectionHeader, (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr->FileHeader.NumberOfSections), 0); + + // + // 12. Using the 'PointerToRawData' in the referenced section headers as + // a key, arrange the elements in the table in ascending order. In other + // words, sort the section headers according to the disk-file offset of + // the section. + // + Section = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *)(UINTN)ImageAddress + + PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + Hdr->FileHeader.SizeOfOptionalHeader + ); + for (Index = 0; Index < Hdr->FileHeader.NumberOfSections; Index++) { + iPos = Index; + while ((iPos > 0) && (Section->PointerToRawData < SectionHeader[iPos - 1].PointerToRawData)) { + pBS->CopyMem (&SectionHeader[iPos], &SectionHeader[iPos - 1], sizeof(EFI_IMAGE_SECTION_HEADER)); + iPos--; + } + pBS->CopyMem( &SectionHeader[iPos], Section, + sizeof(EFI_IMAGE_SECTION_HEADER)); + Section += 1; + } + + // + // 13. Walk through the sorted table, bring the corresponding section + // into memory, and hash the entire section (using the 'SizeOfRawData' + // field in the section header to determine the amount of data to hash). + // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED . + // 15. Repeat steps 13 and 14 for all the sections in the sorted table. + // + for (Index = 0; Index < Hdr->FileHeader.NumberOfSections; Index++) { + Section = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index]; + if (Section->SizeOfRawData == 0) { + continue; + } + HashBase = (UINT8 *)(UINTN)ImageAddress + Section->PointerToRawData; + HashSize = (UINTN) Section->SizeOfRawData; + + if(HashPolicy == 0){ + SHA1Update(&Sha1Ctx, + HashBase, + (u32)HashSize); + }else if(HashPolicy == 1){ + sha256_process( &Sha2Ctx, HashBase, (u32)HashSize ); + } + + + SumOfBytesHashed += HashSize; + } + + // + // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra + // data in the file that needs to be added to the hash. This data begins + // at file offset SUM_OF_BYTES_HASHED and its length is: + // FileSize - (CertDirectory->Size) + // + if (ImageSize > SumOfBytesHashed) { + HashBase = (UINT8 *)(UINTN)ImageAddress + SumOfBytesHashed; + HashSize = (UINTN)(ImageSize - + Hdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - + SumOfBytesHashed); + + if(HashPolicy == 0){ + SHA1Update(&Sha1Ctx, + HashBase, + (u32)HashSize); + }else if(HashPolicy == 1){ + sha256_process( &Sha2Ctx, HashBase, (u32)HashSize ); + } + } + + // + // 17. Finalize the SHA hash. + // + if(HashPolicy == 0){ + SHA1Final(Sha1Digest.digest, &Sha1Ctx); + pBS->CopyMem(&TcgEvent.Digest, Sha1Digest.digest, SHA1_DIGEST_SIZE); + }else if(HashPolicy == 1){ + //sha256_done( &Sha2Ctx, Sha2DigestArray ); + //pBS->CopyMem(&TcgEvent.Digest.digestSha2, Sha2DigestArray, SHA256_DIGEST_SIZE); + } + + // + // HashLogExtendEvent + // + pBS->CopyMem(EventData, ImageLoad, TcgEvent.EventSize); + + Status = pBS->LocateProtocol(&gEfiAmiHLXEGuid, NULL, &InternalHLXE); + if(EFI_ERROR(Status))return Status; + + InternalHLXE->InternalHashLogExtend(NULL, 0, 0, &TcgEvent, EventData); + + PERF_END(0,L"MeasurePeImg",NULL,0); + + if(BootPolicy == TRUE){ +#if (defined(TCGMeasureSecureBootVariables) && (TCGMeasureSecureBootVariables != 0)) + FindandMeasureSecureBootCertificate(); +#endif + } + +Done: + if (ImageLoad != NULL) { + pBS->FreePool (ImageLoad); + } + + if (FullPathSize > 0) { + pBS->FreePool (FullPath); + } + + if (SectionHeader != NULL) { + pBS->FreePool (SectionHeader); + } + return Status; +} + + + +//******************************************************************************* +//<AMI_PHDR_START> +// +// Procedure: FindAndMeasureDxeFWVol +// +// Description: +// +// Input: +// +// Output: EFI_STATUS +// +// Modified: +// +// Referrals: +// +// Notes: +//<AMI_PHDR_END> +//****************************************************************************** +EFI_STATUS FindAndMeasureDxeFWVol() +{ + EFI_STATUS Status; + EFI_GUID NameGuid =\ + {0x7739f24c, 0x93d7, 0x11d4,\ + 0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d}; + UINTN Size; + void *Buffer = NULL; + VOID *HobStart; + UINTN TableEntries; + EFI_PEI_HOB_POINTERS FirmwareVolumeHob; + BOOLEAN Found = FALSE; + TrEE_EVENT *Tcg20Event = NULL; + EFI_TCG_EV_POST_CODE EventData; + + + if(TrEEProtocolInstance == NULL) return EFI_NOT_FOUND; + + Status = pBS->AllocatePool(EfiBootServicesData, (sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + sizeof(EventData)), &Tcg20Event); + + if(EFI_ERROR(Status) || (Tcg20Event == NULL))return Status; + + + TableEntries = pST->NumberOfTableEntries; + + while ( TableEntries > 0 ) + { + TableEntries--; + + if ((!MemCmp( + &pST->ConfigurationTable[TableEntries].VendorGuid, + &NameGuid, sizeof(EFI_GUID)))) + { + HobStart = pST->ConfigurationTable[TableEntries].VendorTable; + FirmwareVolumeHob.Raw = GetHob (EFI_HOB_TYPE_FV, HobStart); + if (FirmwareVolumeHob.Header->HobType != EFI_HOB_TYPE_FV) { + continue; + } + break; + } + } + + for (Status = EFI_NOT_FOUND; EFI_ERROR (Status);) { + if (END_OF_HOB_LIST (FirmwareVolumeHob)) { + return EFI_NOT_FOUND; + } + + if (GET_HOB_TYPE (FirmwareVolumeHob) == EFI_HOB_TYPE_FV) { + if ((((UINT64)FirmwareVolumeHob.FirmwareVolume->BaseAddress)\ + < (UINT64)NVRAM_ADDRESS ) || + ((UINT64)FirmwareVolumeHob.FirmwareVolume->BaseAddress) == FV_MAIN_BASE) + { + Found = TRUE; + break; + } + } + + FirmwareVolumeHob.Raw = GET_NEXT_HOB (FirmwareVolumeHob); + } + + if(Found == FALSE)return EFI_NOT_FOUND; + + pBS->AllocatePool(EfiBootServicesData, (UINTN)FirmwareVolumeHob.FirmwareVolume->Length, Buffer); + + if(Buffer == NULL) return EFI_OUT_OF_RESOURCES; + + if(FirmwareVolumeHob.FirmwareVolume->BaseAddress == FV_MAIN_BASE) + { + if(FirmwareVolumeHob.FirmwareVolume->Length > TCG_SIZE){ + Size = TCG_SIZE; + }else{ + Size = FirmwareVolumeHob.FirmwareVolume->Length; + } + + pBS->CopyMem(Buffer, (UINT8 *)(EFI_PHYSICAL_ADDRESS)FirmwareVolumeHob.FirmwareVolume->BaseAddress,\ + Size); + + }else{ + + Buffer = (UINT8 *)(EFI_PHYSICAL_ADDRESS)FirmwareVolumeHob.FirmwareVolume->BaseAddress; + Size = FirmwareVolumeHob.FirmwareVolume->Length; + } + + EventData.PostCodeAddress = \ + (EFI_PHYSICAL_ADDRESS)FirmwareVolumeHob.FirmwareVolume->BaseAddress; + + #if defined x64_BUILD && x64_BUILD == 1 + EventData.PostCodeLength = Size; + #else + EventData.PostCodeLength = Size; + #endif + + + Tcg20Event->Size = sizeof(TrEE_EVENT_HEADER) + sizeof(UINT32) + sizeof(EventData); + Tcg20Event->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); + Tcg20Event->Header.HeaderVersion = 1; + Tcg20Event->Header.PCRIndex = 0; + Tcg20Event->Header.EventType = EV_POST_CODE; + + pBS->CopyMem(Tcg20Event->Event, &EventData,sizeof(EventData)); + + + Status = TrEEProtocolInstance->HashLogExtendEvent(TrEEProtocolInstance, + 0, EventData.PostCodeAddress, Size, + Tcg20Event); + + return Status; +} + + +EFI_STATUS +EFIAPI +MeasureHandoffTables ( + VOID + ) +{ + EFI_STATUS Status = EFI_SUCCESS; +#if Measure_Smbios_Tables + SMBIOS_TABLE_ENTRY_POINT *SmbiosTable; + TrEE_EVENT *Tpm20Event; + + if(TrEEProtocolInstance == NULL) return EFI_NOT_FOUND; + + Status = pBS->AllocatePool(EfiBootServicesData, (sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + sizeof(EFI_HANDOFF_TABLE_POINTERS)), &Tpm20Event); + + if(EFI_ERROR(Status) || (Tpm20Event == NULL))return Status; + + Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, + (VOID **) &SmbiosTable); + + if (!EFI_ERROR (Status)) { + ASSERT (SmbiosTable != NULL); + } + + Tpm20Event->Size = sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + sizeof(EFI_HANDOFF_TABLE_POINTERS); + + Tpm20Event->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); + Tpm20Event->Header.HeaderVersion = 1; + Tpm20Event->Header.PCRIndex = 1; + Tpm20Event->Header.EventType = EV_EFI_HANDOFF_TABLES; + + ((EFI_HANDOFF_TABLE_POINTERS *)((UINTN)&Tpm20Event->Event[0]))->NumberOfTables = 1; + ((EFI_HANDOFF_TABLE_POINTERS *)((UINTN)&Tpm20Event->Event[0]))->TableEntry[0].VendorGuid = gEfiSmbiosTableGuid; + ((EFI_HANDOFF_TABLE_POINTERS *)((UINTN)&Tpm20Event->Event[0]))->TableEntry[0].VendorTable = SmbiosTable; + + Status = TrEEProtocolInstance->HashLogExtendEvent(TrEEProtocolInstance, + 0, (EFI_PHYSICAL_ADDRESS)(UINT8*)(UINTN)SmbiosTable->TableAddress, + SmbiosTable->TableLength, + Tpm20Event); + + pBS->FreePool(Tpm20Event); +#endif + + return Status; +} + + + +VOID * +EFIAPI +ReadVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize + ) +{ + EFI_STATUS Status; + VOID *VarData; + + *VarSize = 0; + Status = pRS->GetVariable ( + VarName, + VendorGuid, + NULL, + VarSize, + NULL + ); + if (Status != EFI_BUFFER_TOO_SMALL) { + return NULL; + } + + pBS->AllocatePool (EfiBootServicesData, *VarSize, &VarData); + if (VarData != NULL) { + Status = pRS->GetVariable ( + VarName, + VendorGuid, + NULL, + VarSize, + VarData + ); + if (EFI_ERROR (Status)) { + pBS->FreePool (VarData); + VarData = NULL; + *VarSize = 0; + } + } + return VarData; +} + + + +EFI_STATUS +EFIAPI +MeasureVariable ( + IN UINT32 PCRIndex, + IN UINT32 EventType, + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + IN VOID *VarData, + IN UINTN VarSize + ) +{ + EFI_STATUS Status; + TrEE_EVENT *Tpm20Event; + UINTN EventSize; + UINTN VarNameLength; + EFI_VARIABLE_DATA *VarLog; + + VarNameLength = Wcslen (VarName); + + if(TrEEProtocolInstance == NULL) return EFI_NOT_FOUND; + + EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize + - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData)); + + pBS->AllocatePool(EfiBootServicesData, (sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + EventSize), &Tpm20Event); + + if(Tpm20Event==NULL)return EFI_OUT_OF_RESOURCES; + + Tpm20Event->Size = sizeof(TrEE_EVENT_HEADER) + \ + sizeof(UINT32) + (UINT32)EventSize; + + Tpm20Event->Header.HeaderSize = sizeof(TrEE_EVENT_HEADER); + Tpm20Event->Header.HeaderVersion = 1; + Tpm20Event->Header.PCRIndex = PCRIndex; + Tpm20Event->Header.EventType = EventType; + + + ((EFI_VARIABLE_DATA *)((UINTN)&Tpm20Event->Event[0]))->VariableName = *VendorGuid; + ((EFI_VARIABLE_DATA *)((UINTN)&Tpm20Event->Event[0]))->UnicodeNameLength = VarNameLength; + ((EFI_VARIABLE_DATA *)((UINTN)&Tpm20Event->Event[0]))->VariableDataLength = VarSize; + + pBS->CopyMem (((EFI_VARIABLE_DATA *)((UINTN)&Tpm20Event->Event[0]))->UnicodeName, + VarName, + VarNameLength * sizeof (*VarName)); + + pBS->CopyMem ((CHAR16 *)((EFI_VARIABLE_DATA *)((UINTN)&Tpm20Event->Event[0]))->UnicodeName + VarNameLength, + VarData, + VarSize); + + Status = TrEEProtocolInstance->HashLogExtendEvent(TrEEProtocolInstance, + 0, (EFI_PHYSICAL_ADDRESS)(UINT8 *)(&Tpm20Event->Event[0]), EventSize, + Tpm20Event); + + pBS->FreePool(Tpm20Event); + + return Status; +} + + +EFI_STATUS +EFIAPI +TcgMeasureGptTable ( + IN EFI_HANDLE GptHandle + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_PARTITION_TABLE_HEADER *PrimaryHeader; + EFI_PARTITION_ENTRY *PartitionEntry; + UINT8 *EntryPtr; + UINTN NumberOfPartition; + UINT32 Index; + UINT64 Flags; + EFI_GPT_DATA *GptData; + UINT32 EventSize; + MASTER_BOOT_RECORD *Mbr; + UINT8 Count; + UINT32 LBAofGptHeader = 0; + TCG_PCR_EVENT_HDR TcgEvent; + AMI_INTERNAL_HLXE_PROTOCOL *InternalHLXE = NULL; + EFI_GUID gEfiAmiHLXEGuid = AMI_PROTOCOL_INTERNAL_HLXE_GUID; + + if (mMeasureGptCount > 0) { + return EFI_SUCCESS; + } + + Status = pBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + Status = pBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + //Read the protective MBR + pBS->AllocatePool (EfiBootServicesData, BlockIo->Media->BlockSize, &Mbr); + if (Mbr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + 0 * BlockIo->Media->BlockSize, + BlockIo->Media->BlockSize, + (UINT8 *)Mbr + ); + + for(Count=0; Count<MAX_MBR_PARTITIONS;Count++){ + if(Mbr->Partition[Count].OSIndicator == 0xEE){//(i.e., GPT Protective) + LBAofGptHeader = *(Mbr->Partition[Count].StartingLBA); + break; + } + } + + if(LBAofGptHeader == 0x00)//Did not find the correct GPTHeader so return EFI_NOT_FOUND + return EFI_NOT_FOUND; + + // + // Read the EFI Partition Table Header + // + pBS->AllocatePool (EfiBootServicesData, BlockIo->Media->BlockSize, &PrimaryHeader); + if (PrimaryHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + LBAofGptHeader * BlockIo->Media->BlockSize, + BlockIo->Media->BlockSize, + (UINT8 *)PrimaryHeader); + +// if(PrimaryHeader->Header.Signature != EFI_GPT_HEADER_ID)//Check for "EFI PART" signature + if (MemCmp(EFI_GPT_HEADER_ID, &PrimaryHeader->Header.Signature, sizeof(UINT64))) return EFI_NOT_FOUND; + + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "Failed to Read Partition Table Header!\n")); + pBS->FreePool (PrimaryHeader); + return EFI_DEVICE_ERROR; + } + + // + // Read the partition entry. + // + pBS->AllocatePool (EfiBootServicesData, PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, &EntryPtr); + if (EntryPtr == NULL) { + pBS->FreePool (PrimaryHeader); + return EFI_OUT_OF_RESOURCES; + } + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + Mul64(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), + PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, + EntryPtr + ); + if (EFI_ERROR (Status)) { + pBS->FreePool (PrimaryHeader); + pBS->FreePool (EntryPtr); + return EFI_DEVICE_ERROR; + } + + // + // Count the valid partition + // + PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr; + NumberOfPartition = 0; + for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { + if (MemCmp (&PartitionEntry->PartitionTypeGUID, &ZeroGuid, sizeof(EFI_GUID))) { + NumberOfPartition++; + } + PartitionEntry++; + } + + // + // Parepare Data for Measurement + // + EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); + + pBS->AllocatePool (EfiBootServicesData, EventSize, &GptData); + if (GptData == NULL) { + pBS->FreePool (PrimaryHeader); + pBS->FreePool (EntryPtr); + return EFI_OUT_OF_RESOURCES; + } + + MemSet(GptData, EventSize, 0); + + TcgEvent.PCRIndex = 5; + TcgEvent.EventType = EV_EFI_GPT_EVENT; + TcgEvent.EventSize = EventSize; + + Flags = 0; + + // + // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition + // + pBS->CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); + GptData->NumberOfPartitions = NumberOfPartition; + // + // Copy the valid partition entry + // + PartitionEntry = (EFI_PARTITION_ENTRY*)EntryPtr; + NumberOfPartition = 0; + for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { + if (MemCmp (&PartitionEntry->PartitionTypeGUID, &ZeroGuid, sizeof(EFI_GUID))) { + pBS->CopyMem ( + (UINT8 *)&GptData->Partitions + NumberOfPartition * sizeof (EFI_PARTITION_ENTRY), + (UINT8 *)PartitionEntry, + sizeof (EFI_PARTITION_ENTRY) + ); + NumberOfPartition++; + } + PartitionEntry++; + } + + // + // Measure the GPT data + // + if(NumberOfPartition > 0) + { + + Status = pBS->LocateProtocol(&gEfiAmiHLXEGuid, NULL, &InternalHLXE); + if(EFI_ERROR(Status))return Status; + + InternalHLXE->InternalHashLogExtend((UINT8 *)GptData, 0, EventSize, &TcgEvent, (UINT8 *)GptData); + + if (!EFI_ERROR (Status)) { + mMeasureGptCount++; + TRACE ((TRACE_ALWAYS, "\n GPT measurement successfull !!!\n")); + } + } + + pBS->FreePool (PrimaryHeader); + pBS->FreePool (EntryPtr); + pBS->FreePool (GptData); + return Status; +} + + + + + +EFI_STATUS +EFIAPI +MeasureGptTable () +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_HANDLE *HandleArray; + UINTN HandleArrayCount; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + TRACE ((TRACE_ALWAYS, "MeasureGptTable\n")); + + + Status = pBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleArrayCount, &HandleArray); + if (EFI_ERROR (Status)) { + return Status; + } + for (Index=0; Index < HandleArrayCount; Index++) { + Status = pBS->HandleProtocol (HandleArray[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath); + if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) { + continue; + } + for (DevicePath = BlockIoDevicePath; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + if ((DevicePathType (DevicePath) == ACPI_DEVICE_PATH) && (DevicePathSubType (DevicePath) == ACPI_DP)) { + Status = pBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &DevicePath, &Handle); + if (!EFI_ERROR (Status)) { + Status = TcgMeasureGptTable (Handle); + if (!EFI_ERROR (Status)) { + // + // GPT partition check done. + // +// mMeasureGptTableFlag = TRUE; + } + } + break; + } + } + } + + return Status; +} + +#if (defined(TCGMeasureSecureBootVariables) && (TCGMeasureSecureBootVariables != 0)) +EFI_STATUS +MeasureSecureBootState( + VOID + ) +{ + EFI_STATUS Status; + UINT32 Attribute; + UINTN DataSize; + UINT8 *Variable; + UINT64 MaxStorSize; + UINT64 RemStorSize; + UINT64 MaxVarSize; + TCG_PCR_EVENT_HDR TcgEvent; + CHAR16 *VarName; + EFI_GUID VendorGuid; + + Attribute = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS; + + TcgEvent.PCRIndex = 7; + TcgEvent.EventType = EV_EFI_VARIABLE_DRIVER_CONFIG; + + // Query maximum size of the variable and allocate memory + + Status = pRS->QueryVariableInfo(Attribute, &MaxStorSize, &RemStorSize, &MaxVarSize); + if (EFI_ERROR(Status)) { + return (Status); + } + + DataSize = (UINTN)MaxStorSize; + pBS->AllocatePool(EfiBootServicesData, DataSize, &Variable); + if (Variable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + MemSet(Variable, DataSize, 0); // Clear the buffer + + // 1.Measure Secure Boot Variable Value + + Status = pRS->GetVariable ( + EFI_SECURE_BOOT_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Variable + ); + + VarName = EFI_SECURE_BOOT_NAME; + VendorGuid = gEfiGlobalVariableGuid; + + if(EFI_ERROR(Status) || *Variable == 0){ + DataSize = 0; + *Variable = 0; + } + + + Status = MeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + VarName, + &VendorGuid, + Variable, + DataSize + ); + + // 2.Measure PK Variable Value + + DataSize = (UINTN)MaxStorSize; // DataSize gets updated by GetVariable. So initialize everytime before the call + MemSet(Variable, DataSize, 0); // Clear the buffer + + Status = pRS->GetVariable ( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Variable + ); + + VarName = EFI_PLATFORM_KEY_NAME; + VendorGuid = gEfiGlobalVariableGuid; + + if(EFI_ERROR(Status)){ + DataSize = 0; + *Variable = 0; + } + + Status = MeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + VarName, + &VendorGuid, + Variable, + DataSize + ); + + // 3.Measure KEK Variable Value + + DataSize = (UINTN)MaxStorSize; // DataSize gets updated by GetVariable. So initialize everytime before the call + MemSet(Variable, DataSize, 0); // Clear the buffer + + Status = pRS->GetVariable ( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Variable + ); + + VarName = EFI_KEY_EXCHANGE_KEY_NAME; + VendorGuid = gEfiGlobalVariableGuid; + + if(EFI_ERROR(Status)){ + DataSize = 0; + *Variable = 0; + } + + Status = MeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + VarName, + &VendorGuid, + Variable, + DataSize + ); + + if(EFI_ERROR(Status)){ + goto Exit; + } + + // 4.Measure EFI_IMAGE_SECURITY_DATABASE Variable Value + + DataSize = (UINTN)MaxStorSize; // DataSize gets updated by GetVariable. So initialize everytime before the call + MemSet(Variable, DataSize, 0); // Clear the buffer + + Status = pRS->GetVariable ( + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + NULL, + &DataSize, + Variable + ); + + VarName = EFI_IMAGE_SECURITY_DATABASE; + VendorGuid = gEfiImageSecurityDatabaseGuid; + + if(EFI_ERROR(Status)){ + DataSize = 0; + *Variable = 0; + } + + Status = MeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + VarName, + &VendorGuid, + Variable, + DataSize + ); + + if(EFI_ERROR(Status)){ + goto Exit; + } + + // 5.Measure EFI_IMAGE_SECURITY_DATABASE1 Variable Value + + DataSize = (UINTN)MaxStorSize; // DataSize gets updated by GetVariable. So initialize everytime before the call + MemSet(Variable, DataSize, 0); // Clear the buffer + + Status = pRS->GetVariable ( + EFI_IMAGE_SECURITY_DATABASE1, + &gEfiImageSecurityDatabaseGuid, + NULL, + &DataSize, + Variable + ); + + VarName = EFI_IMAGE_SECURITY_DATABASE1; + VendorGuid = gEfiImageSecurityDatabaseGuid; + + if(EFI_ERROR(Status)){ + DataSize = 0; + *Variable = 0; + } + + Status = MeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + VarName, + &VendorGuid, + Variable, + DataSize + ); + + if(EFI_ERROR(Status)){ + goto Exit; + } + +Exit: + pBS->FreePool(Variable); + return EFI_SUCCESS; +} +#endif + + +EFI_STATUS ResetMorVariable() +{ + EFI_STATUS Status; + EFI_GUID MorGuid = MEMORY_ONLY_RESET_CONTROL_GUID; + UINT32 Attribs = EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS; + + UINT8 Temp = 0; + UINTN TempSize = sizeof (UINT8); + + + + Status = pRS->GetVariable( + L"MemoryOverwriteRequestControl", + &MorGuid, + &Attribs, + &TempSize, + &Temp ); + + if ( EFI_ERROR( Status ) || (Temp&01) != 0 ) + { + Temp &= 0xFE; + Status = pRS->SetVariable( + L"MemoryOverwriteRequestControl", + &MorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT8), + &Temp ); + } + + return Status; +} + +EFI_STATUS +InternalMeasureAction ( + IN CHAR8 *ActionString + ) +{ + return EFI_SUCCESS; //not supported +} + + +EFI_STATUS +InternalMeasureGpt ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + + return EFI_SUCCESS; //not supported; +} + + + +EFI_TCG_PLATFORM_PROTOCOL mTcgPlatformProtocol = { + TreeMeasurePeImage, + InternalMeasureAction, + InternalMeasureGpt +}; + + +EFI_STATUS InstallTcgPlatformProtocol( + VOID +) +{ + + EFI_GUID gEfiTcgPrivateInterfaceGuid = EFI_TCG_PLATFORM_PROTOCOL_GUID; + + return pBS->InstallProtocolInterface ( + &PlatformProtocolHandle, + &gEfiTcgPrivateInterfaceGuid, + EFI_NATIVE_INTERFACE, + &mTcgPlatformProtocol + ); + +} + + +VOID +EFIAPI +Tpm20OnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINT32 PcrIndex; + static BOOLEAN mBootAttempts=0; + + if (mBootAttempts == 0) { + + ResetMorVariable(); + // + // Measure handoff tables + // + Status = MeasureHandoffTables (); + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "HandoffTables not measured.\n")); + } + else { + TRACE((TRACE_ALWAYS, "HandoffTables measured.\n")); + } + + // + // Measure the fact that Secure Boot is disabled + // +#if (defined(TCGMeasureSecureBootVariables) && (TCGMeasureSecureBootVariables != 0)) + Status = MeasureSecureBootState(); + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "Measuring secure boot state failed.\n")); + } + else { + TRACE((TRACE_ALWAYS, "Secure boot state measured.\n")); + } +#endif + + + // + // This is the first boot attempt + // + Status = MeasureAction ( + "EFI_CALLING_EFI_APPLICATION" + ); + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "First boot attempt not Measured.\n")); + } + else { + TRACE((TRACE_ALWAYS, "First boot attempt measured.\n")); + } + + // + // Draw a line between pre-boot env and entering post-boot env + // + for (PcrIndex = 0; PcrIndex < 8; PcrIndex++) { + Status = MeasureSeparatorEvent (PcrIndex); + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "Measuring separtator event failed.\n")); + } + else { + TRACE((TRACE_ALWAYS, "Separator event measured.\n")); + } + + } + + // + // Measure GPT + // + Status = MeasureGptTable (); + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "Measuring GPT failed.\n")); + } + else { + TRACE((TRACE_ALWAYS, "GPT measured.\n")); + } + } + else { + // + // Not first attempt, meaning a return from last attempt + // +/* + Status = MeasureAction ( + "EFI_RETURNING_FROM_EFI_APPLICATOIN" + ); + if (EFI_ERROR (Status)) { + TRACE ((TRACE_ALWAYS, "Measuring additional boot attempt failed.\n")); + } +*/ + } + // + // Increase boot attempt counter. + // + mBootAttempts++; + +} + + + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: GetStringFromToken +// +// Description: Gets a UNI string by Token +// +// Input: IN STRING_REF Token, +// OUT CHAR16 **String +// +// Output: EFI_STATUS +// +// Modified: +// +// Referrals: +// +// Notes: +//<AMI_PHDR_END> +//********************************************************************** +EFI_STATUS GetStringFromToken( + IN STRING_REF Token, + OUT CHAR16 **String ) +{ + EFI_STATUS Status; + UINTN StringBufferLength; + UINT16 *Temp; + UINTN Size = 0; + + + // + // Find the string based on the current language + // + StringBufferLength = 0x500; + Status = pBS->AllocatePool( EfiBootServicesData, + sizeof (CHAR16) * 0x500, + String ); + Temp = *String; + while ( Temp < *String + StringBufferLength ) + { + *Temp = 0x0; + Temp++; + } + +#if EFI_SPECIFICATION_VERSION>0x20000 + + Status = HiiLibGetString ( + gHiiHandle, + Token, + &StringBufferLength, + *String + ); + if (EFI_ERROR(Status)) { + return Status; + } + +#else + if ( Hii == NULL ) + { + return EFI_NOT_FOUND; + } + + Status = Hii->GetString( + Hii, + gHiiHandle, + Token, + TRUE, + NULL, + &StringBufferLength, + *String + ); +#endif + + + if ( EFI_ERROR( Status )) + { + pBS->FreePool( *String ); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS TcgSetVariableWithNewAttributes( + IN CHAR16 *Name, IN EFI_GUID *Guid, IN UINT32 Attributes, + IN UINTN DataSize, IN VOID *Data +) +{ + EFI_STATUS Status; + + Status = pRS->SetVariable(Name, Guid, Attributes, DataSize, Data); + if (!EFI_ERROR(Status) || Status != EFI_INVALID_PARAMETER) return Status; + + Status = pRS->SetVariable(Name, Guid, 0, 0, NULL); + if (EFI_ERROR(Status)) return Status; + + return pRS->SetVariable(Name, Guid, Attributes, DataSize, Data); +} + + +//**************************************************************************************** +//<AMI_PHDR_START> +// +// Procedure: write_PPI_result +// +// Description: Updates TCG PPI variable in NVRAM +// +// +// Input: IN UINT8 last_op, +// IN UINT16 status +// +// Output: VOID +// +// Modified: +// +// Referrals: +// +// Notes: +//<AMI_PHDR_END> +//**************************************************************************************** +void WritePpiResult( + IN UINT8 last_op, + IN UINT16 status ) +{ + UINTN Size = sizeof(AMI_PPI_NV_VAR); + AMI_PPI_NV_VAR Temp; + EFI_STATUS Status; + UINT8 Manip = 0; + + Status = pRS->GetVariable( L"AMITCGPPIVAR", \ + &AmitcgefiOsVariableGuid, \ + NULL, \ + &Size, \ + &Temp ); + + //now set variable to data + Temp.RQST = Manip; + Manip = (UINT8)( status & 0xFFFF ); + Temp.ERROR = Manip; + + if(status>0xFF && status<0xFFFF) + { + Temp.AmiMisc = (UINT8)(status >> 8); + }else{ + Temp.AmiMisc = 0; + } + + if ( EFI_ERROR( Status )) + { + TRACE((TRACE_ALWAYS, "Error Setting Return value\n")); + return; + } + + + Status = TcgSetVariableWithNewAttributes(L"AMITCGPPIVAR", &AmitcgefiOsVariableGuid, \ + EFI_VARIABLE_NON_VOLATILE \ + | EFI_VARIABLE_BOOTSERVICE_ACCESS,\ + Size, &Temp ); + +} + + + +/** + Send ClearControl command to TPM2. + + @param Disable if we need disable owner clear flag. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm2ClearControl ( + IN TPMI_YES_NO Disable + ) +{ + EFI_STATUS Status; + TPM2_CLEAR_CONTROL_COMMAND Cmd; + TPM2_CLEAR_CONTROL_RESPONSE Res; + UINT32 ResultBufSize; + UINT32 CmdSize; + UINT32 RespSize; + UINT8 *Buffer; + UINT8 *AuthSizeOffset; + + Cmd.Header.tag = (TPMI_ST_COMMAND_TAG)TPM_H2NS(TPM_ST_SESSIONS); + Cmd.Header.commandCode = TPM_H2NL(TPM_CC_ClearControl); + Cmd.Auth = TPM_H2NL(TPM_RH_PLATFORM); + + Buffer = (UINT8 *)&Cmd.AuthorizationSize; + + // + // Add in Auth session + // + AuthSizeOffset = Buffer; + *(UINT32 *)Buffer = 0; + Buffer += sizeof(UINT32); + + // authHandle + *(UINT32 *)Buffer = TPM_H2NL(TPM_RS_PW); + Buffer += sizeof(UINT32); + + // nonce = nullNonce + *(UINT16 *)Buffer = 0; + Buffer += sizeof(UINT16); + + // sessionAttributes = 0 + *(UINT8 *)Buffer = 0; + Buffer += sizeof(UINT8); + + // auth = nullAuth + *(UINT16 *)Buffer = 0; + Buffer += sizeof(UINT16); + + // authorizationSize + *(UINT32 *)AuthSizeOffset = TPM_H2NL((UINT32)(Buffer - AuthSizeOffset - sizeof(UINT32))); + + // disable + *(UINT8 *)Buffer = Disable; + Buffer += sizeof(UINT8); + + CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd); + Cmd.Header.paramSize = TPM_H2NL(CmdSize); + + ResultBufSize = sizeof(Res); + Status = TrEEProtocolInstance->SubmitCommand(TrEEProtocolInstance,CmdSize,(UINT8 *)&Cmd , ResultBufSize , (UINT8 *)&Res); + + if (EFI_ERROR(Status)) { + return Status; + } + + if (ResultBufSize > sizeof(Res)) { + TRACE((TRACE_ALWAYS, "ClearControl: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto ClearControlEND; + } + + // + // Validate response headers + // + RespSize = TPM_H2NL(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { + TRACE((TRACE_ALWAYS, "ClearControl: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto ClearControlEND; + } + + // + // Fail if command failed + // + if (TPM_H2NL(Res.Header.responseCode) != TPM_RC_SUCCESS) { + TRACE((TRACE_ALWAYS, "ClearControl: Response Code error! 0x%08x\r\n", TPM_H2NL(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto ClearControlEND; + } + + // + // Unmarshal the response + // + + // None + + Status = EFI_SUCCESS; + +ClearControlEND: + return Status; +} + + + +EFI_STATUS +EFIAPI +Tpm2Clear ( + VOID + ) +{ + EFI_STATUS Status; + TPM2_CLEAR_COMMAND Cmd; + TPM2_CLEAR_RESPONSE Res; + UINT32 ResultBufSize; + UINT32 CmdSize; + UINT32 RespSize; + UINT8 *Buffer; + UINT8 *AuthSizeOffset; + + Cmd.Header.tag = (TPMI_ST_COMMAND_TAG)TPM_H2NS(TPM_ST_SESSIONS); + Cmd.Header.commandCode = TPM_H2NL(TPM_CC_Clear); + Cmd.Auth = TPM_H2NL(TPM_RH_PLATFORM); + + Buffer = (UINT8 *)&Cmd.AuthorizationSize; + + // + // Add in Auth session + // + AuthSizeOffset = Buffer; + *(UINT32 *)Buffer = 0; + Buffer += sizeof(UINT32); + + // authHandle + *(UINT32 *)Buffer = TPM_H2NL(TPM_RS_PW); + Buffer += sizeof(UINT32); + + // nonce = nullNonce + *(UINT16 *)Buffer = 0; + Buffer += sizeof(UINT16); + + // sessionAttributes = 0 + *(UINT8 *)Buffer = 0; + Buffer += sizeof(UINT8); + + // auth = nullAuth + *(UINT16 *)Buffer = 0; + Buffer += sizeof(UINT16); + + // authorizationSize + *(UINT32 *)AuthSizeOffset = TPM_H2NL((UINT32)(Buffer - AuthSizeOffset - sizeof(UINT32))); + + CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd); + Cmd.Header.paramSize = TPM_H2NL(CmdSize); + + ResultBufSize = sizeof(Res); + + Status = TrEEProtocolInstance->SubmitCommand(TrEEProtocolInstance,CmdSize,(UINT8 *)&Cmd , ResultBufSize , (UINT8 *)&Res); + if (EFI_ERROR(Status)) { + return Status; + } + + if (ResultBufSize > sizeof(Res)) { + TRACE((TRACE_ALWAYS, "Clear: Failed ExecuteCommand: Buffer Too Small\r\n")); + Status = EFI_BUFFER_TOO_SMALL; + goto ClearEND; + } + + // + // Validate response headers + // + RespSize = TPM_H2NL(Res.Header.paramSize); + if (RespSize > sizeof(Res)) { + TRACE((TRACE_ALWAYS, "Clear: Response size too large! %d\r\n", RespSize)); + Status = EFI_BUFFER_TOO_SMALL; + goto ClearEND; + } + + // + // Fail if command failed + // + if (TPM_H2NL(Res.Header.responseCode) != TPM_RC_SUCCESS) { + TRACE((TRACE_ALWAYS, "Clear: Response Code error! 0x%08x\r\n", TPM_H2NL(Res.Header.responseCode))); + Status = EFI_DEVICE_ERROR; + goto ClearEND; + } + + // + // Unmarshal the response + // + + // None + + Status = EFI_SUCCESS; + +ClearEND: + return Status; +} + + + +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: read_PPI_request +// +// Description: Reads and returns TCG PPI requests Value +// +// +// Input: +// +// Output: UINT8 +// +// Modified: +// +// Referrals: +// +// Notes: +//<AMI_PHDR_END> +//********************************************************************** +UINT8 ReadPpiRequest( ) +{ + UINTN Size = sizeof(AMI_PPI_NV_VAR); + AMI_PPI_NV_VAR Temp; + EFI_STATUS Status; + + Status = pRS->GetVariable( L"AMITCGPPIVAR", \ + &AmitcgefiOsVariableGuid, \ + NULL, \ + &Size, \ + &Temp ); + + if(Status == EFI_NOT_FOUND) + { + Temp.RQST = 0; + Temp.RCNT = 0; + Temp.ERROR = 0; + Temp.Flag = 0; + Temp.AmiMisc = 0; + + Status = TcgSetVariableWithNewAttributes(L"AMITCGPPIVAR", &AmitcgefiOsVariableGuid, \ + EFI_VARIABLE_NON_VOLATILE \ + | EFI_VARIABLE_BOOTSERVICE_ACCESS,\ + Size, &Temp ); + + } + + return Temp.RQST; +} + + + +void HandleTpm20Ppi(IN EFI_EVENT ev, + IN VOID *ctx) +{ + BOOLEAN UserAction; + UINT8 StringType = 0; + UINTN CurX, CurY; + CHAR16 *StrBuffer = NULL; + CHAR16 *String; + EFI_INPUT_KEY key; + TSE_POST_STATUS TsePostStatus; + EFI_STATUS Status; + + + TRACE((TRACE_ALWAYS, "HandleTpm20Ppi Entry \n")); + if (pAmiPostMgr == NULL) { + Status = pBS->LocateProtocol( &gAmiPostManagerProtocolGuid, + NULL, + &pAmiPostMgr ); + if (EFI_ERROR(Status)) { + return; + } + } + + // + // Calling GetPostStatus() to check current TSE_POST_STATUS + // + TsePostStatus = pAmiPostMgr->GetPostStatus(); + + if ( pST->ConIn == NULL || pST->ConOut == NULL || TsePostStatus == TSE_POST_STATUS_BEFORE_POST_SCREEN ) + { + TRACE((TRACE_ALWAYS, "\tTextIn/Out not ready: in=%x; out=%x\n", + pST->ConIn, pST->ConOut)); + return; + } + + switch(PpiRequest){ + case TPM20_PP_NO_ACTION_MAX: + return; + + case TPM20_PP_CLEAR_CONTROL_CLEAR_2: + case TPM20_PP_CLEAR_CONTROL_CLEAR_3: + case TPM20_PP_CLEAR_CONTROL_CLEAR_4: + if(TpmNvflags.NoPpiClear != 1) + { + UserAction = TRUE; + StringType = 1; + break; + } + case TPM20_PP_SET_NO_PPI_CLEAR_FALSE: + UserAction = FALSE; + StringType = 0; + break; + + case TPM20_PP_SET_NO_PPI_CLEAR_TRUE: + if(TpmNvflags.NoPpiClear != 1) + { + UserAction = TRUE; + StringType = 2; + break; + } + + default: + if (PpiRequest <= TPM20_PP_NO_ACTION_MAX){ + WritePpiResult( PpiRequest, (UINT16)(0)); + }else{ + WritePpiResult( PpiRequest, (UINT16)(TCPA_PPI_BIOSFAIL)); + } + return; + } + + if(UserAction) + { + pAmiPostMgr->SwitchToPostScreen( ); + + Status = pBS->AllocatePool(EfiBootServicesData, + sizeof (CHAR16) * 0x100, + (VOID*) &StrBuffer); + + if ( EFI_ERROR( Status ) || StrBuffer == NULL ) + { + return; + } + + MemSet( StrBuffer, sizeof (CHAR16) * 0x100, 0 ); + + pAmiPostMgr->DisplayPostMessage( StrBuffer ); + + pAmiPostMgr->GetCurPos(&CurX, &CurY); + + CurX = 0; + CurY -= PPI_DISPLAY_OFFSET; + + if(StringType == 1){ + + GetStringFromToken( STRING_TOKEN(TPM_CLEAR_STR), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + GetStringFromToken( STRING_TOKEN( TPM_WARNING_CLEAR ), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + GetStringFromToken( STRING_TOKEN( TPM_CAUTION_KEY ), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + + }else if(StringType == 2){ + + GetStringFromToken( STRING_TOKEN(TPM_PPI_HEAD_STR), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + GetStringFromToken( STRING_TOKEN( TPM_NOTE_CLEAR ), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + GetStringFromToken( STRING_TOKEN( TPM_ACCEPT_KEY ), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + } + + GetStringFromToken( STRING_TOKEN( TPM_REJECT_KEY ), &String ); + pAmiPostMgr->DisplayPostMessage( String ); + + if ( pST->ConIn ) + { + while ( TRUE ) + { + Status = pST->ConIn->ReadKeyStroke( pST->ConIn, &key ); + if ( Status == EFI_SUCCESS ) + { + if ( PpiRequest == TPM20_PP_CLEAR_CONTROL_CLEAR_2 || + PpiRequest == TPM20_PP_CLEAR_CONTROL_CLEAR_3 || + PpiRequest == TPM20_PP_CLEAR_CONTROL_CLEAR_4 ) + { + if ( key.ScanCode == TCG_CLEAR_REQUEST_KEY ) + { + break; + } + } + else if(PpiRequest == TPM20_PP_SET_NO_PPI_CLEAR_FALSE || + PpiRequest == TPM20_PP_SET_NO_PPI_CLEAR_TRUE) + { + + if ( key.ScanCode == TCG_CONFIGURATION_ACCEPT_KEY ) + { + break; + } + } + else if ( key.ScanCode == TCG_CONFIGURATION_IGNORE_KEY ) + { + return; + } + } + } + } + + } + + if ( PpiRequest == TPM20_PP_CLEAR_CONTROL_CLEAR_2 || + PpiRequest == TPM20_PP_CLEAR_CONTROL_CLEAR_3 || + PpiRequest == TPM20_PP_CLEAR_CONTROL_CLEAR_4 ) + { + Status = Tpm2ClearControl(0); + if(!EFI_ERROR(Status)){ + + Status = Tpm2Clear(); + if(EFI_ERROR(Status)){ + TRACE((TRACE_ALWAYS, "Error Clearing TPM20 device\n")); + WritePpiResult( PpiRequest, (UINT16)(TCPA_PPI_BIOSFAIL)); + }else{ + WritePpiResult( PpiRequest, (UINT16)(0)); + } + }else{ + TRACE((TRACE_ALWAYS, "Tpm2ClearControl failure\n")); + WritePpiResult( PpiRequest, (UINT16)(TCPA_PPI_BIOSFAIL)); + } + } + else if(PpiRequest == TPM20_PP_SET_NO_PPI_CLEAR_FALSE || + PpiRequest == TPM20_PP_SET_NO_PPI_CLEAR_TRUE) + { + if(PpiRequest == TPM20_PP_SET_NO_PPI_CLEAR_FALSE) + { + TpmNvflags.NoPpiClear = 0; + + }else{ + TpmNvflags.NoPpiClear = 1; + } + + Status = TcgSetVariableWithNewAttributes(L"TPMPERBIOSFLAGS", &FlagsStatusguid, \ + EFI_VARIABLE_NON_VOLATILE \ + | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (PERSISTENT_BIOS_TPM_FLAGS), &TpmNvflags); + + if(EFI_ERROR(Status)){ + TRACE((TRACE_ALWAYS, "Error Clearing TPM20 device\n")); + WritePpiResult( PpiRequest, (UINT16)(TCPA_PPI_BIOSFAIL)); + } + else{ + WritePpiResult( PpiRequest, (UINT16)(0)); + } + }else{ + WritePpiResult( PpiRequest, (UINT16)(0)); + } + + TRACE((TRACE_ALWAYS, "TPM20 changes made reseting system\n")); + pRS->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); +} + +VOID +EFIAPI +Tpm20OnExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + // + // Measure invocation of ExitBootServices, + // + Status = MeasureAction ( + "Exit Boot Services Invocation"); + + // + // Measure success of ExitBootServices + // + Status = MeasureAction ( + "Exit Boot Services Returned with Success"); +} + + + +EFI_STATUS +Tpm20PlatformEntry( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) +{ + EFI_STATUS Status; + EFI_GUID gEfiTrEEProtocolGuid = EFI_TREE_PROTOCOL_GUID; + EFI_EVENT ReadyToBootEvent; + EFI_EVENT ev; + EFI_EVENT ExitBSEvent; + static VOID *reg; + UINTN Size = sizeof(PERSISTENT_BIOS_TPM_FLAGS); + + + InitAmiLib( ImageHandle, SystemTable ); + + TRACE((TRACE_ALWAYS, "Tpm20PlatformEntry\n")); + + Status = pBS->LocateProtocol(&gEfiTrEEProtocolGuid, NULL, &TrEEProtocolInstance); + if(EFI_ERROR(Status))return Status; + + Status = InstallTcgPlatformProtocol(); + if(EFI_ERROR(Status))return Status; + + //we found TrEE protocol do Tpm20 + //Initializations set ready to boot callback + //install platform protocol + + Status = CreateReadyToBootEvent(TPL_CALLBACK, + Tpm20OnReadyToBoot, + NULL, + &ReadyToBootEvent); + + Status = pBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_NOTIFY, + Tpm20OnExitBootServices, + NULL, + &ExitBSEvent + ); + LoadStrings( ImageHandle, &gHiiHandle ); + + Status = pRS->GetVariable( L"TPMPERBIOSFLAGS", \ + &FlagsStatusguid, \ + NULL, \ + &Size, \ + &TpmNvflags ); + + if(EFI_ERROR(Status)) + { + TpmNvflags.NoPpiProvision = 1; + TpmNvflags.NoPpiClear = 0; + TpmNvflags.NoPpiMaintenance = 0; + + Status = TcgSetVariableWithNewAttributes(L"TPMPERBIOSFLAGS", &FlagsStatusguid, \ + EFI_VARIABLE_NON_VOLATILE \ + | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (PERSISTENT_BIOS_TPM_FLAGS), &TpmNvflags); + + if(EFI_ERROR(Status))return Status; + } + + PpiRequest = ReadPpiRequest(); + PpiRequest &= 0xFF; + + if(PpiRequest > 0 && PpiRequest <= TCPA_PPIOP_ENABLE_ACTV_CLEAR_ENABLE_ACTV){ + + Status = pBS->CreateEvent( EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + HandleTpm20Ppi, + 0, + &ev ); + + if(EFI_ERROR(Status)){ + return Status; + } + + Status = pBS->RegisterProtocolNotify( + &gBdsAllDriversConnectedProtocolGuid, + ev, + ® ); + if(EFI_ERROR(Status)) { + return Status; + } + } + + return Status; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |