summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c')
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c191
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;
+}