diff options
Diffstat (limited to 'ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c')
-rw-r--r-- | ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c b/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c new file mode 100644 index 0000000..8eff986 --- /dev/null +++ b/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c @@ -0,0 +1,191 @@ +/** @file + PFAT EarlyPost initializations. + +@copyright + Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ + +/// +/// External include files do NOT need to be explicitly specified in real EDKII +/// environment +/// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include "CpuInitPeim.h" +#include "CpuAccess.h" +#include "PfatInit.h" +#ifdef PFAT_EC_FLAG +#include EFI_PPI_DEPENDENCY (CpuIo) +#include EFI_PPI_PRODUCER (Stall) +#include "PeiKscLib.h" +#endif //PFAT_EC_FLAG +#endif + +#ifdef PFAT_EC_FLAG +/** + Gets CPU's random number generator. + + @param[out] UINT32 - Random value +**/ +UINT32 +RandomNumber ( + void + ) +{ + UINT32 Random = 0; + + /// + /// Assembly instruction to read CPU's random number generator + /// Instruction is only available 100k cycles after reset + /// + __asm { +tryAgain: + ; rdrand eax + ; db 0Fh, 0C7h, 0F0h + + _emit 0x0F + _emit 0xC7 + _emit 0xF0 + + mov Random, eax + jnc tryAgain; CF will be set is valid number was generated + } + + return (Random); +} +#endif //PFAT_EC_FLAG + +/** + Perform the platform spefific initializations. + + @param[in] PeiServices - Indirect reference to the PEI Services Table. + @param[in] CpuPlatformPolicyPpi - Platform Policy PPI +**/ +VOID +PfatInit ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi + ) +{ + EFI_STATUS Status; + UINT64 MsrValue; + BOOLEAN ResetRequired; + PFAT_HOB *PfatHobPtr; + EFI_GUID PfatHobGuid = PFAT_HOB_GUID; + UINT8 i; + PFAT_CONFIG *PfatConfig; +#ifdef PFAT_EC_FLAG + volatile UINT32 EphemeralAuthValue; + UINT8 EcStatus; + PEI_STALL_PPI *StallPpi; + PEI_CPU_IO_PPI *CpuIo; +#endif //PFAT_EC_FLAG + + DEBUG ((EFI_D_INFO, "PfatInit\n")); + + ResetRequired = FALSE; + MsrValue = AsmReadMsr64 (MSR_PLATFORM_INFO); + if (!(MsrValue & B_MSR_PLATFORM_INFO_PFAT_AVAIL)) { + DEBUG ((EFI_D_INFO, "PFAT Feature is not supported\n")); + return; + } + + if (CpuPlatformPolicyPpi->CpuConfig->Pfat) { + DEBUG ((EFI_D_INFO, "PFAT Module is Enable\n")); + PfatConfig = CpuPlatformPolicyPpi->SecurityConfig->PfatConfig; + /// + /// Read PFAT Control Register + /// + MsrValue = AsmReadMsr64 (MSR_PLAT_FRMW_PROT_CTRL); + if (MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_LK) { + if (!(MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_EN)) { + /// + /// Reset required as the PFAT CTRL MSR is locked and needs to be toggled + /// + ResetRequired = TRUE; + } + } else { +#ifdef PFAT_EC_FLAG + if ((PfatConfig->Ppdt.PlatAttr & EC_PRESENT) && (PfatConfig->Ppdt.PlatAttr & EC_PFAT_PROTECTED)) { + DEBUG ((EFI_D_INFO, "EC is Present and EC FW supports PFAT\n")); + CpuIo = (**PeiServices).CpuIo; + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + Status = SendKscCommand (PeiServices, CpuIo, StallPpi, PfatConfig->EcCmdProvisionEav); + if (Status == EFI_SUCCESS) { + EphemeralAuthValue = RandomNumber (); + for (i = 0; (i < (sizeof (EphemeralAuthValue))); i++) { + Status = SendKscData (PeiServices, CpuIo, StallPpi, (UINT8) ((EphemeralAuthValue >> (i * 8)) & 0xFF)); + } + Status = ReceiveKscData (PeiServices, CpuIo, StallPpi, &EcStatus); + if (EcStatus != 0) { + ResetRequired = TRUE; + } + AsmWriteMsr32 (MSR_PLAT_FRMW_PROT_PASSWD, EphemeralAuthValue); + EphemeralAuthValue = 0; + Status = SendKscCommand (PeiServices, CpuIo, StallPpi, PfatConfig->EcCmdLock); + } + } +#endif //PFAT_EC_FLAG + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_0, PfatConfig->PpdtHash[0]); + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_1, PfatConfig->PpdtHash[1]); + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_2, PfatConfig->PpdtHash[2]); + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_3, PfatConfig->PpdtHash[3]); + MsrValue |= (B_MSR_PLAT_FRMW_PROT_CTRL_LK | B_MSR_PLAT_FRMW_PROT_CTRL_EN); + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_CTRL, MsrValue); + } + /// + /// Create PFAT HOB + /// + if (!ResetRequired) { + Status = (*PeiServices)->CreateHob (PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, sizeof (PFAT_HOB), (VOID **) &PfatHobPtr); + PfatHobPtr->EfiHobGuidType.Name = PfatHobGuid; + CopyMem (&PfatHobPtr->Ppdt, &PfatConfig->Ppdt, PfatConfig->Ppdt.PpdtSize); + CopyMem (&PfatHobPtr->PupHeader, &PfatConfig->PupHeader, sizeof (PUP_HEADER)); + CopyMem (&PfatHobPtr->PfatLog, &PfatConfig->PfatLog, sizeof (PFAT_LOG)); + PfatHobPtr->NumSpiComponents = PfatConfig->NumSpiComponents; + for (i = 0; i < PfatConfig->NumSpiComponents; i++) { + PfatHobPtr->ComponentSize[i] = PfatConfig->ComponentSize[i]; + } + } + } else { + DEBUG ((EFI_D_INFO, "PFAT Module is Disabled\n")); + MsrValue = AsmReadMsr64 (MSR_PLAT_FRMW_PROT_CTRL); + if (MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_LK) { + if (MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_EN) { + /// + /// Reset required as the PFAT CTRL MSR is locked and needs to be toggled + /// + ResetRequired = TRUE; + } + } else { + MsrValue &= ~B_MSR_PLAT_FRMW_PROT_CTRL_EN; + MsrValue |= B_MSR_PLAT_FRMW_PROT_CTRL_LK; + AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_CTRL, MsrValue); + } + } + + if (ResetRequired) { + /// + /// Perform Cold Reset + /// + DEBUG ((EFI_D_INFO, "Reset Required. Performing Cold Reset to unlock PFAT CONTROL MSR\n")); + PerformWarmORColdReset (PeiServices, COLDRESET); + } + + return; +} |