summaryrefslogtreecommitdiff
path: root/ReferenceCode/ME/Heci/Smm
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/ME/Heci/Smm
downloadzprj-master.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/ME/Heci/Smm')
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciHpet.c282
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciHpet.h197
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciSmm.c228
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciSmm.cif16
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciSmm.dxs51
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciSmm.inf102
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciSmm.mak64
-rw-r--r--ReferenceCode/ME/Heci/Smm/HeciSmm.sdl25
-rw-r--r--ReferenceCode/ME/Heci/Smm/Hecicore.c1585
-rw-r--r--ReferenceCode/ME/Heci/Smm/Hecicore.h512
10 files changed, 3062 insertions, 0 deletions
diff --git a/ReferenceCode/ME/Heci/Smm/HeciHpet.c b/ReferenceCode/ME/Heci/Smm/HeciHpet.c
new file mode 100644
index 0000000..2f75571
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciHpet.c
@@ -0,0 +1,282 @@
+/*++
+ 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
+--*/
+/*++
+
+Copyright (c) 2006 - 2010 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.
+
+Module Name:
+
+ HeciHpet.c
+
+Abstract:
+
+ Definitions for HECI driver
+
+--*/
+#include "HeciHpet.h"
+#include "HeciRegs.h"
+#include "HeciCore.h"
+
+//
+// Extern for shared HECI data and protocols
+//
+extern HECI_INSTANCE_SMM *mHeciContext;
+VOLATILE UINT32 mSaveHpetConfigReg;
+
+VOID
+SaveHpet (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Store the value of High Performance Timer
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ mSaveHpetConfigReg = MmioRead32 (PCH_RCRB_BASE + R_PCH_RCRB_HPTC);
+}
+
+VOID
+RestoreHpet (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Restore the value of High Performance Timer
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ MmioWrite32 (PCH_RCRB_BASE + R_PCH_RCRB_HPTC, mSaveHpetConfigReg);
+}
+
+VOID
+StartTimer (
+ OUT UINT32 *Start,
+ OUT UINT32 *End,
+ IN UINT32 Time
+ )
+/*++
+
+ Routine Description:
+
+ Used for calculating timeouts
+
+ Arguments:
+
+ Start - Snapshot of the HPET timer
+ End - Calculated time when timeout period will be done
+ Time - Timeout period in microseconds
+
+ Returns:
+
+ VOID
+
+--*/
+{
+ UINT32 Ticks;
+
+ //
+ // Make sure that HPET is enabled and running
+ //
+ EnableHpet ();
+
+ //
+ // Read current timer value into start time from HPET
+ //
+ *Start = mHeciContext->HpetTimer[HPET_MAIN_COUNTER_LOW];
+
+ //
+ // Convert microseconds into 70ns timer ticks
+ //
+ Ticks = Time * HPET_TICKS_PER_MICRO;
+
+ //
+ // Compute end time
+ //
+ *End = *Start + Ticks;
+
+ return ;
+}
+
+EFI_STATUS
+Timeout (
+ IN UINT32 Start,
+ IN UINT32 End
+ )
+/*++
+
+ Routine Description:
+ Used to determine if a timeout has occured.
+
+ Arguments:
+ Start - Snapshot of the HPET timer when the timeout period started.
+ End - Calculated time when timeout period will be done.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ UINT32 Current;
+
+ //
+ // Read HPET and assign the value as the current time.
+ //
+ Current = mHeciContext->HpetTimer[HPET_MAIN_COUNTER_LOW];
+
+ //
+ // Test basic case (no overflow)
+ //
+ if ((Start < End) && (End <= Current)) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Test basic start/end conditions with overflowed timer
+ //
+ if ((Start < End) && (Current < Start)) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Test for overflowed start/end condition
+ //
+ if ((Start > End) && ((Current < Start) && (Current > End))) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Catch corner case of broken arguments
+ //
+ if (Start == End) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Else, we have not yet timed out
+ //
+ return EFI_SUCCESS;
+}
+
+VOID
+IoDelay (
+ UINT32 delayTime
+ )
+/*++
+
+Routine Description:
+
+ Delay for at least the request number of microseconds
+
+Arguments:
+
+ delayTime - Number of microseconds to delay.
+
+Returns:
+
+ None.
+
+--*/
+{
+ SmmStall (delayTime);
+}
+
+VOID
+SmmStall (
+ IN UINTN Microseconds
+ )
+/*++
+
+Routine Description:
+
+ Delay for at least the request number of microseconds.
+ Timer used is DMA refresh timer, which has 15us granularity.
+ You can call with any number of microseconds, but this
+ implementation cannot support 1us granularity.
+
+Arguments:
+
+ Microseconds - Number of microseconds to delay.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT8 Data;
+ UINT8 InitialState;
+ UINTN CycleIterations;
+
+ CycleIterations = 0;
+ Data = 0;
+ InitialState = 0;
+
+ //
+ // The time-source is 15 us granular, so calibrate the timing loop
+ // based on this baseline
+ // Error is possible 15us.
+ //
+ CycleIterations = (Microseconds / 15) + 1;
+
+ //
+ // Use the DMA Refresh timer in port 0x61. Cheap but effective.
+ // The only issue is that the granularity is 15us, and we want to
+ // guarantee "at least" one full transition to avoid races.
+ //
+ //
+ // _____________/----------\__________/--------
+ //
+ // |<--15us-->|
+ //
+ // --------------------------------------------------> Time (us)
+ //
+ while (CycleIterations--) {
+ Data = IoRead8 (0x61);
+ InitialState = Data;
+
+ //
+ // Capture first transition (strictly less than one period)
+ //
+ while (InitialState == Data) {
+ Data = IoRead8 (0x61);
+ }
+
+ InitialState = Data;
+ //
+ // Capture next transition (guarantee at least one full pulse)
+ //
+ while (InitialState == Data) {
+ Data = IoRead8 (0x61);
+ }
+ }
+}
diff --git a/ReferenceCode/ME/Heci/Smm/HeciHpet.h b/ReferenceCode/ME/Heci/Smm/HeciHpet.h
new file mode 100644
index 0000000..8624445
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciHpet.h
@@ -0,0 +1,197 @@
+/*++
+ 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
+--*/
+/*++
+
+Copyright (c) 2006 - 2010 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.
+
+Module Name:
+
+ HeciHpet.h
+
+Abstract:
+
+ Definitions for HECI driver
+
+--*/
+#ifndef _HECI_HPET_H
+#define _HECI_HPET_H
+
+#include "EdkIIGlueDxe.h"
+#include "MeAccess.h"
+#include "HeciRegs.h"
+#include "Pci22.h"
+
+#define HECI_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('H', 'e', 'c', 'i')
+#define HECI_ROUND_UP_BUFFER_LENGTH(Length) ((UINT32) ((((Length) + 3) / 4) * 4))
+
+//
+// Driver Produced Protocol Prototypes
+//
+#include EFI_PROTOCOL_PRODUCER (HeciSmm)
+
+VOID
+SaveHpet (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Store the value of High Performance Timer
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+RestoreHpet (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Restore the value of High Performance Timer
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+StartTimer (
+ OUT UINT32 *Start,
+ OUT UINT32 *End,
+ IN UINT32 Time
+ )
+/*++
+
+ Routine Description:
+
+ Used for calculating timeouts
+
+ Arguments:
+
+ Start - Snapshot of the HPET timer
+ End - Calculated time when timeout period will be done
+ Time - Timeout period in microseconds
+
+ Returns:
+
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+Timeout (
+ IN UINT32 Start,
+ IN UINT32 End
+ )
+/*++
+
+ Routine Description:
+ Used to determine if a timeout has occured.
+
+ Arguments:
+ Start - Snapshot of the HPET timer when the timeout period started.
+ End - Calculated time when timeout period will be done.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+VOID
+EnableHpet (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enable Hpet function.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+;
+
+VOID
+IoDelay (
+ UINT32 delayTime
+ )
+/*++
+
+Routine Description:
+
+ Delay for at least the request number of microseconds
+
+Arguments:
+
+ delayTime - Number of microseconds to delay.
+
+Returns:
+
+ None.
+
+--*/
+;
+
+VOID
+SmmStall (
+ IN UINTN Microseconds
+ )
+/*++
+
+Routine Description:
+
+ Delay for at least the request number of microseconds.
+ Timer used is DMA refresh timer, which has 15us granularity.
+ You can call with any number of microseconds, but this
+ implementation cannot support 1us granularity.
+
+Arguments:
+
+ Microseconds - Number of microseconds to delay.
+
+Returns:
+
+ None
+
+--*/
+;
+#endif // _HECI_HPET_H
diff --git a/ReferenceCode/ME/Heci/Smm/HeciSmm.c b/ReferenceCode/ME/Heci/Smm/HeciSmm.c
new file mode 100644
index 0000000..df1f165
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciSmm.c
@@ -0,0 +1,228 @@
+/*++
+ 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
+--*/
+/*++
+
+Copyright (c) 2008 - 2010 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.
+
+Module Name:
+
+ HeciSmm.c
+
+Abstract:
+
+ SMM HECI driver
+
+--*/
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "HeciHpet.h"
+#include "HeciCore.h"
+#endif // EDK_RELEASE_VERSION
+//
+// Global driver data
+//
+EFI_SMM_BASE_PROTOCOL *mSmmBase;
+HECI_INSTANCE_SMM *mHeciContext;
+
+UINT32
+CheckAndFixHeciForAccess (
+ VOID
+ )
+/*++
+
+Routine Description:
+ 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.
+
+Arguments:
+ None.
+
+Returns:
+ VOID
+
+--*/
+{
+ UINTN HeciPciAddressBase;
+
+ HeciPciAddressBase = mHeciContext->PciAddressBase;
+
+ //
+ // Read HECI_MBAR in case it has changed
+ //
+ mHeciContext->HeciMBAR = PciRead32 (HeciPciAddressBase + R_HECIMBAR) & 0xFFFFFFF0;
+
+ //
+ // Check if HECI_MBAR is disabled
+ //
+ if ((
+ PciRead8 (HeciPciAddressBase + 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.
+ //
+ PciOr8 (
+ HeciPciAddressBase + PCI_COMMAND_OFFSET,
+ EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER
+ );
+ }
+
+ return mHeciContext->HeciMBAR;
+}
+
+VOID
+EnableHpet (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Enable Hpet function.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+{
+ 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 ;
+}
+
+EFI_STATUS
+InitializeHECI (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ HECI driver entry point used to initialize support for the HECI device.
+
+Arguments:
+ ImageHandle - Standard entry point parameter.
+ SystemTable - Standard entry point parameter.
+
+Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, &mSmmBase);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Create database record and add to database
+ //
+ Status = mSmmBase->SmmAllocatePool (
+ mSmmBase,
+ EfiRuntimeServicesData,
+ sizeof (HECI_INSTANCE_SMM),
+ &mHeciContext
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ mHeciContext->Handle = ImageHandle;
+
+ //
+ // Initialize HECI protocol pointers
+ //
+ 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)) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Install the HECI interface
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHeciContext->Handle,
+ &gSmmHeciProtocolGuid,
+ &mHeciContext->HeciCtlr,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/ME/Heci/Smm/HeciSmm.cif b/ReferenceCode/ME/Heci/Smm/HeciSmm.cif
new file mode 100644
index 0000000..3ddcf24
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciSmm.cif
@@ -0,0 +1,16 @@
+<component>
+ name = "HeciSmm"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\ME\Heci\Smm\"
+ RefName = "HeciSmm"
+[files]
+"HeciSmm.sdl"
+"HeciSmm.mak"
+"Hecicore.c"
+"Hecicore.h"
+"HeciSmm.c"
+"HeciSmm.dxs"
+"HeciHpet.c"
+"HeciHpet.h"
+"HeciSmm.inf"
+<endComponent>
diff --git a/ReferenceCode/ME/Heci/Smm/HeciSmm.dxs b/ReferenceCode/ME/Heci/Smm/HeciSmm.dxs
new file mode 100644
index 0000000..9c3676a
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciSmm.dxs
@@ -0,0 +1,51 @@
+/*++
+ This file contains a 'Sample Driver' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may be modified by the user, subject to
+ the additional terms of the license agreement
+--*/
+/*++
+
+Copyright (c) 2010 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.
+
+Module Name:
+
+ HeciSmm.dxs
+
+Abstract:
+
+ Dependency expression source file.
+
+--*/
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#include EFI_PROTOCOL_DEFINITION (SmmBase)
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo)
+#endif
+
+DEPENDENCY_START
+ EFI_CPU_IO_PROTOCOL_GUID AND
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID AND
+ EFI_SMM_BASE_PROTOCOL_GUID
+DEPENDENCY_END
+
diff --git a/ReferenceCode/ME/Heci/Smm/HeciSmm.inf b/ReferenceCode/ME/Heci/Smm/HeciSmm.inf
new file mode 100644
index 0000000..600e1f2
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciSmm.inf
@@ -0,0 +1,102 @@
+#/*++
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#--*/
+#/*++
+#
+# Copyright (c) 2007 - 2010 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.
+#
+# Module Name:
+#
+# HeciSmm.inf
+#
+# Abstract:
+#
+# Component description file for Heci SMM driver
+#
+#--*/
+
+[defines]
+BASE_NAME = HeciSmm
+FILE_GUID = 921CD783-3E22-4579-A71F-00D74197FCC8
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ HeciSmm.c
+ Hecicore.c
+ HeciCore.h
+ HeciHpet.c
+ HeciHpet.h
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueSmmDriverEntryPoint.c
+
+[includes.common]
+ $(EDK_SOURCE)\Foundation
+ $(EDK_SOURCE)\Foundation\Framework
+ $(EDK_SOURCE)\Foundation\Efi
+ $(EDK_SOURCE)\Foundation\Include
+ $(EDK_SOURCE)\Foundation\Efi\Include
+ $(EDK_SOURCE)\Foundation\Framework\Include
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+ $(EDK_SOURCE)\Foundation\Cpu\Pentium\Include
+ $(EFI_SOURCE)\$(PROJECT_ME_ROOT)
+ $(EFI_SOURCE)\$(PROJECT_ME_ROOT)\Library\MeKernel\Dxe
+ $(EFI_SOURCE)\$(PROJECT_ME_ROOT)\Library\MeKernel\Include
+ $(EFI_SOURCE)\$(PROJECT_ME_ROOT)\Heci\Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)\Framework
+ $(EDK_SOURCE)\Foundation
+ $(EDK_SOURCE)\Foundation\Framework
+ $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+ $(EDK_SOURCE)\Foundation\Core\Dxe
+ $(EDK_SOURCE)\Foundation\Include\Pei
+ $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+ $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\Include
+
+[libraries.common]
+ MeProtocolLib
+ MeLib
+ MeChipsetLib
+ EdkProtocolLib
+ EdkFrameworkProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGluePeiDxeDebugLibReportStatusCode
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiDevicePathLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT=_ModuleEntryPoint
+ DPX_SOURCE=HeciSmm.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) /D__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeHECI
+ C_FLAGS = $(C_FLAGS) /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_PEI_DXE_DEBUG_LIB_REPORT_STATUS_CODE__\
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
diff --git a/ReferenceCode/ME/Heci/Smm/HeciSmm.mak b/ReferenceCode/ME/Heci/Smm/HeciSmm.mak
new file mode 100644
index 0000000..31006bc
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciSmm.mak
@@ -0,0 +1,64 @@
+# MAK file for the ModulePart:HeciSmm
+all : HeciSmm
+
+HeciSmm : $(BUILD_DIR)\HeciSmm.mak HeciSmmBin
+
+$(BUILD_DIR)\HeciSmm.mak : $(HeciSmm_DIR)\$(@B).cif $(HeciSmm_DIR)\$(@B).mak $(CP_BUILD_RULES)
+ $(CIF2MAK) $(HeciSmm_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+HeciSmm_INCLUDES= \
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(ME_INCLUDES)\
+ /I$(INTEL_COUGAR_POINT_INCLUDE_DIR)
+
+
+HeciSmm_LIBS=\
+ $(EDKPROTOCOLLIB)\
+ $(MeProtocolLib_LIB)\
+ $(MeLibDxe_LIB)\
+ $(MeChipsetDxeLib_LIB)\
+ $(MeGuidLib_LIB)\
+ $(EFISCRIPTLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EFIGUIDLIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(RcFviDxeLib_LIB)\
+ $(PchPlatformDxeLib_LIB)
+
+HeciSmm_DEFINES=$(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeHECI"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_LIB__\
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+
+HeciSmmBin : $(HeciSmm_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\HeciSmm.mak all\
+ MAKEFILE=$(BUILD_DIR)\HeciSmm.mak\
+ "MY_INCLUDES=$(HeciSmm_INCLUDES)"\
+ "MY_DEFINES=$(HeciSmm_DEFINES)"\
+ GUID=921CD783-3E22-4579-A71F-00D74197FCC8\
+ DEPEX1=$(HeciSmm_DIR)\HeciSmm.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER\
+ EDKIIModule=SMMDRIVER\
+ COMPRESS=1
diff --git a/ReferenceCode/ME/Heci/Smm/HeciSmm.sdl b/ReferenceCode/ME/Heci/Smm/HeciSmm.sdl
new file mode 100644
index 0000000..3165eee
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/HeciSmm.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "HeciSmm_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable HeciSmm Suppport in Project"
+End
+
+MODULE
+ Help = "Includes HeciSmm.mak to Project"
+ File = "HeciSmm.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\HeciSmm.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
+PATH
+ Name = "HeciSmm_DIR"
+ Help = "iAMT Hec SMM Driver files source directory"
+End \ No newline at end of file
diff --git a/ReferenceCode/ME/Heci/Smm/Hecicore.c b/ReferenceCode/ME/Heci/Smm/Hecicore.c
new file mode 100644
index 0000000..612f2f6
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/Hecicore.c
@@ -0,0 +1,1585 @@
+/*++
+ 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
+--*/
+/*++
+
+Copyright (c) 2008 - 2010 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.
+
+Module Name:
+
+ Hecicore.c
+
+Abstract:
+
+ Heci driver core. For Dxe Phase, determines the HECI device and initializes it.
+
+--*/
+#include "HeciHpet.h"
+#include "HeciCore.h"
+#include "HeciRegs.h"
+#include "MeState.h"
+
+//
+// //////////////////////////////////////////////////////////////////////////////////
+// Globals used in Heci driver
+////////////////////////////////////////////////////////////////////////////////////
+//
+UINT16 HECICtlrBDF;
+static UINT32 HeciMBAR = 0;
+
+//
+// //////////////////////////////////////////////////////////////////////////////////
+// Macro definition for function used in Heci driver
+////////////////////////////////////////////////////////////////////////////////////
+//
+#define R_PCH_RCRB_FUNC_DIS2 0x3428
+
+UINT32
+MmIoReadDword (
+ UINTN a
+ )
+/*++
+
+Routine Description:
+
+ The routing of MmIo Read Dword
+
+Arguments:
+
+ a - The address of Mmio
+
+Returns:
+
+ Return the valut of MmIo Read
+
+--*/
+{
+ volatile HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+
+ HeciRegHCsrPtr = (HECI_HOST_CONTROL_REGISTER *) a;
+ return HeciRegHCsrPtr->ul;
+}
+
+VOID
+MmIoWriteDword (
+ UINTN a,
+ UINT32 b
+ )
+/*++
+
+Routine Description:
+
+ The routing of MmIo Write Dword
+
+Arguments:
+
+ a - The address of Mmio
+ b - Value revised
+
+Returns:
+
+ None
+
+--*/
+{
+ volatile HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+
+ HeciRegHCsrPtr = (HECI_HOST_CONTROL_REGISTER *) a;
+
+ HeciRegHCsrPtr->ul = b;
+}
+
+#define MMIOREADDWORD(a) MmIoReadDword (a)
+#define MMIOWRITEDWORD(a, b) MmIoWriteDword (a, b)
+
+//
+// Extern for shared HECI data and protocols
+//
+extern HECI_INSTANCE_SMM *mHeciContext;
+
+//
+// //////////////////////////////////////////////////////////////////////////////////
+// Forward declaration
+////////////////////////////////////////////////////////////////////////////////////
+//
+UINT8
+FilledSlots (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer
+ );
+
+EFI_STATUS
+OverflowCB (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer,
+ IN UINT32 BufferDepth
+ );
+
+EFI_STATUS
+WaitForMEReady (
+ VOID
+ );
+
+//
+// Heci driver function definitions
+//
+EFI_STATUS
+InitializeHeciPrivate (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Determines if the HECI device is present and, if present, initializes it for
+ use by the BIOS.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+ UINT32 MeMode;
+ EFI_STATUS Status;
+ UINTN HeciPciAddressBase;
+
+ Status = EFI_SUCCESS;
+
+ SaveHpet ();
+
+ do {
+ //
+ // Check for ME FPT Bad
+ //
+ if ((HeciPciRead32 (R_FWSTATE) & 0x0020) != 0) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ //
+ // Check for ME error status
+ //
+ if ((HeciPciRead32 (R_FWSTATE) & 0xF000) != 0) {
+ //
+ // ME failed to start so no HECI
+ //
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ //
+ // Check ME Operation Mode to decice which HECI to use in SMM mode
+ //
+ Status = HeciGetMeMode (&MeMode);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // HECI MSG is unsupported if ME MODE is in Security Override
+ //
+ mHeciContext->MeMode = MeMode;
+ if (mHeciContext->MeMode == ME_MODE_DEBUG) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ HeciPciAddressBase = PCI_LIB_ADDRESS (
+ ME_BUS,
+ ME_DEVICE_NUMBER,
+ HECI_FUNCTION_NUMBER,
+ 0
+ );
+ mHeciContext->HeciDevSaveEnable = Heci2DevSaveEnable;
+ mHeciContext->PciAddressBase = HeciPciAddressBase;
+
+ //
+ // Store HECI vendor and device information away
+ //
+ mHeciContext->DeviceInfo = PciRead16 (HeciPciAddressBase + PCI_DEVICE_ID_OFFSET);
+
+ //
+ // Check for HECI-2 PCI device availability
+ //
+ if (mHeciContext->DeviceInfo == 0xFFFF) {
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ //
+ // Store HECI revision ID
+ //
+ mHeciContext->RevisionInfo = PciRead8 (HeciPciAddressBase + PCI_REVISION_ID_OFFSET);
+
+ //
+ // Get HECI_MBAR and see if it is programmed
+ // to a useable value
+ //
+ mHeciContext->HeciMBAR = PciRead32 (HeciPciAddressBase + R_HECIMBAR) & 0xFFFFFFF0;
+ HeciMBAR = mHeciContext->HeciMBAR;
+
+ //
+ // Load temporary address for HECI_MBAR if one is not assigned
+ //
+ if (mHeciContext->HeciMBAR == 0) {
+ //
+ // mHeciContext->HeciMBAR = mHeciContext->DefaultHeciBar;
+ // PciWrite32 (HeciPciAddressBase + R_HECIMBAR, mHeciContext->HeciMBAR);
+ // HeciMBAR = mHeciContext->HeciMBAR;
+ //
+ DEBUG ((EFI_D_ERROR, "Heci MMIO Bar not programmed in SMM phase\n"));
+ }
+ //
+ // Enable HECI BME and MSE
+ //
+ PciOr8 (
+ HeciPciAddressBase + PCI_COMMAND_OFFSET,
+ EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER
+ );
+
+ //
+ // Set HECI interrupt delivery mode.
+ // HECI-2 using legacy/MSI interrupt
+ //
+ PciAnd8 (HeciPciAddressBase + R_HIDM, 0xFC);
+
+ //
+ // Need to do following on ME init:
+ //
+ // 1) wait for ME_CSR_HA reg ME_RDY bit set
+ //
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ //
+ // 2) setup H_CSR reg as follows:
+ // a) Make sure H_RST is clear
+ // b) Set H_RDY
+ // c) Set H_IG
+ //
+ HeciRegHCsrPtr = (VOID *) (UINTN) (mHeciContext->HeciMBAR + H_CSR);
+ HeciRegHCsr.ul = HeciRegHCsrPtr->ul;
+ if (HeciRegHCsrPtr->r.H_RDY == 0) {
+ HeciRegHCsr.r.H_RST = 0;
+ HeciRegHCsr.r.H_RDY = 1;
+ HeciRegHCsr.r.H_IG = 1;
+ HeciRegHCsrPtr->ul = HeciRegHCsr.ul;
+ }
+
+ } while (EFI_ERROR (Status));
+
+ RestoreHpet ();
+
+ return Status;
+}
+
+EFI_STATUS
+WaitForMEReady (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Waits for the ME to report that it is ready for communication over the HECI
+ interface.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+
+ //
+ // Wait for ME ready
+ //
+ //
+ // Check for ME ready status
+ //
+ StartTimer (&TimerStart, &TimerEnd, HECI_INIT_TIMEOUT);
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ while (HeciRegMeCsrHa.r.ME_RDY_HRA == 0) {
+ //
+ // If 5 second timeout has expired, return fail
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Perform IO delay
+ //
+ IoDelay (HECI_WAIT_DELAY);
+
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ }
+ //
+ // ME ready!!!
+ //
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CheckForHeciReset (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Checks if HECI reset has occured.
+
+ Arguments:
+ None.
+
+ Returns:
+ TRUE - HECI reset occurred
+ FALSE - No HECI reset occurred
+
+--*/
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+
+ //
+ // Init Host & ME CSR
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+
+ if ((HeciRegMeCsrHa.r.ME_RDY_HRA == 0) || (HeciRegHCsr.r.H_RDY == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+HeciInitialize (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Determines if the HECI device is present and, if present, initializes it for
+ use by the BIOS.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+
+ //
+ // Make sure that HECI device BAR is correct and device is enabled.
+ //
+ HeciMBAR = CheckAndFixHeciForAccess ();
+
+ //
+ // Need to do following on ME init:
+ //
+ // 1) wait for ME_CSR_HA reg ME_RDY bit set
+ //
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // 2) setup H_CSR reg as follows:
+ // a) Make sure H_RST is clear
+ // b) Set H_RDY
+ // c) Set H_IG
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ if (HeciRegHCsr.r.H_RDY == 0) {
+ HeciRegHCsr.r.H_RST = 0;
+ HeciRegHCsr.r.H_RDY = 1;
+ HeciRegHCsr.r.H_IG = 1;
+ MMIOWRITEDWORD (HeciMBAR + H_CSR, HeciRegHCsr.ul);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HeciReInitialize (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Heci Re-initializes it for Host
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ //
+ // Need to do following on ME init:
+ //
+ // 1) wait for HOST_CSR_HA reg H_RDY bit set
+ //
+ // if (WaitForHostReady() != EFI_SUCCESS) {
+ //
+ if (MeResetWait (HECI_INIT_TIMEOUT) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ if (HeciRegHCsr.r.H_RDY == 0) {
+ Status = ResetHeciInterface ();
+
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+HeciReInitialize2 (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Heci Re-initializes it for Me
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+ EFI_STATUS Status;
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+ Status = EFI_SUCCESS;
+ //
+ // Need to do following on ME init:
+ //
+ // 1) wait for HOST_CSR_HA reg H_RDY bit set
+ //
+ // if (WaitForHostReady() != EFI_SUCCESS) {
+ //
+ StartTimer (&TimerStart, &TimerEnd, HECI_INIT_TIMEOUT);
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ while (HeciRegMeCsrHa.r.ME_RDY_HRA == 1) {
+ //
+ // If 5 second timeout has expired, return fail
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+
+ IoDelay (HECI_WAIT_DELAY);
+
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ }
+
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+HECIPacketRead (
+ IN UINT32 Blocking,
+ OUT HECI_MESSAGE_HEADER *MessageHeader,
+ OUT UINT32 *MessageData,
+ IN OUT UINT32 *Length
+ )
+/*++
+
+ Routine Description:
+ Function to pull one messsage packet off the HECI circular buffer.
+ Corresponds to HECI HPS (part of) section 4.2.4
+
+
+ Arguments:
+ Blocking - Used to determine if the read is BLOCKING or NON_BLOCKING.
+ MessageHeader - Pointer to a buffer for the message header.
+ MessageData - Pointer to a buffer to recieve the message in.
+ Length - On input is the size of the callers buffer in bytes. On
+ output this is the size of the packet in bytes.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ BOOLEAN GotMessage;
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+ UINT32 TimerStart1;
+ UINT32 TimerEnd1;
+ UINT32 i;
+ UINT32 LengthInDwords;
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+
+ GotMessage = FALSE;
+ //
+ // Initialize memory mapped register pointers
+ //
+ // VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr = (VOID*)(mHeciContext->HeciMBAR + H_CSR);
+ // VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr = (VOID*)(mHeciContext->HeciMBAR + ME_CSR_HA);
+ // VOLATILE UINT32 *HeciRegMeCbrwPtr = (VOID*)(mHeciContext->HeciMBAR + ME_CB_RW);
+ //
+ // clear Interrupt Status bit
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ HeciRegHCsr.r.H_IS = 1;
+
+ //
+ // test for circular buffer overflow
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ if (OverflowCB (
+ HeciRegMeCsrHa.r.ME_CBRP_HRA,
+ HeciRegMeCsrHa.r.ME_CBWP_HRA,
+ HeciRegMeCsrHa.r.ME_CBD_HRA
+ ) != EFI_SUCCESS) {
+ //
+ // if we get here, the circular buffer is overflowed
+ //
+ *Length = 0;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // If NON_BLOCKING, exit if the circular buffer is empty
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);;
+ if ((FilledSlots (HeciRegMeCsrHa.r.ME_CBRP_HRA, HeciRegMeCsrHa.r.ME_CBWP_HRA) == 0) && (Blocking == NON_BLOCKING)) {
+ *Length = 0;
+ return EFI_NO_RESPONSE;
+ }
+ //
+ // Start timeout counter
+ //
+ StartTimer (&TimerStart, &TimerEnd, HECI_READ_TIMEOUT);
+
+ //
+ // loop until we get a message packet
+ //
+ while (!GotMessage) {
+ //
+ // If 1 second timeout has expired, return fail as we have not yet received a full message.
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ *Length = 0;
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read one message from HECI buffer and advance read pointer. Make sure
+ // that we do not pass the write pointer.
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);;
+ if (FilledSlots (HeciRegMeCsrHa.r.ME_CBRP_HRA, HeciRegMeCsrHa.r.ME_CBWP_HRA) > 0) {
+ //
+ // Eat the HECI Message header
+ //
+ MessageHeader->Data = MMIOREADDWORD (HeciMBAR + ME_CB_RW);
+
+ //
+ // Compute required message length in DWORDS
+ //
+ LengthInDwords = ((MessageHeader->Fields.Length + 3) / 4);
+
+ //
+ // Just return success if Length is 0
+ //
+ if (MessageHeader->Fields.Length == 0) {
+ //
+ // Set Interrupt Generate bit and return
+ //
+ MMIOREADDWORD (HeciMBAR + H_CSR);
+ HeciRegHCsr.r.H_IG = 1;
+ MMIOWRITEDWORD (HeciMBAR + H_CSR, HeciRegHCsr.ul);
+ *Length = 0;
+ return EFI_SUCCESS;
+ }
+ //
+ // Make sure that the message does not overflow the circular buffer.
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ if ((MessageHeader->Fields.Length + sizeof (HECI_MESSAGE_HEADER)) > (HeciRegMeCsrHa.r.ME_CBD_HRA * 4)) {
+ *Length = 0;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Make sure that the callers buffer can hold the correct number of DWORDS
+ //
+ if ((MessageHeader->Fields.Length) <= *Length) {
+ //
+ // Start timeout counter for inner loop
+ //
+ StartTimer (&TimerStart1, &TimerEnd1, HECI_READ_TIMEOUT);
+
+ //
+ // Wait here until entire message is present in circular buffer
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ while (LengthInDwords > FilledSlots (HeciRegMeCsrHa.r.ME_CBRP_HRA, HeciRegMeCsrHa.r.ME_CBWP_HRA)) {
+ //
+ // If 1 second timeout has expired, return fail as we have not yet received a full message
+ //
+ if (Timeout (TimerStart1, TimerEnd1) != EFI_SUCCESS) {
+ *Length = 0;
+ return EFI_TIMEOUT;
+ }
+ //
+ // Wait before we read the register again
+ //
+ IoDelay (HECI_WAIT_DELAY);
+
+ //
+ // Read the register again
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ }
+ //
+ // copy rest of message
+ //
+ for (i = 0; i < LengthInDwords; i++) {
+ MessageData[i] = MMIOREADDWORD (HeciMBAR + ME_CB_RW);
+ }
+ //
+ // Update status and length
+ //
+ GotMessage = TRUE;
+ *Length = MessageHeader->Fields.Length;
+
+ } else {
+ //
+ // Message packet is larger than caller's buffer
+ //
+ *Length = 0;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ }
+ //
+ // Wait before we try to get a message again
+ //
+ IoDelay (HECI_WAIT_DELAY);
+ }
+ //
+ // Read ME_CSR_HA. If the ME_RDY bit is 0, then an ME reset occurred during the
+ // transaction and the message should be discarded as bad data may have been retrieved
+ // from the host's circular buffer
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ if (HeciRegMeCsrHa.r.ME_RDY_HRA == 0) {
+ *Length = 0;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set Interrupt Generate bit
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ HeciRegHCsr.r.H_IG = 1;
+ MMIOWRITEDWORD (HeciMBAR + H_CSR, HeciRegHCsr.ul);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HeciReceive (
+ IN UINT32 Blocking,
+ IN OUT UINT32 *MessageBody,
+ IN OUT UINT32 *Length
+ )
+/*++
+
+ Routine Description:
+ Reads a message from the ME across HECI.
+
+ Arguments:
+ Blocking - Used to determine if the read is BLOCKING or NON_BLOCKING.
+ MessageBody - Pointer to a buffer used to receive a message.
+ Length - Pointer to the length of the buffer on input and the length
+ of the message on return. (in bytes)
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_MESSAGE_HEADER PacketHeader;
+ UINT32 CurrentLength;
+ UINT32 MessageComplete;
+ EFI_STATUS Status;
+ UINT32 PacketBuffer;
+ UINT32 timer_start;
+ UINT32 timer_end;
+ UINT32 MeDeviceState;
+ BOOLEAN QuitFlag;
+
+ Status = EFI_SUCCESS;
+ CurrentLength = 0;
+ MessageComplete = 0;
+ QuitFlag = FALSE;
+
+ SaveHpet ();
+
+ do {
+ if (mHeciContext->MeMode == ME_MODE_SECOVER) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ //
+ // Enable HECI and Save the Device State
+ //
+ mHeciContext->HeciDevSaveEnable (&MeDeviceState);
+
+ //
+ // Make sure that HECI device BAR is correct and device is enabled.
+ //
+ HeciMBAR = CheckAndFixHeciForAccess ();
+
+ //
+ // Make sure we do not have a HECI reset
+ //
+ if (CheckForHeciReset ()) {
+ //
+ // if HECI reset than try to re-init HECI
+ //
+ Status = HeciInitialize ();
+
+ if (EFI_ERROR (Status)) {
+ HeciDevRestore (MeDeviceState);
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ }
+ //
+ // Make sure that HECI is ready for communication.
+ //
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ HeciDevRestore (MeDeviceState);
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ //
+ // Set up timer for BIOS timeout.
+ //
+ StartTimer (&timer_start, &timer_end, HECI_READ_TIMEOUT);
+ while ((CurrentLength < *Length) && (MessageComplete == 0)) {
+ //
+ // If 1 second timeout has expired, return fail as we have not yet received a full message
+ //
+ if (Timeout (timer_start, timer_end) != EFI_SUCCESS) {
+ Status = EFI_TIMEOUT;
+ QuitFlag = TRUE;
+ break;
+ }
+
+ PacketBuffer = *Length - CurrentLength;
+ Status = HECIPacketRead (
+ Blocking,
+ &PacketHeader,
+ (UINT32 *) &MessageBody[CurrentLength / 4],
+ &PacketBuffer
+ );
+
+ //
+ // Check for error condition on read
+ //
+ if (EFI_ERROR (Status)) {
+ *Length = 0;
+ QuitFlag = TRUE;
+ break;
+ }
+ //
+ // Get completion status from the packet header
+ //
+ MessageComplete = PacketHeader.Fields.MessageComplete;
+
+ //
+ // Check for zero length messages
+ //
+ if (PacketBuffer == 0) {
+ //
+ // If we are not in the middle of a message, and we see Message Complete,
+ // this is a valid zero-length message.
+ //
+ if ((CurrentLength == 0) && (MessageComplete == 1)) {
+ *Length = 0;
+ QuitFlag = TRUE;
+ break;
+ } else {
+ //
+ // We should not expect a zero-length message packet except as described above.
+ //
+ *Length = 0;
+ Status = EFI_DEVICE_ERROR;
+ QuitFlag = TRUE;
+ break;
+ }
+ }
+ //
+ // Track the length of what we have read so far
+ //
+ CurrentLength += PacketBuffer;
+
+ }
+
+ if (QuitFlag == TRUE) {
+ break;
+ }
+ //
+ // If we get here the message should be complete, if it is not
+ // the caller's buffer was not large enough.
+ //
+ if (MessageComplete == 0) {
+ *Length = 0;
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (*Length != 0) {
+ *Length = CurrentLength;
+ }
+ //
+ // Restore HECI Device State
+ //
+ HeciDevRestore (MeDeviceState);
+
+ } while (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL));
+ RestoreHpet ();
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+HeciSend (
+ IN UINT32 *Message,
+ IN UINT32 Length,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+/*++
+
+ Routine Description:
+ Function sends one messsage (of any length) through the HECI circular buffer.
+
+ Arguments:
+ Message - Pointer to the message data to be sent.
+ Length - Length of the message in bytes.
+ HostAddress - The address of the host processor.
+ MeAddress - Address of the ME subsystem the message is being sent to.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ UINT32 CBLength;
+ UINT32 SendLength;
+ UINT32 CurrentLength;
+ HECI_MESSAGE_HEADER MessageHeader;
+ EFI_STATUS Status;
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ UINT32 MeDeviceState;
+
+ Status = EFI_SUCCESS;
+ CurrentLength = 0;
+
+ SaveHpet ();
+
+ do {
+ if (mHeciContext->MeMode == ME_MODE_SECOVER) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ //
+ // Enable HECI and Save the Device State
+ //
+ mHeciContext->HeciDevSaveEnable (&MeDeviceState);
+
+ //
+ // Make sure that HECI device BAR is correct and device is enabled.
+ //
+ HeciMBAR = CheckAndFixHeciForAccess ();
+
+ //
+ // Make sure we do not have a HECI reset
+ //
+ if (CheckForHeciReset ()) {
+ //
+ // if HECI reset than try to re-init HECI
+ //
+ Status = HeciInitialize ();
+
+ if (EFI_ERROR (Status)) {
+ HeciDevRestore (MeDeviceState);
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+ }
+ //
+ // Make sure that HECI is ready for communication.
+ //
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ HeciDevRestore (MeDeviceState);
+ Status = EFI_TIMEOUT;
+ break;
+ }
+ //
+ // Set up memory mapped registers
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+
+ //
+ // Grab Circular Buffer length
+ //
+ CBLength = HeciRegHCsr.r.H_CBD;
+
+ //
+ // Prepare message header
+ //
+ MessageHeader.Data = 0;
+ MessageHeader.Fields.MeAddress = MeAddress;
+ MessageHeader.Fields.HostAddress = HostAddress;
+
+ //
+ // Break message up into CB-sized packets and loop until completely sent
+ //
+ while (Length > CurrentLength) {
+ //
+ // Set the Message Complete bit if this is our last packet in the message.
+ // Needs to be 'less than' to account for the header.
+ //
+ if ((((Length - CurrentLength) + 3) / 4) < CBLength) {
+ MessageHeader.Fields.MessageComplete = 1;
+ }
+ //
+ // Calculate length for Message Header
+ // header length == smaller of circular buffer or remaining message (both account for the size of the header)
+ //
+ SendLength = ((CBLength < (((Length - CurrentLength) + 3) / 4)) ? ((CBLength - 1) * 4) : (Length - CurrentLength));
+ MessageHeader.Fields.Length = SendLength;
+
+ //
+ // send the current packet (CurrentLength can be treated as the index into the message buffer)
+ //
+ Status = HeciPacketWrite (&MessageHeader, (UINT32 *) ((UINTN) Message + CurrentLength));
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Update the length information
+ //
+ CurrentLength += SendLength;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Restore HECI Device State
+ //
+ HeciDevRestore (MeDeviceState);
+
+ } while (EFI_ERROR (Status));
+
+ RestoreHpet ();
+
+ return Status;
+}
+
+EFI_STATUS
+HeciPacketWrite (
+ IN HECI_MESSAGE_HEADER *MessageHeader,
+ IN UINT32 *MessageData
+ )
+/*++
+
+ Routine Description:
+ Function sends one messsage packet through the HECI circular buffer
+ Corresponds to HECI HPS (part of) section 4.2.3
+
+ Arguments:
+ MessageHeader - Pointer to the message header.
+ MessageData - Pointer to the actual message data.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ UINT32 timer_start;
+ UINT32 timer_end;
+ UINT32 i;
+ UINT32 LengthInDwords;
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+
+ //
+ // VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr = (VOID*)(mHeciContext->HeciMBAR + H_CSR);
+ // VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr = (VOID*)(mHeciContext->HeciMBAR + ME_CSR_HA);
+ // VOLATILE UINT32 *HeciRegHCbwwPtr = (VOID*)(mHeciContext->HeciMBAR + H_CB_WW);
+ //
+ // Make sure that HECI is ready for communication.
+ //
+ if (WaitForMEReady () != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Start timeout counter
+ //
+ StartTimer (&timer_start, &timer_end, HECI_SEND_TIMEOUT);
+
+ //
+ // Compute message length in DWORDS
+ //
+ LengthInDwords = ((MessageHeader->Fields.Length + 3) / 4);
+
+ //
+ // Wait until there is sufficient room in the circular buffer
+ // Must have room for message and message header
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ while ((LengthInDwords + 1) > (HeciRegHCsr.r.H_CBD - FilledSlots (HeciRegHCsr.r.H_CBRP, HeciRegHCsr.r.H_CBWP))) {
+ //
+ // If 1 second timeout has expired, return fail as the circular buffer never emptied
+ //
+ if (Timeout (timer_start, timer_end) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Wait before we read the register again
+ //
+ IoDelay (HECI_WAIT_DELAY);
+
+ //
+ // Read Host CSR for next iteration
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ }
+ //
+ // Write Message Header
+ //
+ MMIOWRITEDWORD (HeciMBAR + H_CB_WW, MessageHeader->Data);
+
+ //
+ // Write Message Body
+ //
+ for (i = 0; i < LengthInDwords; i++) {
+ MMIOWRITEDWORD (HeciMBAR + H_CB_WW, MessageData[i]);
+ }
+ //
+ // Set Interrupt Generate bit
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ HeciRegHCsr.r.H_IG = 1;
+ MMIOWRITEDWORD (HeciMBAR + H_CSR, HeciRegHCsr.ul);
+
+ //
+ // Test if ME Ready bit is set to 1, if set to 0 a fatal error occured during
+ // the transmission of this message.
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ if (HeciRegMeCsrHa.r.ME_RDY_HRA == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HeciSendwACK (
+ IN OUT UINT32 *Message,
+ IN UINT32 Length,
+ IN OUT UINT32 *RecLength,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+/*++
+
+ Routine Description:
+ Function sends one messsage through the HECI circular buffer and waits
+ for the corresponding ACK message.
+
+ Arguments:
+ Message - Pointer to the message buffer.
+ SendLength - Length of the message in bytes.
+ RecLength - Length of the message response in bytes.
+ HostAddress - Address of the sending entity.
+ MeAddress - Address of the ME entity that should receive the message.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 RetryCount;
+ UINT32 TempRecLength;
+
+ if (mHeciContext->MeMode == ME_MODE_SECOVER) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Send the message
+ //
+ Status = HeciSend (Message, Length, HostAddress, MeAddress);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Wait for ACK message
+ //
+ TempRecLength = *RecLength;
+ for (RetryCount = 0; RetryCount < HECI_MAX_RETRY; RetryCount++) {
+ //
+ // Read Message
+ //
+ Status = HeciReceive (BLOCKING, Message, &TempRecLength);
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ //
+ // Reload receive length as it has been modified by the read function
+ //
+ TempRecLength = *RecLength;
+ }
+ //
+ // Return read length and status
+ //
+ *RecLength = TempRecLength;
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+MeResetWait (
+ IN UINT32 Delay
+ )
+/*++
+
+Routine Description:
+
+ Me reset and waiting for ready
+
+Arguments:
+
+ Delay - The biggest waiting time
+
+Returns:
+
+ EFI_TIMEOUT - Time out
+ EFI_SUCCESS - Me ready
+
+--*/
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+
+ //
+ // Make sure that HECI device BAR is correct and device is enabled.
+ //
+ HeciMBAR = CheckAndFixHeciForAccess ();
+
+ //
+ // Wait for the HOST Ready bit to be cleared to signal a reset
+ //
+ StartTimer (&TimerStart, &TimerEnd, Delay);
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ while (HeciRegHCsr.r.H_RDY == 1) {
+ //
+ // If timeout has expired, return fail
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+ResetHeciInterface (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Function forces a reinit of the heci interface by following the reset heci interface via host algorithm
+ in HPS 0.90 doc 4-17-06 njy
+
+ Arguments:
+ none
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+
+ //
+ // Make sure that HECI device BAR is correct and device is enabled.
+ //
+ HeciMBAR = CheckAndFixHeciForAccess ();
+
+ //
+ // Enable Reset
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ HeciRegHCsr.r.H_RST = 1;
+ HeciRegHCsr.r.H_IG = 1;
+ MMIOWRITEDWORD (HeciMBAR + H_CSR, HeciRegHCsr.ul);
+
+ //
+ // Make sure that the reset started
+ //
+ // HeciRegHCsr.ul = MMIOREADDWORD(HeciMBAR + H_CSR);
+ //
+ StartTimer (&TimerStart, &TimerEnd, HECI_INIT_TIMEOUT);
+ do {
+ //
+ // If 5 second timeout has expired, return fail
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read the ME CSR
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ } while (HeciRegHCsr.r.H_RDY == 1);
+
+ //
+ // Wait for ME to perform reset
+ //
+ // HeciRegMeCsrHa.ul = MMIOREADDWORD(HeciMBAR + ME_CSR_HA);
+ //
+ StartTimer (&TimerStart, &TimerEnd, HECI_INIT_TIMEOUT);
+ do {
+ //
+ // If 5 second timeout has expired, return fail
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read the ME CSR
+ //
+ HeciRegMeCsrHa.ul = MMIOREADDWORD (HeciMBAR + ME_CSR_HA);
+ } while (HeciRegMeCsrHa.r.ME_RDY_HRA == 0);
+
+ //
+ // Make sure IS has been signaled on the HOST side
+ //
+ // HeciRegHCsr.ul = MMIOREADDWORD(HeciMBAR + H_CSR);
+ //
+ StartTimer (&TimerStart, &TimerEnd, HECI_INIT_TIMEOUT);
+ do {
+ //
+ // If 5 second timeout has expired, return fail
+ //
+ if (Timeout (TimerStart, TimerEnd) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read the ME CSR
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);
+ } while (HeciRegHCsr.r.H_IS == 0);
+
+ //
+ // Enable host side interface
+ //
+ HeciRegHCsr.ul = MMIOREADDWORD (HeciMBAR + H_CSR);;
+ HeciRegHCsr.r.H_RST = 0;
+ HeciRegHCsr.r.H_IG = 1;
+ HeciRegHCsr.r.H_RDY = 1;
+ MMIOWRITEDWORD (HeciMBAR + H_CSR, HeciRegHCsr.ul);
+
+ return EFI_SUCCESS;
+}
+
+UINT8
+FilledSlots (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer
+ )
+/*++
+
+ Routine Description:
+ Calculate if the circular buffer has overflowed.
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ Arguments:
+ ReadPointer - Location of the read pointer.
+ WritePointer - Location of the write pointer.
+
+ Returns:
+ Number of filled slots.
+
+--*/
+{
+ UINT8 FilledSlots;
+
+ //
+ // Calculation documented in HECI HPS 0.68 section 4.2.1
+ //
+ FilledSlots = (((INT8) WritePointer) - ((INT8) ReadPointer));
+
+ return FilledSlots;
+}
+
+EFI_STATUS
+OverflowCB (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer,
+ IN UINT32 BufferDepth
+ )
+/*++
+
+ Routine Description:
+ Calculate if the circular buffer has overflowed
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ Arguments:
+ ReadPointer - Value read from host/me read pointer
+ WritePointer - Value read from host/me write pointer
+ BufferDepth - Value read from buffer depth register
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ UINT8 FilledSlots;
+
+ //
+ // Calculation documented in HECI HPS 0.68 section 4.2.1
+ //
+ FilledSlots = (((INT8) WritePointer) - ((INT8) ReadPointer));
+
+ //
+ // test for overflow
+ //
+ if (FilledSlots > ((UINT8) BufferDepth)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HeciGetMeStatus (
+ IN UINT32 *MeStatus
+ )
+/*++
+
+ Routine Description:
+ Return ME Status
+
+ Arguments:
+ MeStatus pointer for status report
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_FWS_REGISTER MeFirmwareStatus;
+ UINT32 MeDeviceState;
+
+ if (MeStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Save HECI1 Device State and Enable it
+ //
+ Heci1DevSaveEnable (&MeDeviceState);
+
+ MeFirmwareStatus.ul = HeciPciRead32 (R_FWSTATE);
+
+ if (MeFirmwareStatus.r.CurrentState == ME_STATE_NORMAL && MeFirmwareStatus.r.ErrorCode == ME_ERROR_CODE_NO_ERROR) {
+ *MeStatus = ME_READY;
+ } else if (MeFirmwareStatus.r.CurrentState == ME_STATE_RECOVERY) {
+ *MeStatus = ME_IN_RECOVERY_MODE;
+ } else {
+ *MeStatus = ME_NOT_READY;
+ }
+
+ if (MeFirmwareStatus.r.FwInitComplete == ME_FIRMWARE_COMPLETED) {
+ *MeStatus |= ME_FW_INIT_COMPLETE;
+ }
+ //
+ // Save HECI Device State and Enable it
+ //
+ HeciDevRestore (MeDeviceState);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+HeciGetMeMode (
+ IN UINT32 *MeMode
+ )
+/*++
+
+ Routine Description:
+ Return ME Mode
+
+ Arguments:
+ MeMode pointer for ME Mode report
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ HECI_FWS_REGISTER MeFirmwareStatus;
+ UINT32 MeDeviceState;
+
+ if (MeMode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Save HECI1 Device State and Enable it
+ //
+ Heci1DevSaveEnable (&MeDeviceState);
+
+ MeFirmwareStatus.ul = HeciPciRead32 (R_FWSTATE);
+ switch (MeFirmwareStatus.r.MeOperationMode) {
+ case ME_OPERATION_MODE_NORMAL:
+ *MeMode = ME_MODE_NORMAL;
+ break;
+
+ case ME_OPERATION_MODE_DEBUG:
+ *MeMode = ME_MODE_DEBUG;
+ break;
+
+ case ME_OPERATION_MODE_SOFT_TEMP_DISABLE:
+ *MeMode = ME_MODE_TEMP_DISABLED;
+ break;
+
+ case ME_OPERATION_MODE_SECOVR_JMPR:
+ case ME_OPERATION_MODE_SECOVR_HECI_MSG:
+ *MeMode = ME_MODE_SECOVER;
+ break;
+
+ default:
+ *MeMode = ME_MODE_FAILED;
+ }
+ //
+ // Save HECI Device State and Enable it
+ //
+ HeciDevRestore (MeDeviceState);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Heci1DevSaveEnable (
+ IN OUT UINT32 *DevState
+ )
+/*++
+
+ Routine Description:
+ Save HECI1 State and Enable it
+
+ Arguments:
+ DevState - Device State Save Buffer
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ *DevState = MMIOREADDWORD (PCH_RCRB_BASE + R_PCH_RCRB_FUNC_DIS2);
+ HeciEnable ();
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Heci2DevSaveEnable (
+ IN OUT UINT32 *DevState
+ )
+/*++
+
+ Routine Description:
+ Save HECI2 State and Enable it
+
+ Arguments:
+ DevState - Device State Save Buffer
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ *DevState = MMIOREADDWORD (PCH_RCRB_BASE + R_PCH_RCRB_FUNC_DIS2);
+ Heci2Enable ();
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+HeciDevRestore (
+ IN UINT32 DevState
+ )
+/*++
+
+ Routine Description:
+ Restore HECI1&HECI2 State
+
+ Arguments:
+ DevState - Device State Save Buffer
+
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ MMIOWRITEDWORD (PCH_RCRB_BASE + R_PCH_RCRB_FUNC_DIS2, DevState);
+ MMIOREADDWORD (PCH_RCRB_BASE + R_PCH_RCRB_FUNC_DIS2);
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/ME/Heci/Smm/Hecicore.h b/ReferenceCode/ME/Heci/Smm/Hecicore.h
new file mode 100644
index 0000000..5f05c10
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Smm/Hecicore.h
@@ -0,0 +1,512 @@
+/*++
+ 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
+--*/
+/*++
+
+Copyright (c) 2006 - 2010 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.
+
+Module Name:
+
+ HeciCore.h
+
+Abstract:
+
+ Definitions for HECI driver
+
+--*/
+#ifndef _HECI_CORE_H
+#define _HECI_CORE_H
+
+#include "CpuIa32.h"
+#include "CoreBiosMsg.h"
+
+//
+// HECI bus function version
+//
+#define HBM_MINOR_VERSION 0
+#define HBM_MAJOR_VERSION 1
+
+//
+// HECI save/restore Function
+//
+typedef
+EFI_STATUS
+(EFIAPI *HECI_DEV_SAVE_ENABLE) (
+ IN OUT UINT32 *DevState
+ );
+
+//
+// HECI private data structure
+//
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ UINT32 HeciMBAR;
+ UINT16 DeviceInfo;
+ UINT32 RevisionInfo;
+ SMM_HECI_PROTOCOL HeciCtlr;
+ VOLATILE UINT32 *HpetTimer;
+ UINTN PciAddressBase;
+ UINT32 DefaultHeciBar;
+ HECI_DEV_SAVE_ENABLE HeciDevSaveEnable;
+ UINT32 MeMode;
+} HECI_INSTANCE_SMM;
+
+//
+// Prototypes
+//
+EFI_STATUS
+EFIAPI
+HeciInitialize (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Determines if the HECI device is present and, if present, initializes it for
+ use by the BIOS.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciReInitialize (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Heci Re-initializes it for Host
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciReInitialize2 (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Heci Re-initializes it for Me
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciReceive (
+ IN UINT32 Blocking,
+ OUT UINT32 *MessageData,
+ IN OUT UINT32 *Length
+ )
+/*++
+
+ Routine Description:
+ Reads a message from the ME across HECI.
+
+ Arguments:
+ Blocking - Used to determine if the read is BLOCKING or NON_BLOCKING.
+ MessageData - Pointer to a buffer used to receive a message.
+ Length - Pointer to the length of the buffer on input and the length
+ of the message on return. (in bytes)
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciSend (
+ IN UINT32 *Message,
+ IN UINT32 Length,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+/*++
+
+ Routine Description:
+ Function sends one messsage (of any length) through the HECI circular buffer.
+
+ Arguments:
+ Message - Pointer to the message data to be sent.
+ Length - Length of the message in bytes.
+ HostAddress - The address of the host processor.
+ MeAddress - Address of the ME subsystem the message is being sent to.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciSendwACK (
+ IN OUT UINT32 *Message,
+ IN UINT32 Length,
+ IN OUT UINT32 *RecLength,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+/*++
+
+ Routine Description:
+ Function sends one messsage through the HECI circular buffer and waits
+ for the corresponding ACK message.
+
+ Arguments:
+ Message - Pointer to the message buffer.
+ SendLength - Length of the message in bytes.
+ RecLength - Length of the message response in bytes.
+ HostAddress - Address of the sending entity.
+ MeAddress - Address of the ME entity that should receive the message.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+MeResetWait (
+ IN UINT32 Delay
+ )
+/*++
+
+Routine Description:
+
+ Me reset and waiting for ready
+
+Arguments:
+
+ Delay - The biggest waiting time
+
+Returns:
+
+ EFI_TIMEOUT - Time out
+ EFI_SUCCESS - Me ready
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+ResetHeciInterface (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Function forces a reinit of the heci interface by following the reset heci interface via host algorithm
+ in HPS 0.90 doc 4-17-06 njy
+
+ Arguments:
+ none
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciGetMeStatus (
+ IN UINT32 *MeStatus
+ )
+/*++
+
+ Routine Description:
+ Return ME Status
+
+ Arguments:
+ MeStatus pointer for status report
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+HeciGetMeMode (
+ IN UINT32 *MeMode
+ )
+/*++
+
+ Routine Description:
+ Return ME Mode
+
+ Arguments:
+ MeMode pointer for ME Mode report
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+//
+// Local/Private functions not part of EFIAPI for HECI
+//
+EFI_STATUS
+InitializeHECI (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+ HECI driver entry point used to initialize support for the HECI device.
+
+Arguments:
+ ImageHandle - Standard entry point parameter.
+ SystemTable - Standard entry point parameter.
+
+Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+InitializeHeciPrivate (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Determines if the HECI device is present and, if present, initializes it for
+ use by the BIOS.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+UINT32
+CheckAndFixHeciForAccess (
+ VOID
+ )
+/*++
+
+Routine Description:
+ 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.
+
+Arguments:
+ None.
+
+Returns:
+ VOID
+
+--*/
+;
+
+EFI_STATUS
+WaitForMEReady (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Waits for the ME to report that it is ready for communication over the HECI
+ interface.
+
+ Arguments:
+ None.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+UINT8
+FilledSlots (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer
+ )
+/*++
+
+ Routine Description:
+ Calculate if the circular buffer has overflowed.
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ Arguments:
+ ReadPointer - Location of the read pointer.
+ WritePointer - Location of the write pointer.
+
+ Returns:
+ Number of filled slots.
+
+--*/
+;
+
+EFI_STATUS
+OverflowCB (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer,
+ IN UINT32 BufferDepth
+ )
+/*++
+
+ Routine Description:
+ Calculate if the circular buffer has overflowed
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ Arguments:
+ ReadPointer - Value read from host/me read pointer
+ WritePointer - Value read from host/me write pointer
+ BufferDepth - Value read from buffer depth register
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+HeciPacketRead (
+ IN UINT32 Blocking,
+ OUT HECI_MESSAGE_HEADER *MessageHeader,
+ OUT UINT32 *MessageData,
+ IN OUT UINT32 *Length
+ )
+/*++
+
+ Routine Description:
+ Function to pull one messsage packet off the HECI circular buffer.
+ Corresponds to HECI HPS (part of) section 4.2.4
+
+
+ Arguments:
+ Blocking - Used to determine if the read is BLOCKING or NON_BLOCKING.
+ MessageHeader - Pointer to a buffer for the message header.
+ MessageData - Pointer to a buffer to recieve the message in.
+ Length - On input is the size of the callers buffer in bytes. On
+ output this is the size of the packet in bytes.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+HeciPacketWrite (
+ IN HECI_MESSAGE_HEADER *MessageHeader,
+ IN UINT32 *MessageData
+ )
+/*++
+
+ Routine Description:
+ Function sends one messsage packet through the HECI circular buffer
+ Corresponds to HECI HPS (part of) section 4.2.3
+
+ Arguments:
+ MessageHeader - Pointer to the message header.
+ MessageData - Pointer to the actual message data.
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+Heci1DevSaveEnable (
+ IN OUT UINT32 *DevState
+ )
+/*++
+
+ Routine Description:
+ Save HECI1 State and Enable it
+
+ Arguments:
+ DevState - Device State Save Buffer
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+Heci2DevSaveEnable (
+ IN OUT UINT32 *DevState
+ )
+/*++
+
+ Routine Description:
+ Save HECI2 State and Enable it
+
+ Arguments:
+ DevState - Device State Save Buffer
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+
+EFI_STATUS
+HeciDevRestore (
+ IN UINT32 DevState
+ )
+/*++
+
+ Routine Description:
+ Restore HECI1 State
+
+ Arguments:
+ DevState - Device State Save Buffer
+
+ Returns:
+ EFI_STATUS
+
+--*/
+;
+#endif // _HECI_CORE_H