summaryrefslogtreecommitdiff
path: root/ReferenceCode/ME/Heci/Dxe/Hecidrv.c
diff options
context:
space:
mode:
Diffstat (limited to 'ReferenceCode/ME/Heci/Dxe/Hecidrv.c')
-rw-r--r--ReferenceCode/ME/Heci/Dxe/Hecidrv.c1540
1 files changed, 1540 insertions, 0 deletions
diff --git a/ReferenceCode/ME/Heci/Dxe/Hecidrv.c b/ReferenceCode/ME/Heci/Dxe/Hecidrv.c
new file mode 100644
index 0000000..b34ea6f
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Dxe/Hecidrv.c
@@ -0,0 +1,1540 @@
+/** @file
+ HECI driver
+
+@copyright
+ Copyright (c) 2007 - 2013 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 "HeciDrv.h"
+#include "HeciHpet.h"
+#include "HeciCore.h"
+#include "MeLib.h"
+#include "EfiScriptLib.h"
+#include "PchPlatformLib.h"
+
+#include EFI_GUID_DEFINITION (MePlatformReadyToBoot)
+#include EFI_GUID_DEFINITION (MeBiosExtensionSetup)
+#include EFI_PROTOCOL_DEFINITION (MeplatformPolicy)
+#include EFI_PROTOCOL_DEFINITION (AmtReadyToBoot)
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+
+extern DXE_ME_POLICY_PROTOCOL *mDxePlatformMePolicy;
+
+#ifdef TCG_SUPPORT_FLAG
+#include "Acpi1_0.h"
+#include "Acpi2_0.h"
+#include "Acpi3_0.h"
+#include EFI_PROTOCOL_DEFINITION (TcgService)
+#include "TpmPc.h"
+#endif // TCG_SUPPORT_FLAG
+#endif // EDK_RELEASE_VERSION
+#define ONE_SECOND_TIMEOUT 1000000
+#define FWU_TIMEOUT 90
+
+//
+// Global driver data
+//
+HECI_INSTANCE *mHeciContext;
+EFI_HANDLE mHeciDrv;
+EFI_EVENT mExitBootServicesEvent;
+EFI_EVENT mLegacyBootEvent;
+DXE_MBP_DATA_PROTOCOL mMbpData;
+
+/**
+ This function provides a standard way to verify the HECI cmd and MBAR regs
+ in its PCI cfg space are setup properly and that the local mHeciContext
+ variable matches this info.
+
+ @param[in] None.
+
+ @retval UINT64 HeciMar address
+**/
+UINT64
+CheckAndFixHeciForAccess (
+ VOID
+ )
+{
+ ///
+ /// Read HECI_MBAR in case it has changed
+ ///
+ ///
+ /// Check if Base register is 64 bits wide.
+ ///
+ if (HeciPciRead32 (R_HECIMBAR) & 0x4) {
+ mHeciContext->HeciMBAR = (((UINT64) HeciPciRead32 (R_HECIMBAR + 4) << 32) |
+ (UINT64) HeciPciRead32 (R_HECIMBAR)) & 0xFFFFFFF0;
+ } else {
+ mHeciContext->HeciMBAR = (UINT64) HeciPciRead32 (R_HECIMBAR) & 0xFFFFFFF0;
+ }
+ ///
+ /// Check if HECI_MBAR is disabled
+ ///
+ if ((HeciPciRead8 (PCI_COMMAND_OFFSET) & (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER)) !=
+ (EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER)
+ ) {
+ ///
+ /// If cmd reg in pci cfg space is not turned on turn it on.
+ ///
+ HeciPciOr8 (
+ PCI_COMMAND_OFFSET,
+ EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER
+ );
+ }
+
+ return mHeciContext->HeciMBAR;
+}
+
+/**
+ Enable Hpet function.
+
+ @param[in] None.
+
+ @retval None
+**/
+VOID
+EnableHpet (
+ VOID
+ )
+{
+ VOLATILE UINT32 *HpetConfigReg;
+
+ HpetConfigReg = NULL;
+ ///
+ /// Get the High Precision Event Timer base address and enable the memory range
+ ///
+ HpetConfigReg = (UINT32 *) (UINTN) (PCH_RCRB_BASE + R_PCH_RCRB_HPTC);
+ switch (*HpetConfigReg & B_PCH_RCRB_HPTC_AS) {
+ case 0:
+ mHeciContext->HpetTimer = (VOID *) (UINTN) (HPET_ADDRESS_0);
+ break;
+
+ case 1:
+ mHeciContext->HpetTimer = (VOID *) (UINTN) (HPET_ADDRESS_1);
+ break;
+
+ case 2:
+ mHeciContext->HpetTimer = (VOID *) (UINTN) (HPET_ADDRESS_2);
+ break;
+
+ case 3:
+ mHeciContext->HpetTimer = (VOID *) (UINTN) (HPET_ADDRESS_3);
+ break;
+
+ default:
+ mHeciContext->HpetTimer = NULL;
+ break;
+ }
+ ///
+ /// Read this back to force the write-back.
+ ///
+ *HpetConfigReg = *HpetConfigReg | B_PCH_RCRB_HPTC_AE;
+
+ ///
+ /// Start the timer so it is up and running
+ ///
+ mHeciContext->HpetTimer[HPET_GEN_CONFIG_LOW] = HPET_START;
+ mHeciContext->HpetTimer[HPET_GEN_CONFIG_LOW] = HPET_START;
+
+ return ;
+}
+
+#ifdef TCG_SUPPORT_FLAG
+
+/**
+ Perform measurement for HER register.
+
+ @param[in] HerValue The value of HECI Extend Register.
+ @param[in] Index HerValue Size.
+
+ @retval EFI_SUCCESS Measurement performed
+**/
+EFI_STATUS
+MeasureHer (
+ IN UINT32 *HerValue,
+ IN UINT8 Index
+ )
+{
+ EFI_STATUS Status;
+ EFI_TCG_PROTOCOL *TcgProtocol;
+ EFI_TCG_PCR_EVENT TcgEvent;
+ UINT32 EventNumber;
+ EFI_PHYSICAL_ADDRESS EventLogLastEntry;
+
+ Status = gBS->LocateProtocol (
+ &gEfiTcgProtocolGuid,
+ NULL,
+ (VOID **) &TcgProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// This below data will be stored in Tcg eventlog
+ ///
+ TcgEvent.Event.PostCode.PostCodeAddress = *HerValue;
+ TcgEvent.Event.PostCode.PostCodeLength = sizeof (UINT32);
+
+ ///
+ /// Fill the TcgEvent Header
+ ///
+ TcgEvent.Header.PCRIndex = PCRi_CRTM_AND_POST_BIOS;
+ TcgEvent.Header.EventType = EV_S_CRTM_CONTENTS;
+
+ TcgEvent.Header.EventDataSize = (Index * sizeof (UINT32));
+
+ Status = TcgProtocol->HashLogExtendEvent (
+ TcgProtocol,
+ (EFI_PHYSICAL_ADDRESS) HerValue,
+ TcgEvent.Header.EventDataSize,
+ TPM_ALG_SHA,
+ (TCG_PCR_EVENT *) &TcgEvent,
+ &EventNumber,
+ &EventLogLastEntry
+ );
+ return Status;
+}
+
+/**
+ Me Measurement.
+
+ @param[in] None.
+
+ @retval EFI_NOT_READY Not ready for measurement.
+ @retval EFI_SUCCESS Measurement done
+**/
+EFI_STATUS
+MeMeasurement (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ DATA32_UNION Data32[7];
+ UINT8 HerMax;
+ UINT8 HerIndex;
+ UINT8 Index;
+
+ Index = 0;
+ ///
+ /// Measure HER
+ ///
+ HerMax = R_ME_HER5;
+ Data32[Index].Data32 = PciRead32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, HECI_FUNCTION_NUMBER, R_ME_HERS));
+
+ if ((Data32[Index].Data32 & B_ME_EXTEND_REG_VALID) == B_ME_EXTEND_REG_VALID) {
+ if ((Data32[Index].Data8[0] & B_ME_EXTEND_REG_ALGORITHM) == V_ME_SHA_256) {
+ HerMax = R_ME_HER8;
+ }
+
+ for (HerIndex = R_ME_HER1, Index = 0; HerIndex <= HerMax; HerIndex += 4, Index++) {
+ Data32[Index].Data32 = PciRead32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, HECI_FUNCTION_NUMBER, HerIndex));
+ }
+
+ Status = MeasureHer (&Data32->Data32, Index);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "ME Measurement feature failed, Status is %r \n", Status));
+ }
+ } else {
+ Status = EFI_NOT_READY;
+ }
+
+ return Status;
+}
+
+/**
+ Signal a event for last checking.
+
+ @param[in] Event The event that triggered this notification function
+ @param[in] Context Pointer to the notification functions context
+
+ @retval EFI_SUCCESS Event excuted and closed.
+**/
+EFI_STATUS
+MeMeasurementEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ MeMeasurement ();
+
+ gBS->CloseEvent (Event);
+
+ return EFI_SUCCESS;
+}
+#endif
+
+/**
+ Show warning message to user.
+
+ @param[in] None.
+
+ @retval EFI_SUCCESS Warning reported
+**/
+EFI_STATUS
+MeWarningMessage (
+ VOID
+ )
+{
+ HECI_FWS_REGISTER MeFirmwareStatus;
+
+ MeFirmwareStatus.ul = HeciPciRead32 (R_FWSTATE);
+
+ ///
+ /// Check for ME FPT Bad & FT BUP LD FLR
+ ///
+ if (MeFirmwareStatus.r.FptBad != 0 || MeFirmwareStatus.r.FtBupLdFlr != 0) {
+ MeReportError (MSG_ME_FW_UPDATE_FAILED);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Store the current value of DEVEN for S3 resume path
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+DeviceStatusSave (
+ VOID
+ )
+{
+ UINT32 Data;
+
+ ///
+ /// Read RCBA register for saving
+ ///
+ Data = Mmio16 (PCH_RCRB_BASE, R_PCH_RCRB_FD2);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PCH_RCRB_BASE + R_PCH_RCRB_FD2),
+ 1,
+ &Data
+ );
+ Data = Mmio16 (PCH_RCRB_BASE, R_PCH_RCRB_FDSW);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PCH_RCRB_BASE + R_PCH_RCRB_FDSW),
+ 1,
+ &Data
+ );
+}
+
+/**
+ ME BWG 1.0 5.3.1.1: IDER Workaround, perform this only when IDER device is present.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+PerformIderWorkaround (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 BaseAddress;
+ UINT64 BaseAddress2;
+ UINT64 Index;
+ BOOLEAN WorkaroundFlag;
+
+ WorkaroundFlag = TRUE;
+
+ Status = gDS->AllocateIoSpace (
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdIoTypeIo,
+ 4,
+ 0x10,
+ &BaseAddress,
+ mHeciDrv,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Program BAR4
+ ///
+ PciWrite32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x20), (UINT32) BaseAddress);
+
+ ///
+ /// Enable IDER IOE
+ ///
+ PciOr8 (
+ PCI_LIB_ADDRESS (ME_BUS,
+ ME_DEVICE_NUMBER,
+ IDER_FUNCTION_NUMBER,
+ PCI_COMMAND_OFFSET),
+ EFI_PCI_COMMAND_IO_SPACE
+ );
+
+ ///
+ /// Perform the workaround if offset 3 bit 0 is not set
+ ///
+ if ((IoRead8 ((UINTN) BaseAddress + 3) & 0x01) == 00) {
+ Status = gDS->AllocateIoSpace (
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdIoTypeIo,
+ 4,
+ 0x10,
+ &BaseAddress2,
+ mHeciDrv,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ PciWrite32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x10), (UINT32) BaseAddress2);
+ ///
+ /// check all ports to make sure all are 0x7f before running the workaround
+ ///
+ for (Index = 0; Index <= 7; Index++) {
+ if (IoRead8 ((UINTN) BaseAddress2 + (UINTN) Index) != 0x7f) {
+ WorkaroundFlag = FALSE;
+ break;
+ }
+ }
+ ///
+ /// Disable IDER IOE and clear BAR0 and BAR4
+ ///
+ PciAnd8 (
+ PCI_LIB_ADDRESS (ME_BUS,
+ ME_DEVICE_NUMBER,
+ IDER_FUNCTION_NUMBER,
+ PCI_COMMAND_OFFSET),
+ (UINT8)~EFI_PCI_COMMAND_IO_SPACE
+ );
+ PciWrite32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x10), 0);
+ PciWrite32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x20), 0);
+
+ if (WorkaroundFlag) {
+ IderDisable ();
+ }
+
+ gDS->FreeIoSpace (BaseAddress2, (UINT64) 0x10);
+ } else {
+ PciAnd8 (
+ PCI_LIB_ADDRESS (ME_BUS,
+ ME_DEVICE_NUMBER,
+ IDER_FUNCTION_NUMBER,
+ PCI_COMMAND_OFFSET),
+ (UINT8)~EFI_PCI_COMMAND_IO_SPACE
+ );
+ PciWrite32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x20), 0);
+ }
+
+ gDS->FreeIoSpace (BaseAddress, (UINT64) 0x10);
+ return ;
+}
+
+/**
+ Disable ME Devices when needed
+
+ @param[in] None
+
+ @retval EFI_SUCCESS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+MeDeviceConfigure (
+ VOID
+ )
+{
+ UINT32 MeMode;
+ UINT16 VendorID;
+ UINT16 DeviceID;
+
+ HeciGetMeMode (&MeMode);
+ if (MeMode == ME_MODE_NORMAL) {
+ if (mHeciContext->MeFwImageType != INTEL_ME_5MB_FW) {
+ ///
+ /// We will disable all AMT relevant devices in 1.5M SKU
+ ///
+ IderDisable ();
+ SolDisable ();
+ Usbr1Disable ();
+ Usbr2Disable ();
+ } else {
+ ///
+ /// ME BWG 1.0 5.3.1.1: IDER Workaround, perform this only when IDER device is present.
+ ///
+ VendorID = PciRead16 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x00));
+ DeviceID = PciRead16 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, IDER_FUNCTION_NUMBER, 0x02));
+ if ((VendorID == V_ME_IDER_VENDOR_ID) && IS_PCH_LPT_IDER_DEVICE_ID(DeviceID)
+ ) {
+ PerformIderWorkaround ();
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send ME the BIOS end of Post message.
+
+ @param[in] None.
+
+ @retval EFI_SUCCESS Always return EFI_SUCCESS except for policy initization failure.
+ @exception EFI_UNSUPPORTED Policy initization failure.
+**/
+EFI_STATUS
+MeEndOfPostEvent (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HECI_PROTOCOL *Heci;
+ UINT32 MeStatus;
+ UINT8 EopSendRetries;
+ UINT32 HECI_BASE_ADDRESS;
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+ VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr;
+
+ //
+ // Init ME Policy Library, continue to send EOP message even if can't find Me Platform Policy
+ //
+ if (mDxePlatformMePolicy == NULL) {
+ MePolicyLibInit ();
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiHeciProtocolGuid,
+ NULL,
+ (VOID **) &Heci
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Send EOP message when ME is ready. Do not care about if ME FW INIT is completed.
+ ///
+ Status = Heci->GetMeStatus (&MeStatus);
+ ASSERT_EFI_ERROR (Status);
+
+ if (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY) {
+
+ if (MeEndOfPostEnabled ()) {
+ DEBUG ((EFI_D_INFO, "Sending EOP...\n"));
+
+ //
+ // Initialize pointers to control registers
+ //
+ HECI_BASE_ADDRESS = PciRead32 (PCI_LIB_ADDRESS (ME_BUS, ME_DEVICE_NUMBER, HECI_FUNCTION_NUMBER, R_HECIMBAR)) & 0xFFFFFFF0;
+ HeciRegHCsrPtr = (VOID *) (UINTN) (HECI_BASE_ADDRESS + H_CSR);
+ HeciRegMeCsrHaPtr = (VOID *) (UINTN) (HECI_BASE_ADDRESS + ME_CSR_HA);
+
+ for (EopSendRetries = 0; EopSendRetries <= MAX_EOP_SEND_RETRIES; EopSendRetries++) {
+
+ Status = HeciSendEndOfPostMessage (mHeciDrv);
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+
+ MeReportError (MSG_EOP_ERROR);
+
+ //
+ // Set H_RST and H_IG bits to reset HECI
+ //
+ HeciRegHCsr.ul = HeciRegHCsrPtr->ul;
+ HeciRegHCsr.r.H_RST = 1;
+ HeciRegHCsr.r.H_IG = 1;
+ HeciRegHCsrPtr->ul = HeciRegHCsr.ul;
+
+ //
+ // Wait for ME_RDY
+ //
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+
+ //
+ // Clear H_RST, set H_RDY & H_IG bits
+ //
+ HeciRegHCsr.ul = HeciRegHCsrPtr->ul;
+ HeciRegHCsr.r.H_RST = 0;
+ HeciRegHCsr.r.H_IG = 1;
+ HeciRegHCsr.r.H_RDY = 1;
+ HeciRegHCsrPtr->ul = HeciRegHCsr.ul;
+ }
+
+ if (EFI_ERROR(Status)) {
+ //
+ // Send HECI_BUS_DISABLE
+ //
+ for (EopSendRetries = 0; EopSendRetries <= MAX_EOP_SEND_RETRIES; EopSendRetries++) {
+ Status = HeciDisableHeciBusMsg();
+ if (!EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
+ //
+ // Disable HECI function
+ //
+ HeciDisable();
+ Heci2Disable();
+ }
+
+ }
+ } else if (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_DISABLE_WAIT) {
+ MeReportError (MSG_PLAT_DISABLE_WAIT);
+ }
+
+ }
+
+ return Status;
+}
+
+/**
+ 1. Cf9Gr Lock Config
+ - PCH BIOS Spec Rev 0.9 Section 18.4 Additional Power Management Programming
+ Step 2
+ Set "Power Management Initialization Register (PMIR) Field 1", D31:F0:ACh[31] = 1b
+ for production machine according to "RS - PCH Intel Management Engine
+ (Intel(r) ME) BIOS Writer's Guide".
+ 2. Function Disable SUS Well Lock
+ - PCH EDS 10.1.76 request that FDSW must be set when Intel Active Management Technology
+ is Enabled
+
+ @param[in] None
+
+ @retval Status.
+**/
+EFI_STATUS
+LockConfig (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HECI_PROTOCOL *Heci;
+ UINT32 MeMode;
+ HECI_FWS_REGISTER MeFirmwareStatus;
+ UINTN Address;
+ UINT32 Data;
+
+ Status = gBS->LocateProtocol (
+ &gEfiHeciProtocolGuid,
+ NULL,
+ (VOID **) &Heci
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check ME Status
+ ///
+ Status = Heci->GetMeMode (&MeMode);
+ ASSERT_EFI_ERROR (Status);
+
+ MeFirmwareStatus.ul = HeciPciRead32 (R_FWSTATE);
+
+ ///
+ /// PCH BIOS Spec Rev 0.9 Section 18.4 Additional Power Management Programming
+ /// Step 2
+ /// Set "Power Management Initialization Register (PMIR) Field 1", D31:F0:ACh[31] = 1b
+ /// for production machine according to "RS - PCH Intel Management Engine
+ /// (Intel(r) ME) BIOS Writer's Guide".
+ ///
+ /// PCH ME BWG section 4.5.1
+ /// The IntelR FPT tool /GRST option uses CF9GR bit to trigger global reset.
+ /// Based on above reason, the BIOS should not lock down CF9GR bit during Manufacturing and
+ /// Re-manufacturing environment.
+ ///
+ Data = 0;
+ if ((((MeMode == ME_MODE_NORMAL) || (MeMode == ME_MODE_TEMP_DISABLED)) && !(MeFirmwareStatus.r.ManufacturingMode))) {
+ ///
+ /// PCH ME BWG section 4.4.1
+ /// BIOS must also ensure that CF9GR is cleared and locked (via bit31 of the same register) before
+ /// handing control to the OS in order to prevent the host from issuing global resets and reseting
+ /// Intel Management Engine.
+ ///
+ Data |= B_PCH_LPC_PMIR_CF9LOCK;
+ }
+
+ Address = PCI_LIB_ADDRESS (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_PMIR
+ );
+ PciAndThenOr32 (
+ Address,
+ (UINT32) (~(B_PCH_LPC_PMIR_CF9LOCK | B_PCH_LPC_PMIR_CF9GR)),
+ (UINT32) Data
+ );
+
+ ///
+ /// Function Disable SUS Well lockdown
+ ///
+ if (MeMode == ME_MODE_NORMAL) {
+ if (mHeciContext->MeFwImageType == INTEL_ME_5MB_FW) {
+ DEBUG ((EFI_D_ERROR, "Function Disable SUS Well lockdown!\n"));
+ FunctionDisableWellLockdown ();
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Halt Boot for up to 90 seconds if Bit 11 of FW Status Register (FW_UPD_IN_PROGRESS) is set
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+CheckFwUpdInProgress (
+ VOID
+ )
+{
+ HECI_FWS_REGISTER FwStatus;
+ UINT8 StallCount;
+ EFI_STATUS Status;
+
+ StallCount = 0;
+ Status = mHeciContext->HeciCtlr.GetMeStatus (&FwStatus.ul);
+ if (!EFI_ERROR (Status)) {
+ if (FwStatus.ul & ME_FW_UPDATES_IN_PROGRESS) {
+ MeReportError (MSG_ME_FW_UPDATE_WAIT);
+ }
+
+ while ((FwStatus.ul & ME_FW_UPDATES_IN_PROGRESS) && (StallCount < FWU_TIMEOUT)) {
+ gBS->Stall (ONE_SECOND_TIMEOUT);
+ StallCount = StallCount + 1;
+ Status = mHeciContext->HeciCtlr.GetMeStatus (&FwStatus.ul);
+ }
+ }
+
+ return ;
+}
+
+/**
+ Signal a event for Me ready to boot.
+
+ @param[in] Event The event that triggered this notification function
+ @param[in] Context Pointer to the notification functions context
+
+ @retval None
+**/
+VOID
+EFIAPI
+MeReadyToBootEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT MePlatformReadyToBootEvent;
+ EFI_HANDLE *Handles;
+ UINTN Index;
+ UINTN Count;
+ AMT_READY_TO_BOOT_PROTOCOL *AmtReadyToBoot;
+ UINT32 MeMode;
+ UINT32 MeStatus;
+#ifdef TCG_SUPPORT_FLAG
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+
+ Status = MeMeasurement ();
+ if (Status == EFI_NOT_READY) {
+ ///
+ /// Create a Legacy Boot event.
+ ///
+ Status = EfiCreateEventLegacyBootEx (
+ EFI_TPL_CALLBACK,
+ MeMeasurementEvent,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Create a ExitBootService event.
+ ///
+ Status = gBS->CreateEvent (
+ EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ EFI_TPL_CALLBACK,
+ MeMeasurementEvent,
+ NULL,
+ &ExitBootServicesEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+#endif //TCG_SUPPORT_FLAG
+ ///
+ /// PCH BIOS Spec Rev 0.8.0, Section 22.8.3.1 ASPM on DMI and the PCI Express Root Ports
+ /// Step g
+ /// Issue "WRITE_ICC_REGISTER" MEI message to program ICC register offset 0x4 with 0x000999999
+ /// This is always needed for PCIE with hotplug on and off and PCIE RP enabled and disabled.
+ ///
+ if(GetPchSeries() == PchLp) {
+ Status = HeciWriteIccRegDword(0x0004, 0x00999999, ICC_RESPONSE_MODE_SKIP);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Heci writes to TMCSRCCLK failed. Status = %X\n", Status));
+ }
+ }
+
+ ///
+ /// We will trigger all events in order
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gAmtReadyToBootProtocolGuid,
+ NULL,
+ &Count,
+ &Handles
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < Count; Index++) {
+ Status = gBS->HandleProtocol (Handles[Index], &gAmtReadyToBootProtocolGuid, (VOID **) &AmtReadyToBoot);
+ ASSERT_EFI_ERROR (Status);
+ AmtReadyToBoot->Signal ();
+ }
+ }
+
+ Status = gBS->CreateEventEx (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ MeEmptyEvent,
+ NULL,
+ &gMePlatformReadyToBootGuid,
+ &MePlatformReadyToBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ gBS->SignalEvent (MePlatformReadyToBootEvent);
+ gBS->CloseEvent (MePlatformReadyToBootEvent);
+ }
+
+ HeciGetMeMode (&MeMode);
+ HeciGetMeStatus (&MeStatus);
+ if ((MeMode == ME_MODE_NORMAL) &&
+ ((ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_IN_RECOVERY_MODE) || (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY))
+ ) {
+
+ CheckFwUpdInProgress ();
+
+ Status = MeWarningMessage ();
+ ASSERT_EFI_ERROR (Status);
+
+ Status = MeEndOfPostEvent ();
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ ///
+ /// Set EndOfPostDone regardless whether the EOP msg was sent
+ ///
+ if (MeEndOfPostEnabled ()) {
+ mDxePlatformMePolicy->MeConfig.EndOfPostDone = 1;
+ }
+
+ ///
+ /// PMIR Configuration & FDSW Lockdown
+ ///
+ Status = LockConfig ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Disable Heci2 if policy dictates
+ ///
+ Heci2Disable ();
+
+ ///
+ /// If ME Mode is running in ME Temp Disable state, disable Heci1, HECI2, Ider and Sol
+ ///
+ HeciGetMeMode (&MeMode);
+ if (MeMode == ME_MODE_TEMP_DISABLED) {
+ DisableAllMEDevices ();
+ }
+
+ gBS->CloseEvent (Event);
+
+ return;
+}
+
+/**
+ Signal a event to save Me relevant registers and this event must be run before ExitPmAuth.
+
+ @param[in] Event The event that triggered this notification function
+ @param[in] ParentImageHandle Pointer to the notification functions context
+
+ @retval None
+**/
+VOID
+EFIAPI
+MeScriptSaveEvent (
+ IN EFI_EVENT Event,
+ IN VOID *ParentImageHandle
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ EFI_HECI_PROTOCOL *Heci;
+ UINT32 MeMode;
+ HECI_FWS_REGISTER MeFirmwareStatus;
+ UINTN Address;
+ UINT32 Data;
+ UINT32 MebxSetupVariableAttributes;
+ UINTN MebxSetupVariableDataSize;
+ ME_BIOS_EXTENSION_SETUP MeBiosExtensionSetup;
+ const UINT8 Str5MBFw[sizeof (MEFW_5M_STRING)] = MEFW_5M_STRING;
+ EFI_MEBX_PROTOCOL *MebxProtocol;
+
+ INITIALIZE_SCRIPT (ParentImageHandle, gST);
+
+ ///
+ /// Check whether this is real ExitPmAuth notification, or just a SignalEvent
+ ///
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ ///
+ /// PMIR Configuration Save
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiHeciProtocolGuid,
+ NULL,
+ (VOID **) &Heci
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ ///
+ /// Check ME Status
+ ///
+ Status = Heci->GetMeMode (&MeMode);
+ ASSERT_EFI_ERROR (Status);
+
+ MeFirmwareStatus.ul = HeciPciRead32 (R_FWSTATE);
+
+ ///
+ /// Init ME Policy Library
+ ///
+ Status = MePolicyLibInit ();
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+#ifdef EFI_DEBUG
+ //
+ // Dump the ME platform policy
+ //
+ DxeMePolicyDebugDump ();
+#endif
+
+ ///
+ /// Report ME components version information to FVI
+ ///
+ InitFviDataHubCbContext (
+ mDxePlatformMePolicy->MeMiscConfig.FviSmbiosType,
+ (UINT8) mMeFviElements,
+ &mMeFviVersionData
+ );
+
+ mMeFviElementsData[EnumMeFw].Element.Version.MajorVersion = (UINT8) mMbpData.MeBiosPayload.FwVersionName.MajorVersion;
+ mMeFviElementsData[EnumMeFw].Element.Version.MinorVersion = (UINT8) mMbpData.MeBiosPayload.FwVersionName.MinorVersion;
+ mMeFviElementsData[EnumMeFw].Element.Version.Revision = (UINT8) mMbpData.MeBiosPayload.FwVersionName.HotfixVersion;
+ mMeFviElementsData[EnumMeFw].Element.Version.BuildNum = (UINT16) mMbpData.MeBiosPayload.FwVersionName.BuildVersion;
+ if (mMbpData.MeBiosPayload.FwPlatType.RuleData.Fields.IntelMeFwImageType == INTEL_ME_5MB_FW) {
+ CopyMem (mMeFviElementsData[EnumMeFw].Element.VerString, Str5MBFw, sizeof (MEFW_5M_STRING));
+ }
+ Status = gBS->LocateProtocol (&gEfiMebxProtocolGuid, NULL, (VOID **) &MebxProtocol);
+ if (!EFI_ERROR (Status)) {
+ mMeFviElementsData[EnumMebx].Element.Version.MajorVersion = (UINT8) MebxProtocol->MebxVersion.Major;
+ mMeFviElementsData[EnumMebx].Element.Version.MinorVersion = (UINT8) MebxProtocol->MebxVersion.Minor;
+ mMeFviElementsData[EnumMebx].Element.Version.Revision = (UINT8) MebxProtocol->MebxVersion.Hotfix;
+ mMeFviElementsData[EnumMebx].Element.Version.BuildNum = (UINT16) MebxProtocol->MebxVersion.Build;
+ }
+
+ CreateRcFviDatahub (&mMeFviVersionData);
+
+ ///
+ /// PCH BIOS Spec Rev 0.9 Section 18.4 Additional Power Management Programming
+ /// Step 2
+ /// Set "Power Management Initialization Register (PMIR) Field 1", D31:F0:ACh[31] = 1b
+ /// for production machine according to "RS - PCH Intel Management Engine
+ /// (Intel(r) ME) BIOS Writer's Guide".
+ ///
+ /// PCH ME BWG section 4.5.1
+ /// The IntelR FPT tool /GRST option uses CF9GR bit to trigger global reset.
+ /// Based on above reason, the BIOS should not lock down CF9GR bit during Manufacturing and
+ /// Re-manufacturing environment.
+ ///
+ Address = PCI_LIB_ADDRESS (
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_PMIR
+ );
+ Data = PciRead32 (Address);
+ Data &= (UINT32) (~(B_PCH_LPC_PMIR_CF9LOCK | B_PCH_LPC_PMIR_CF9GR));
+
+ if ((((MeMode == ME_MODE_NORMAL) || (MeMode == ME_MODE_TEMP_DISABLED)) && !(MeFirmwareStatus.r.ManufacturingMode))) {
+ ///
+ /// PCH ME BWG section 4.4.1
+ /// BIOS must also ensure that CF9GR is cleared and locked (via bit31 of the same register) before
+ /// handing control to the OS in order to prevent the host from issuing global resets and reseting
+ /// Intel Management Engine.
+ ///
+ Data |= (UINT32) (B_PCH_LPC_PMIR_CF9LOCK);
+ }
+#ifdef SUS_WELL_RESTORE
+ ///
+ /// PMIR is a resume well register and has no script save for it.
+ /// System may go through S3 resume path from G3 if RapidStart is enabled,
+ /// that means all resume well registers will be reset to defaults.
+ /// Save boot script for PMIR register if RapidStart is enabled.
+ ///
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) MmPciAddress (0x0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_PMIR),
+ 1,
+ &Data
+ );
+#endif
+ ///
+ ///
+ /// Read RCBA register for saving
+ ///
+ Data = Mmio16 (PCH_RCRB_BASE, R_PCH_RCRB_FD2);
+ ///
+ /// Disable Heci2 if policy dictates
+ ///
+ Data |= (BIT0 << HECI2);
+
+ ///
+ /// If ME Mode is running in ME Temp Disable state, disable Heci1, HECI2, Ider and Sol
+ ///
+ if ((MeMode == ME_MODE_TEMP_DISABLED) || (MeMode == ME_MODE_SECOVER)) {
+ Data |= ((BIT0 << HECI1) + (BIT0 << HECI2) + (BIT0 << IDER) + (BIT0 << SOL));
+ }
+
+ if (MeMode == ME_MODE_NORMAL) {
+ if (mHeciContext->MeFwImageType == INTEL_ME_1_5MB_FW) {
+ ///
+ /// We will disable HECI2, Ider and Sol in 1.5M SKU
+ ///
+ Data |= ((BIT0 << HECI2) + (BIT0 << IDER) + (BIT0 << SOL));
+ } else if (mHeciContext->MeFwImageType == INTEL_ME_5MB_FW) {
+ MebxSetupVariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_NON_VOLATILE;
+ MebxSetupVariableDataSize = sizeof (ME_BIOS_EXTENSION_SETUP);
+
+ Status = gST->RuntimeServices->GetVariable (
+ gEfiMeBiosExtensionSetupName,
+ &gEfiMeBiosExtensionSetupGuid,
+ &MebxSetupVariableAttributes,
+ &MebxSetupVariableDataSize,
+ &MeBiosExtensionSetup
+ );
+ if (!EFI_ERROR (Status)) {
+ if ((MeBiosExtensionSetup.AmtSolIder & SOL_ENABLE) == 0) {
+ Data |= (BIT0 << SOL);
+ }
+
+ if ((MeBiosExtensionSetup.AmtSolIder & IDER_ENABLE) == 0) {
+ Data |= (BIT0 << IDER);
+ }
+ }
+ }
+ }
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PCH_RCRB_BASE + R_PCH_RCRB_FD2),
+ 1,
+ &Data
+ );
+ ///
+ /// Function Disable SUS Well lockdown
+ ///
+ Data = Mmio16 (PCH_RCRB_BASE, R_PCH_RCRB_FDSW);
+
+ if (MeMode == ME_MODE_NORMAL) {
+ if (mHeciContext->MeFwImageType == INTEL_ME_5MB_FW) {
+ Data |= B_PCH_RCRB_FDSW_FDSWL;
+ }
+ }
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint16,
+ (UINTN) (PCH_RCRB_BASE + R_PCH_RCRB_FDSW),
+ 1,
+ &Data
+ );
+
+ gBS->CloseEvent (Event);
+ return;
+}
+
+/**
+ Send Get Firmware SKU Request to ME
+
+ @param[out] FwCapsSku Return FwCapsSku mask for Get Firmware Capability SKU
+
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support this function
+ @retval EFI_SUCCESS Command succeeded
+ @retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
+ @retval EFI_TIMEOUT HECI does not return the buffer before timeout
+ @retval EFI_BUFFER_TOO_SMALL Message Buffer is too smallfor the Acknowledge
+**/
+EFI_STATUS
+MbpGetFwCapsSkuThroughHeci (
+ OUT MEFWCAPS_SKU *FwCapsSku
+ )
+{
+ EFI_STATUS Status;
+ GEN_GET_FW_CAPS_SKU_BUFFER MsgGenGetFwCapsSku;
+ UINT32 Length;
+ UINT32 RespLength;
+
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Data = 0;
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Fields.GroupId = MKHI_FWCAPS_GROUP_ID;
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Fields.Command = FWCAPS_GET_RULE_CMD;
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Fields.IsResponse = 0;
+ MsgGenGetFwCapsSku.Request.Data.RuleId = 0;
+ Length = sizeof (GEN_GET_FW_CAPSKU);
+ RespLength = sizeof(GEN_GET_FW_CAPS_SKU_ACK);
+
+ ///
+ /// Send Get FW SKU Request to ME
+ ///
+ Status = HeciSendwACK (
+ (UINT32 *) &MsgGenGetFwCapsSku,
+ Length,
+ &RespLength,
+ BIOS_FIXED_HOST_ADDR,
+ HECI_CORE_MESSAGE_ADDR
+ );
+
+ if (!EFI_ERROR(Status) &&
+ ((MsgGenGetFwCapsSku.Response.MKHIHeader.Fields.Command) == FWCAPS_GET_RULE_CMD) &&
+ ((MsgGenGetFwCapsSku.Response.MKHIHeader.Fields.IsResponse) == 1) &&
+ (MsgGenGetFwCapsSku.Response.MKHIHeader.Fields.Result == 0)
+ ) {
+ *FwCapsSku = MsgGenGetFwCapsSku.Response.Data.FWCapSku;
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Send Get Platform Type Request to ME
+
+ @param[in] RuleData PlatformBrand,
+ IntelMeFwImageType,
+ SuperSku,
+ PlatformTargetMarketType,
+ PlatformTargetUsageType
+
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support this function
+ @retval EFI_SUCCESS Command succeeded
+ @retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
+ @retval EFI_TIMEOUT HECI does not return the buffer before timeout
+ @retval EFI_BUFFER_TOO_SMALL Message Buffer is too smallfor the Acknowledge
+**/
+EFI_STATUS
+MbpGetPlatformTypeThroughHeci (
+ OUT PLATFORM_TYPE_RULE_DATA *RuleData
+ )
+{
+ EFI_STATUS Status;
+ GEN_GET_PLATFORM_TYPE_BUFFER MsgGenGetPlatformType;
+ UINT32 Length;
+ UINT32 RespLength;
+
+ MsgGenGetPlatformType.Request.MKHIHeader.Data = 0;
+ MsgGenGetPlatformType.Request.MKHIHeader.Fields.GroupId = MKHI_FWCAPS_GROUP_ID;
+ MsgGenGetPlatformType.Request.MKHIHeader.Fields.Command = FWCAPS_GET_RULE_CMD;
+ MsgGenGetPlatformType.Request.MKHIHeader.Fields.IsResponse = 0;
+ MsgGenGetPlatformType.Request.Data.RuleId = 0x1D;
+ Length = sizeof (GEN_GET_PLATFORM_TYPE);
+ RespLength = sizeof(GEN_GET_PLATFORM_TYPE_ACK);
+
+ ///
+ /// Send Get FW SKU Request to ME
+ ///
+ Status = HeciSendwACK (
+ (UINT32 *) &MsgGenGetPlatformType,
+ Length,
+ &RespLength,
+ BIOS_FIXED_HOST_ADDR,
+ HECI_CORE_MESSAGE_ADDR
+ );
+
+ if (!EFI_ERROR(Status) &&
+ ((MsgGenGetPlatformType.Response.MKHIHeader.Fields.Command) == FWCAPS_GET_RULE_CMD) &&
+ ((MsgGenGetPlatformType.Response.MKHIHeader.Fields.IsResponse) == 1) &&
+ (MsgGenGetPlatformType.Response.MKHIHeader.Fields.Result == 0)
+ ) {
+ *RuleData = MsgGenGetPlatformType.Response.Data.RuleData;
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Send Get Firmware Features State Request to ME
+
+ @param[out] FwFeaturesState Return FwFeaturesState mask for Get Firmware Features State
+
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support this function
+ @retval EFI_SUCCESS Command succeeded
+ @retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
+ @retval EFI_TIMEOUT HECI does not return the buffer before timeout
+ @retval EFI_BUFFER_TOO_SMALL Message Buffer is too smallfor the Acknowledge
+**/
+EFI_STATUS
+MbpGetFwFeaturesStateThroughHeci (
+ OUT MEFWCAPS_SKU *FwFeaturesState
+ )
+{
+ EFI_STATUS Status;
+ GEN_GET_FW_CAPS_SKU_BUFFER MsgGenGetFwCapsSku;
+ UINT32 Length;
+ UINT32 RespLength;
+
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Data = 0;
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Fields.GroupId = MKHI_FWCAPS_GROUP_ID;
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Fields.Command = FWCAPS_GET_RULE_CMD;
+ MsgGenGetFwCapsSku.Request.MKHIHeader.Fields.IsResponse = 0;
+ MsgGenGetFwCapsSku.Request.Data.RuleId = 0x20;
+ Length = sizeof (GEN_GET_FW_CAPSKU);
+ RespLength = sizeof(GEN_GET_FW_CAPS_SKU_ACK);
+
+ ///
+ /// Send Get FW SKU Request to ME
+ ///
+ Status = HeciSendwACK (
+ (UINT32 *) &MsgGenGetFwCapsSku,
+ Length,
+ &RespLength,
+ BIOS_FIXED_HOST_ADDR,
+ HECI_CORE_MESSAGE_ADDR
+ );
+
+ if (!EFI_ERROR(Status) &&
+ ((MsgGenGetFwCapsSku.Response.MKHIHeader.Fields.Command) == FWCAPS_GET_RULE_CMD) &&
+ ((MsgGenGetFwCapsSku.Response.MKHIHeader.Fields.IsResponse) == 1) &&
+ (MsgGenGetFwCapsSku.Response.MKHIHeader.Fields.Result == 0)
+ ) {
+ *FwFeaturesState = MsgGenGetFwCapsSku.Response.Data.FWCapSku;
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Install MbpData protocol.
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+InstallMbpDataProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MeMode;
+ UINT32 MeStatus;
+ MEFWCAPS_SKU FwCapsSku;
+ PLATFORM_TYPE_RULE_DATA RuleData;
+
+ ZeroMem (&mMbpData, sizeof (DXE_MBP_DATA_PROTOCOL));
+
+ HeciGetMeMode (&MeMode);
+
+ mMbpData.Revision = DXE_MBP_DATA_PROTOCOL_REVISION_2;
+
+ PERF_START_EX (NULL, EVENT_REC_TOK, NULL, AsmReadTsc (), 0x8010);
+ Status = PrepareMeBiosPayload (&mMbpData.MeBiosPayload);
+ PERF_END_EX (NULL, EVENT_REC_TOK, NULL, AsmReadTsc (), 0x8011);
+
+ if (!EFI_ERROR (Status)) {
+ HeciGetMeStatus (&MeStatus);
+ HeciGetMeMode (&MeMode);
+
+ if (mMbpData.MeBiosPayload.FwCapsSku.Available == 0) {
+ if ((MeMode == ME_MODE_NORMAL) &&
+ (
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_IN_RECOVERY_MODE) ||
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY)
+ )
+ ) {
+ Status = MbpGetFwCapsSkuThroughHeci (&FwCapsSku);
+ if (!EFI_ERROR (Status)) {
+ mMbpData.MeBiosPayload.FwCapsSku.FwCapabilities.Data = FwCapsSku.Data;
+ mMbpData.MeBiosPayload.FwCapsSku.Available = TRUE;
+ }
+ }
+ }
+
+ if (mMbpData.MeBiosPayload.FwPlatType.Available == 0) {
+ if ((MeMode == ME_MODE_NORMAL) &&
+ (
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_IN_RECOVERY_MODE) ||
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY)
+ )
+ ) {
+ Status = MbpGetPlatformTypeThroughHeci (&RuleData);
+ if (!EFI_ERROR (Status)) {
+ mMbpData.MeBiosPayload.FwPlatType.RuleData.Data = RuleData.Data;
+ mMbpData.MeBiosPayload.FwPlatType.Available = TRUE;
+ }
+ }
+ }
+
+ if (mMbpData.MeBiosPayload.FwVersionName.MajorVersion == 10) {
+ //
+ // For ME 10 get the FW features state mask
+ //
+ if (mMbpData.MeBiosPayload.FwFeaturesState.Available == 0) {
+ if ((MeMode == ME_MODE_NORMAL) &&
+ (
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_IN_RECOVERY_MODE) ||
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY)
+ )
+ ) {
+ Status = MbpGetFwFeaturesStateThroughHeci ((MEFWCAPS_SKU*)&RuleData.Data);
+ if (!EFI_ERROR (Status)) {
+ mMbpData.MeBiosPayload.FwFeaturesState.FwFeatures.Data = RuleData.Data;
+ mMbpData.MeBiosPayload.FwFeaturesState.Available = TRUE;
+ }
+ }
+ }
+ }
+
+#ifdef EFI_DEBUG
+ //
+ // Dump the Mbp data
+ //
+ DxeMbpDebugDump (&mMbpData);
+#endif
+
+ ///
+ /// Install the MBP protocol
+ ///
+ mMbpData.Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mMbpData.Handle,
+ &gMeBiosPayloadDataProtocolGuid,
+ &mMbpData,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MBP data protocol install failed, Status is %r \n", Status));
+ }
+ }
+}
+
+/**
+ HECI driver entry point used to initialize support for the HECI device.
+
+ @param[in] ImageHandle Standard entry point parameter.
+ @param[in] SystemTable Standard entry point parameter.
+
+ @retval EFI_SUCCESS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+InitializeHECI (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBootEvent;
+ VOID *Registration;
+ BOOLEAN HeciInitializeError;
+ UINT32 MeStatus;
+ UINT32 MeMode;
+ MEFWCAPS_SKU FwCapsSku;
+ PLATFORM_TYPE_RULE_DATA RuleData;
+ DXE_MBP_DATA_PROTOCOL *MbpData;
+
+ INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+
+ mHeciDrv = ImageHandle;
+ HeciInitializeError = FALSE;
+ mHeciContext = AllocateZeroPool (sizeof (HECI_INSTANCE));
+ ///
+ /// Initialize HECI protocol pointers
+ ///
+ if (mHeciContext != NULL) {
+ mHeciContext->HeciCtlr.ResetHeci = ResetHeciInterface;
+ mHeciContext->HeciCtlr.SendwACK = HeciSendwACK;
+ mHeciContext->HeciCtlr.ReadMsg = HeciReceive;
+ mHeciContext->HeciCtlr.SendMsg = HeciSend;
+ mHeciContext->HeciCtlr.InitHeci = HeciInitialize;
+ mHeciContext->HeciCtlr.ReInitHeci = HeciReInitialize;
+ mHeciContext->HeciCtlr.MeResetWait = MeResetWait;
+ mHeciContext->HeciCtlr.GetMeStatus = HeciGetMeStatus;
+ mHeciContext->HeciCtlr.GetMeMode = HeciGetMeMode;
+ }
+ ///
+ /// Initialize the HECI device
+ ///
+ Status = InitializeHeciPrivate ();
+ if ((EFI_ERROR (Status)) || (mHeciContext == NULL)) {
+ HeciInitializeError = TRUE;
+ }
+ ///
+ /// Install the MBP information
+ ///
+ InstallMbpDataProtocol ();
+
+ if (HeciInitializeError) {
+ ///
+ /// Don't install on ERR
+ ///
+ if (Status != EFI_NOT_READY) {
+ DEBUG ((EFI_D_ERROR, "HECI not initialized - Removing devices from PCI space!\n"));
+ DisableAllMEDevices ();
+ ///
+ /// Store the current value of DEVEN for S3 resume path
+ ///
+ }
+ DeviceStatusSave ();
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Install the HECI interface
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHeciContext->Handle,
+ &gEfiHeciProtocolGuid,
+ &mHeciContext->HeciCtlr,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ HeciGetMeStatus (&MeStatus);
+ HeciGetMeMode (&MeMode);
+
+ Status = gBS->LocateProtocol (
+ &gMeBiosPayloadDataProtocolGuid,
+ NULL,
+ (VOID **) &MbpData
+ );
+ if (!EFI_ERROR (Status)) {
+ if (MbpData->MeBiosPayload.FwCapsSku.Available == 0) {
+ if ((MeMode == ME_MODE_NORMAL) &&
+ (
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_IN_RECOVERY_MODE) ||
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY)
+ )
+ ) {
+ Status = HeciGetFwCapsSku (&FwCapsSku);
+ if (!EFI_ERROR (Status)) {
+ MbpData->MeBiosPayload.FwCapsSku.FwCapabilities.Data = FwCapsSku.Data;
+ }
+ }
+ }
+
+ if (MbpData->MeBiosPayload.FwPlatType.Available == 0) {
+ if ((MeMode == ME_MODE_NORMAL) &&
+ (
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_IN_RECOVERY_MODE) ||
+ (ME_STATUS_ME_STATE_ONLY (MeStatus) == ME_READY)
+ )
+ ) {
+ Status = HeciGetPlatformType (&RuleData);
+ if (!EFI_ERROR (Status)) {
+ MbpData->MeBiosPayload.FwPlatType.RuleData.Data = RuleData.Data;
+ }
+ }
+ }
+ ///
+ /// Dxe Mbp data is gone after ExitPmAuth, so we keep MeFwImageType for the inspection after ExitPmAuth
+ ///
+ mHeciContext->MeFwImageType = (UINT8) MbpData->MeBiosPayload.FwPlatType.RuleData.Fields.IntelMeFwImageType;
+ }
+
+
+ ///
+ /// Hide Me relevant Devices
+ ///
+ Status = MeDeviceConfigure ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize the Me Reference Code Information
+ ///
+ mHeciContext->MeRcInfo.Revision = ME_RC_INFO_PROTOCOL_REVISION_1;
+ mHeciContext->MeRcInfo.RCVersion = ME_RC_VERSION;
+
+ ///
+ /// Install the Me Reference Code Information
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHeciContext->Handle,
+ &gEfiMeRcInfoProtocolGuid,
+ &mHeciContext->MeRcInfo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ ///
+ /// Create an ExitPmAuth protocol call back event.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ MeScriptSaveEvent,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Create a Ready to Boot event.
+ ///
+ Status = EfiCreateEventReadyToBootEx (
+ EFI_TPL_CALLBACK,
+ MeReadyToBootEvent,
+ (VOID *) &ImageHandle,
+ &ReadyToBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}