summaryrefslogtreecommitdiff
path: root/ReferenceCode/ME/Heci/Pei
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/Pei
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/ME/Heci/Pei')
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciCore.c1247
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciInit.c182
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciInit.dxs45
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciInit.h390
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciInit.inf82
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciPei.cif14
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciPei.mak48
-rw-r--r--ReferenceCode/ME/Heci/Pei/HeciPei.sdl24
8 files changed, 2032 insertions, 0 deletions
diff --git a/ReferenceCode/ME/Heci/Pei/HeciCore.c b/ReferenceCode/ME/Heci/Pei/HeciCore.c
new file mode 100644
index 0000000..e248118
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciCore.c
@@ -0,0 +1,1247 @@
+/** @file
+ Heci driver core. For PEI Phase, determines the HECI device and initializes it.
+
+@copyright
+ Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#include "HeciInit.h"
+/**
+ Delay for at least the request number of microseconds
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] Microseconds Number of microseconds to delay.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+Stall (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINTN Microseconds
+ )
+{
+ UINTN Ticks;
+ UINTN Counts;
+ UINT32 CurrentTick;
+ UINT32 OriginalTick;
+ UINT32 RemainingTick;
+ UINT32 AcpiPm1TimerBar;
+
+ if (Microseconds == 0) {
+ return EFI_SUCCESS;
+ }
+
+ AcpiPm1TimerBar = (
+ PciRead32 (PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_ACPI_BASE)) & B_PCH_LPC_ACPI_BASE_BAR
+ ) +
+ R_PCH_ACPI_PM1_TMR;
+
+ OriginalTick = IoRead32 ((UINTN) (UINT64) AcpiPm1TimerBar);
+ OriginalTick &= (PCH_ACPI_TIMER_MAX_VALUE - 1);
+ CurrentTick = OriginalTick;
+
+ ///
+ /// The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks
+ ///
+ Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
+
+ ///
+ /// The loops needed for timer overflow
+ ///
+ Counts = Ticks / PCH_ACPI_TIMER_MAX_VALUE;
+
+ ///
+ /// Remaining clocks within one loop
+ ///
+ RemainingTick = Ticks % PCH_ACPI_TIMER_MAX_VALUE;
+
+ ///
+ /// Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra
+ /// one I/O operation, and may generate SMI
+ ///
+ while (Counts != 0) {
+ CurrentTick = IoRead32 ((UINTN) (UINT64) AcpiPm1TimerBar);
+ CurrentTick &= (PCH_ACPI_TIMER_MAX_VALUE - 1);
+ if (CurrentTick <= OriginalTick) {
+ Counts--;
+ }
+
+ OriginalTick = CurrentTick;
+ }
+
+ while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) {
+ OriginalTick = CurrentTick;
+ CurrentTick = IoRead32 ((UINTN) (UINT64) AcpiPm1TimerBar);
+ CurrentTick &= (PCH_ACPI_TIMER_MAX_VALUE - 1);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enable Hpet function.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval UINT32 Return the High Precision Event Timer base address
+**/
+VOLATILE
+UINT32 *
+EnableHpet (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ VOLATILE UINT32 *HpetConfigReg;
+ VOLATILE UINT32 *HpetTimer;
+ UINT32 Temp32;
+ HpetConfigReg = NULL;
+ ///
+ /// Get the High Precision Event Timer base address and enable the memory range
+ ///
+ HpetConfigReg = (UINT32 *) (PCH_RCRB_BASE + R_PCH_RCRB_HPTC);
+ switch (*HpetConfigReg & B_PCH_RCRB_HPTC_AS) {
+ case 0:
+ HpetTimer = (VOID *) (HPET_ADDRESS_0);
+ break;
+
+ case 1:
+ HpetTimer = (VOID *) (HPET_ADDRESS_1);
+ break;
+
+ case 2:
+ HpetTimer = (VOID *) (HPET_ADDRESS_2);
+ break;
+
+ case 3:
+ HpetTimer = (VOID *) (HPET_ADDRESS_3);
+ break;
+
+ default:
+ HpetTimer = NULL;
+ break;
+ }
+
+ *HpetConfigReg = *HpetConfigReg | B_PCH_RCRB_HPTC_AE;
+ ///
+ /// Read back from RCBA area.
+ ///
+ Temp32 = *HpetConfigReg;
+
+ ///
+ /// Start the timer so it is up and running
+ ///
+ HpetTimer[HPET_GEN_CONFIG_LOW] = HPET_START;
+
+ return HpetTimer;
+}
+
+/**
+ 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] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI
+ @param[in][out] HeciMemBar HECI Memory BAR
+
+ @retval None
+**/
+VOID
+CheckAndFixHeciForAccess (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN OUT UINT32 *HeciMemBar
+ )
+{
+ UINT32 Buffer;
+
+ ///
+ /// Check if HECI_MBAR has changed
+ ///
+ Buffer = HeciPciRead32 (R_HECIMBAR) & 0xFFFFFFF0;
+ if (*HeciMemBar != Buffer) {
+ ///
+ /// If it did change update the mHeciContext variable so we use the proper address for acceses
+ ///
+ *HeciMemBar = Buffer;
+ }
+ ///
+ /// Enable HECI BME and MSE
+ ///
+ HeciPciOr8 (
+ PCI_COMMAND_OFFSET,
+ EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER
+ );
+ return ;
+}
+
+#ifdef EFI_DEBUG
+
+/**
+ For EFI debug used, will show the message of buffer to terminal.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] Message The address of message.
+ @param[in] Length The length of message.
+**/
+VOID
+ShowBuffer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT8 *Message,
+ IN UINT32 Length
+ )
+{
+ UINT32 LineBreak;
+ UINT32 Index;
+ LineBreak = 0;
+ Index = 0;
+
+ while (Length-- > 0) {
+ if (LineBreak == 0) {
+ DEBUG ((EFI_D_ERROR, "%02x: ", (Index & 0xF0)));
+ }
+
+ DEBUG ((EFI_D_ERROR, "%02x ", Message[Index++]));
+ LineBreak++;
+ if (LineBreak == 16) {
+ DEBUG ((EFI_D_ERROR, "\n"));
+ LineBreak = 0;
+ }
+
+ if (LineBreak == 8) {
+ DEBUG ((EFI_D_ERROR, "- "));
+ }
+ }
+
+ DEBUG ((EFI_D_ERROR, "\n"));
+ return ;
+}
+#endif // End Of EFI_DEBUG
+
+/**
+ Determines if the HECI device is present and, if present, initializes it for
+ use by the BIOS.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI
+ @param[in][out] HeciMemBar HECI Memory BAR
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_DEVICE_ERROR No HECI device
+ @retval EFI_TIMEOUT HECI does not return the buffer before timeout
+ @exception EFI_UNSUPPORTED HECI MSG is unsupported
+**/
+EFI_STATUS
+EFIAPI
+InitializeHeci (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN OUT UINT32 *HeciMemBar
+ )
+{
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+ VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr;
+ UINT32 HeciMBar;
+ UINT32 MeMode;
+
+ HeciRegHCsrPtr = NULL;
+ HeciRegMeCsrHaPtr = NULL;
+
+ ///
+ /// Check for HECI-1 PCI device availability
+ ///
+ if (HeciPciRead16 (PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check for ME error status
+ ///
+ if ((HeciPciRead32 (R_FWSTATE) & 0xF000) != 0) {
+ ///
+ /// ME failed to start so no HECI
+ ///
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// HECI MSG is unsupported if ME MODE is in Security Override
+ ///
+ HeciGetMeMode (PeiServices, &MeMode);
+ if (MeMode == ME_MODE_SECOVER) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Get HECI_MBAR and see if it is programmed
+ /// to a useable value
+ ///
+ HeciMBar = HeciPciRead32 (R_HECIMBAR) & 0xFFFFFFF0;
+
+ ///
+ /// Load temporary address for HECI_MBAR if one is not assigned
+ ///
+ if (HeciMBar == 0) {
+ DEBUG ((EFI_D_ERROR, "Heci MMIO Bar not programmed in PEI phase\n"));
+ }
+
+ *HeciMemBar = HeciMBar;
+
+ ///
+ /// Enable HECI BME and MSE
+ ///
+ HeciPciOr8 (
+ PCI_COMMAND_OFFSET,
+ EFI_PCI_COMMAND_MEMORY_SPACE | EFI_PCI_COMMAND_BUS_MASTER
+ );
+
+ ///
+ /// Set HECI interrupt delivery mode.
+ /// HECI-1 using legacy/MSI interrupt
+ ///
+ HeciPciAnd8 (R_HIDM, 0xFC);
+
+ ///
+ /// 2) setup H_CSR reg as follows:
+ /// a) Make sure H_RST is clear
+ /// b) Set H_RDY
+ /// c) Set H_IG
+ ///
+ HeciRegHCsrPtr = (VOID *) (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;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Waits for the ME to report that it is ready for communication over the HECI
+ interface.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_TIMEOUT If 5 second timeout has expired, return fail.
+**/
+EFI_STATUS
+WaitForMEReady (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 HeciMemBar
+ )
+{
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+ VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr;
+ VOLATILE UINT32 *HpetTimer;
+
+ HeciRegMeCsrHaPtr = (VOID *) (HeciMemBar + ME_CSR_HA);
+ ///
+ /// Wait for ME ready
+ ///
+ ///
+ /// Check for ME ready status
+ ///
+ HpetTimer = StartTimer (PeiServices, &TimerStart, &TimerEnd, PEI_HECI_INIT_TIMEOUT);
+ while (HeciRegMeCsrHaPtr->r.ME_RDY_HRA == 0) {
+ ///
+ /// If 5 second timeout has expired, return fail
+ ///
+ if (Timeout (TimerStart, TimerEnd, HpetTimer) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ ///
+ /// Perform IO delay
+ ///
+ Stall (PeiServices, PEI_HECI_WAIT_DELAY);
+ }
+ ///
+ /// ME ready!!!
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Read the HECI Message from Intel ME with size in Length into
+ buffer Message. Set Blocking to BLOCKING and code will wait
+ until one message packet is received. When set to
+ NON_BLOCKING, if the circular buffer is empty at the time, the
+ code not wait for the message packet read.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] Blocking Used to determine if the read is BLOCKING or NON_BLOCKING.
+ @param[in] MessageBody Pointer to a buffer used to receive a message.
+ @param[in][out] Length Pointer to the length of the buffer on input and the length
+ of the message on return. (in bytes)
+
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support this function
+ @retval EFI_SUCCESS One message packet read
+ @retval EFI_TIMEOUT HECI is not ready for communication
+ @retval EFI_DEVICE_ERROR Zero-length message packet read
+ @retval EFI_BUFFER_TOO_SMALL The caller's buffer was not large enough
+**/
+EFI_STATUS
+EFIAPI
+HeciReadMsg (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 Blocking,
+ IN UINT32 HeciMemBar,
+ IN UINT32 *MessageBody,
+ IN OUT UINT32 *Length
+ )
+{
+ HECI_MESSAGE_HEADER PacketHeader;
+ UINT32 CurrentLength;
+ UINT32 MessageComplete;
+ EFI_STATUS ReadError;
+ UINT32 PacketBuffer;
+ UINT32 timer_start;
+ UINT32 timer_end;
+ VOLATILE UINT32 *HpetTimer;
+ UINT32 MeMode;
+
+ CurrentLength = 0;
+ MessageComplete = 0;
+
+ HeciGetMeMode (PeiServices, &MeMode);
+ if (MeMode == ME_MODE_SECOVER) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Make sure that HECI device BAR is correct and device is enabled.
+ ///
+ /// CheckAndFixHeciForAccess (PeiServices, This);
+ ///
+ /// Make sure that HECI is ready for communication.
+ ///
+ if (WaitForMEReady (PeiServices, This, HeciMemBar) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ ///
+ /// Set up timer for BIOS timeout.
+ ///
+ HpetTimer = StartTimer (PeiServices, &timer_start, &timer_end, PEI_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, HpetTimer) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+
+ PacketBuffer = *Length - CurrentLength;
+ ReadError = HeciPacketRead (
+ PeiServices,
+ Blocking,
+ HeciMemBar,
+ &PacketHeader,
+ (UINT32 *) &MessageBody[CurrentLength / 4],
+ &PacketBuffer
+ );
+
+ ///
+ /// Check for error condition on read
+ ///
+ if (EFI_ERROR (ReadError)) {
+ *Length = 0;
+ return ReadError;
+ }
+ ///
+ /// 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;
+ return EFI_SUCCESS;
+ } else {
+ ///
+ /// We should not expect a zero-length message packet except as described above.
+ ///
+ *Length = 0;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ ///
+ /// Track the length of what we have read so far
+ ///
+ CurrentLength += PacketBuffer;
+
+ }
+ ///
+ /// 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;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *Length = CurrentLength;
+
+ DEBUG ((EFI_D_ERROR, "HECI ReadMsg:\n"));
+#ifdef EFI_DEBUG
+ DEBUG_CODE (
+ ShowBuffer (PeiServices, (UINT8 *) MessageBody, *Length);
+ );
+#endif // End Of EFI_DEBUG
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to pull one messsage packet off the HECI circular buffer.
+ Corresponds to HECI HPS (part of) section 4.2.4
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] Blocking Used to determine if the read is BLOCKING or NON_BLOCKING.
+ @param[out] MessageHeader Pointer to a buffer for the message header.
+ @param[out] MessageData Pointer to a buffer to recieve the message in.
+ @param[in][out] Length On input is the size of the callers buffer in bytes. On
+ output this is the size of the packet in bytes.
+
+ @retval EFI_SUCCESS One message packet read.
+ @retval EFI_DEVICE_ERROR The circular buffer is overflowed.
+ @retval EFI_NO_RESPONSE The circular buffer is empty
+ @retval EFI_TIMEOUT Failed to receive a full message
+ @retval EFI_BUFFER_TOO_SMALL Message packet is larger than caller's buffer
+**/
+EFI_STATUS
+HeciPacketRead (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 Blocking,
+ IN UINT32 HeciMemBar,
+ OUT HECI_MESSAGE_HEADER *MessageHeader,
+ OUT UINT32 *MessageData,
+ IN OUT UINT32 *Length
+ )
+{
+ BOOLEAN GotMessage;
+ UINT32 TimerStart;
+ UINT32 TimerEnd;
+ UINT32 TimerStart1;
+ UINT32 TimerEnd1;
+ UINT32 i;
+ UINT32 LengthInDwords;
+ HECI_ME_CONTROL_REGISTER HeciRegMeCsrHa;
+ VOLATILE UINT32 *HpetTimer;
+ ///
+ /// Initialize memory mapped register pointers
+ ///
+ VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+ VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr;
+ VOLATILE UINT32 *HeciRegMeCbrwPtr;
+
+ HeciRegHCsrPtr = (VOID *) (HeciMemBar + H_CSR);
+ HeciRegMeCsrHaPtr = (VOID *) (HeciMemBar + ME_CSR_HA);
+ HeciRegMeCbrwPtr = (VOID *) (HeciMemBar + ME_CB_RW);
+
+ GotMessage = FALSE;
+
+ ///
+ /// clear Interrupt Status bit
+ ///
+ HeciRegHCsrPtr->r.H_IS = 1;
+
+ ///
+ /// test for circular buffer overflow
+ ///
+ HeciRegMeCsrHa.ul = HeciRegMeCsrHaPtr->ul;
+ 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 = HeciRegMeCsrHaPtr->ul;
+ 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
+ ///
+ HpetTimer = StartTimer (PeiServices, &TimerStart, &TimerEnd, PEI_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, HpetTimer) != 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 = HeciRegMeCsrHaPtr->ul;
+ if (FilledSlots (HeciRegMeCsrHa.r.ME_CBRP_HRA, HeciRegMeCsrHa.r.ME_CBWP_HRA) > 0) {
+ ///
+ /// Eat the HECI Message header
+ ///
+ MessageHeader->Data = *HeciRegMeCbrwPtr;
+
+ ///
+ /// 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
+ ///
+ HeciRegHCsrPtr->r.H_IG = 1;
+ *Length = 0;
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Make sure that the message does not overflow the circular buffer.
+ ///
+ if ((MessageHeader->Fields.Length + sizeof (HECI_MESSAGE_HEADER)) > (HeciRegMeCsrHaPtr->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
+ ///
+ HpetTimer = StartTimer (PeiServices, &TimerStart1, &TimerEnd1, PEI_HECI_READ_TIMEOUT);
+
+ ///
+ /// Wait here until entire message is present in circular buffer
+ ///
+ HeciRegMeCsrHa.ul = HeciRegMeCsrHaPtr->ul;
+ 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, HpetTimer) != EFI_SUCCESS) {
+ *Length = 0;
+ return EFI_TIMEOUT;
+ }
+ ///
+ /// Wait before we read the register again
+ ///
+ Stall (PeiServices, PEI_HECI_WAIT_DELAY);
+
+ ///
+ /// Read the register again
+ ///
+ HeciRegMeCsrHa.ul = HeciRegMeCsrHaPtr->ul;
+ }
+ ///
+ /// copy rest of message
+ ///
+ for (i = 0; i < LengthInDwords; i++) {
+ MessageData[i] = *HeciRegMeCbrwPtr;
+ }
+ ///
+ /// 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
+ ///
+ Stall (PeiServices, PEI_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
+ ///
+ if (HeciRegMeCsrHaPtr->r.ME_RDY_HRA == 0) {
+ *Length = 0;
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Set Interrupt Generate bit
+ ///
+ HeciRegHCsrPtr->r.H_IG = 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function sends one messsage (of any length) through the HECI circular buffer.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] Message Pointer to the message data to be sent.
+ @param[in] Length Length of the message in bytes.
+ @param[in] HostAddress The address of the host processor.
+ @param[in] MeAddress Address of the ME subsystem the message is being sent to.
+
+ @retval EFI_SUCCESS One message packet sent.
+ @retval EFI_DEVICE_ERROR Failed to initialize HECI
+ @retval EFI_TIMEOUT HECI is not ready for communication
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support send message through HEC
+**/
+EFI_STATUS
+HeciSendMsg (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 *Message,
+ IN UINT32 HeciMemBar,
+ IN UINT32 Length,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+{
+ UINT32 CBLength;
+ UINT32 SendLength;
+ UINT32 CurrentLength;
+ HECI_MESSAGE_HEADER MessageHeader;
+ EFI_STATUS WriteStatus;
+ VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+ UINT32 MeMode;
+
+ CurrentLength = 0;
+ HeciRegHCsrPtr = NULL;
+
+ HeciGetMeMode (PeiServices, &MeMode);
+ if (MeMode == ME_MODE_SECOVER) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_ERROR, "HECI SendMsg:\n"));
+#ifdef EFI_DEBUG
+ DEBUG_CODE (
+ ShowBuffer (PeiServices, (UINT8 *) Message, Length);
+ );
+#endif // End Of EFI_DEBUG
+ ///
+ /// Make sure that HECI device BAR is correct and device is enabled.
+ ///
+ /// CheckAndFixHeciForAccess (PeiServices, This);
+ ///
+ /// Make sure that HECI is ready for communication.
+ ///
+ if (WaitForMEReady (PeiServices, This, HeciMemBar) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ ///
+ /// Set up memory mapped registers
+ ///
+ HeciRegHCsrPtr = (VOID *) (HeciMemBar + H_CSR);
+
+ ///
+ /// Grab Circular Buffer length
+ ///
+ CBLength = HeciRegHCsrPtr->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;
+
+ DEBUG ((EFI_D_ERROR, "HECI Header: %08x\n", MessageHeader.Data));
+ ///
+ /// send the current packet (CurrentLength can be treated as the index into the message buffer)
+ ///
+ WriteStatus = HeciPacketWrite (
+ PeiServices,
+ This,
+ HeciMemBar,
+ &MessageHeader,
+ (UINT32 *) ((UINT32) Message + CurrentLength)
+ );
+ if (EFI_ERROR (WriteStatus)) {
+ return WriteStatus;
+ }
+ ///
+ /// Update the length information
+ ///
+ CurrentLength += SendLength;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function sends one messsage packet through the HECI circular buffer
+ Corresponds to HECI HPS (part of) section 4.2.3
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] MessageHeader Pointer to the message header.
+ @param[in] MessageData Pointer to the actual message data.
+
+ @retval EFI_SUCCESS One message packet sent
+ @retval EFI_DEVICE_ERROR ME is not ready
+ @retval EFI_TIMEOUT HECI is not ready for communication
+**/
+EFI_STATUS
+HeciPacketWrite (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 HeciMemBar,
+ IN HECI_MESSAGE_HEADER *MessageHeader,
+ IN UINT32 *MessageData
+ )
+{
+ UINT32 timer_start;
+ UINT32 timer_end;
+ UINT32 i;
+ UINT32 LengthInDwords;
+ HECI_HOST_CONTROL_REGISTER HeciRegHCsr;
+ VOLATILE UINT32 *HpetTimer;
+ VOLATILE HECI_HOST_CONTROL_REGISTER *HeciRegHCsrPtr;
+ VOLATILE HECI_ME_CONTROL_REGISTER *HeciRegMeCsrHaPtr;
+ VOLATILE UINT32 *HeciRegHCbwwPtr;
+
+ HeciRegHCsrPtr = (VOID *) (HeciMemBar + H_CSR);
+ HeciRegMeCsrHaPtr = (VOID *) (HeciMemBar + ME_CSR_HA);
+ HeciRegHCbwwPtr = (VOID *) (HeciMemBar + H_CB_WW);
+ ///
+ /// Make sure that HECI is ready for communication.
+ ///
+ if (WaitForMEReady (PeiServices, This, HeciMemBar) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ ///
+ /// Start timeout counter
+ ///
+ HpetTimer = StartTimer (PeiServices, &timer_start, &timer_end, PEI_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 = HeciRegHCsrPtr->ul;
+ 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, HpetTimer) != EFI_SUCCESS) {
+ return EFI_TIMEOUT;
+ }
+ ///
+ /// Wait before we read the register again
+ ///
+ Stall (PeiServices, PEI_HECI_WAIT_DELAY);
+
+ ///
+ /// Read Host CSR for next iteration
+ ///
+ HeciRegHCsr.ul = HeciRegHCsrPtr->ul;
+ }
+ ///
+ /// Write Message Header
+ ///
+ *HeciRegHCbwwPtr = MessageHeader->Data;
+
+ ///
+ /// Write Message Body
+ ///
+ for (i = 0; i < LengthInDwords; i++) {
+ *HeciRegHCbwwPtr = MessageData[i];
+ }
+ ///
+ /// Set Interrupt Generate bit
+ ///
+ HeciRegHCsrPtr->r.H_IG = 1;
+
+ ///
+ /// Test if ME Ready bit is set to 1, if set to 0 a fatal error occured during
+ /// the transmission of this message.
+ ///
+ if (HeciRegMeCsrHaPtr->r.ME_RDY_HRA == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function sends one messsage through the HECI circular buffer and waits
+ for the corresponding ACK message.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in][out] Message Pointer to the message buffer.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in][out] Length Length of the message in bytes.
+ @param[in] HostAddress Address of the sending entity.
+ @param[in] MeAddress Address of the ME entity that should receive the message.
+
+ @retval EFI_SUCCESS Command succeeded
+ @retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
+ @retval EFI_TIMEOUT HECI does not return the bufferbefore timeout
+ @retval EFI_BUFFER_TOO_SMALL Message Buffer is too small for the Acknowledge
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support send message through HECI
+**/
+EFI_STATUS
+HeciSendwAck (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN OUT UINT32 *Message,
+ IN UINT32 HeciMemBar,
+ IN OUT UINT32 *Length,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MeMode;
+
+ HeciGetMeMode (PeiServices, &MeMode);
+ if (MeMode == ME_MODE_SECOVER) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Send the message
+ ///
+ Status = HeciSendMsg (PeiServices, This, Message, HeciMemBar, *Length, HostAddress, MeAddress);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Wait for ACK message
+ ///
+ return HeciReadMsg (PeiServices, This, BLOCKING, HeciMemBar, Message, Length);
+}
+
+/**
+ Calculate if the circular buffer has overflowed.
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ @param[in] ReadPointer Location of the read pointer.
+ @param[in] WritePointer Location of the write pointer.
+
+ @retval UINT8 Number of filled slots.
+**/
+UINT8
+FilledSlots (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer
+ )
+{
+ UINT8 FilledSlots;
+
+ ///
+ /// Calculation documented in HECI HPS 0.68 section 4.2.1
+ ///
+ FilledSlots = (((INT8) WritePointer) - ((INT8) ReadPointer));
+
+ return FilledSlots;
+}
+
+/**
+ Calculate if the circular buffer has overflowed
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ @param[in] ReadPointer Value read from host/me read pointer
+ @param[in] WritePointer Value read from host/me write pointer
+ @param[in] BufferDepth Value read from buffer depth register
+
+ @retval EFI_DEVICE_ERROR The circular buffer has overflowed
+ @retval EFI_SUCCESS The circular buffer does not overflowed
+**/
+EFI_STATUS
+OverflowCB (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer,
+ IN UINT32 BufferDepth
+ )
+{
+ 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;
+}
+
+/**
+ Used for calculating timeouts
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] Start Snapshot of the HPET timer
+ @param[in] End Calculated time when timeout period will be done
+ @param[in] Time Timeout period in microseconds
+
+ @retval None
+**/
+VOLATILE
+UINT32 *
+StartTimer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ OUT UINT32 *Start,
+ OUT UINT32 *End,
+ IN UINT32 Time
+ )
+{
+ UINT32 Ticks;
+ VOLATILE UINT32 *HpetTimer;
+ ///
+ /// Make sure that HPET is enabled and running
+ ///
+ HpetTimer = EnableHpet (PeiServices);
+
+ ///
+ /// Read current timer value into start time from HPET
+ ///
+ *Start = HpetTimer[HPET_MAIN_COUNTER_LOW];
+
+ ///
+ /// Convert microseconds into 70ns timer ticks
+ ///
+ Ticks = Time * HPET_TICKS_PER_MICRO;
+
+ ///
+ /// Compute end time
+ ///
+ *End = *Start + Ticks;
+
+ return HpetTimer;
+}
+
+/**
+ Used to determine if a timeout has occured.
+
+ @param[in] Start Snapshot of the HPET timer when the timeout period started.
+ @param[in] End Calculated time when timeout period will be done.
+ @param[in] HpetTimer The value of High Precision Event Timer
+
+ @retval EFI_TIMEOUT Timeout occured.
+ @retval EFI_SUCCESS Not yet timed out
+**/
+EFI_STATUS
+Timeout (
+ IN UINT32 Start,
+ IN UINT32 End,
+ IN VOLATILE UINT32 *HpetTimer
+ )
+{
+ UINT32 Current;
+
+ ///
+ /// Read HPET and assign the value as the current time.
+ ///
+ Current = HpetTimer[HPET_MAIN_COUNTER_LOW];
+
+ ///
+ /// If no timeout, current timer always is +1 to Start timer
+ ///
+ /// if(This->HeciTimeout == 0){
+ /// Current = Start + 1;
+ /// }
+ ///
+ /// 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;
+}
+
+/**
+ Get an abstract Intel ME Status from Firmware Status Register.
+ This is used to control BIOS flow for different Intel ME
+ functions.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] MeStatus Pointer for status report,
+ see MeState.h - Abstract ME status definitions.
+
+ @retval EFI_SUCCESS MeStatus copied
+ @retval EFI_INVALID_PARAMETER Pointer of MeStatus is invalid
+**/
+EFI_STATUS
+EFIAPI
+HeciGetMeStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 *MeStatus
+ )
+{
+ HECI_FWS_REGISTER MeFirmwareStatus;
+
+ if (MeStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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;
+ }
+
+ DEBUG ((EFI_D_ERROR, "HECI MeStatus %X\n", MeFirmwareStatus.ul));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get an abstract ME operation mode from firmware status
+ register. This is used to control BIOS flow for different
+ Intel ME functions.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] MeMode Pointer for ME Mode report,
+ see MeState.h - Abstract ME Mode definitions.
+
+ @retval EFI_SUCCESS MeMode copied
+ @retval EFI_INVALID_PARAMETER Pointer of MeMode is invalid
+**/
+EFI_STATUS
+EFIAPI
+HeciGetMeMode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 *MeMode
+ )
+{
+ HECI_FWS_REGISTER MeFirmwareStatus;
+
+ if (MeMode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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;
+ }
+ DEBUG ((EFI_D_ERROR, "HECI MeMode %X\n", MeFirmwareStatus.r.MeOperationMode));
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/ME/Heci/Pei/HeciInit.c b/ReferenceCode/ME/Heci/Pei/HeciInit.c
new file mode 100644
index 0000000..0375bd7
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciInit.c
@@ -0,0 +1,182 @@
+/** @file
+ Framework PEIM to HECI.
+
+@copyright
+ Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+//
+// Statements that include other files
+//
+#include "HeciInit.h"
+#endif
+//
+// Function Declarations
+//
+static PEI_HECI_PPI mHeciPpi = {
+ HeciSendwAck,
+ HeciReadMsg,
+ HeciSendMsg,
+ InitializeHeci,
+ HeciGetMeStatus,
+ HeciGetMeMode
+};
+
+static EFI_PEI_PPI_DESCRIPTOR mInstallHeciPpi = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gPeiHeciPpiGuid,
+ &mHeciPpi
+};
+
+//
+// Function Implementations
+//
+
+/**
+ Internal function performing Heci platform PPIs init needed in PEI phase
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_DEVICE_ERROR ME FPT is bad
+**/
+EFI_STATUS
+EFIAPI
+PeiInstallHeciPpi (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Check for ME FPT Bad
+ ///
+ if ((HeciPciRead32 (R_FWSTATE) & 0x0020) != 0) {
+
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Initialize Heci platform PPIs
+ /// Do not use EdkIIGlueLib here because PeiService pointer used in GlueLib
+ /// is not updated after memory installed.
+ ///
+ Status = (**PeiServices).InstallPpi (PeiServices, &mInstallHeciPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((EFI_D_ERROR, "Install Heci Ppi Complete.\n"));
+ return Status;
+}
+
+/**
+ Internal function performing PM register initialization for Me
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+MePmInit (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ UINT16 PmBase;
+ UINT16 Pm1Cnt;
+
+ ///
+ /// Before system memory initialization, BIOS should check the WAK_STS bit in PM1_STS[15] (PCH register PMBASE+00h)
+ /// to determine if Intel Management Engine has reset the system while the host was in a sleep state. If WAK_STS is
+ /// not set, BIOS should ensure a non-sleep exit path is taken. One way to accomplish this is by overwriting
+ /// PM1_CNT[12:10] (PCH register PMBASE+04h) to 111b to force an S5 exit path by the BIOS.
+ ///
+ PmBase = PciRead16 (
+ PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ 0,
+ R_PCH_LPC_ACPI_BASE)
+ ) & B_PCH_LPC_ACPI_BASE_BAR;
+
+ ASSERT (PmBase != 0);
+
+ if (PmBase != 0) {
+ if ((IoRead16 (PmBase + R_PCH_ACPI_PM1_STS) & B_PCH_ACPI_PM1_STS_WAK) == 0) {
+ Pm1Cnt = IoRead16 (PmBase + R_PCH_ACPI_PM1_CNT) | V_PCH_ACPI_PM1_CNT_S5;
+ IoWrite16 (PmBase + R_PCH_ACPI_PM1_CNT, Pm1Cnt);
+ DEBUG ((EFI_D_ERROR, "Force an S5 exit path.\n"));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal function performing Me initialization.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS Heci initialization completed successfully.
+ @retval All other error conditions encountered result in an ASSERT.
+**/
+EFI_STATUS
+EFIAPI
+MeInit (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MePmInit (PeiServices);
+ return Status;
+}
+
+/**
+ Initialize ME after reset
+
+ @param[in] FfsHeader Not used.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS Heci initialization completed successfully.
+ @retval All other error conditions encountered result in an ASSERT.
+**/
+EFI_STATUS
+PeimHeciInit (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Performing Me initialization
+ ///
+ Status = MeInit (PeiServices);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiInstallHeciPpi (PeiServices);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "(ICC) Failed to PeiInstallHeciPpi! Status = %r\n", Status));
+ } else {
+ DEBUG ((EFI_D_INFO, "HeciInit Complete.\n"));
+ }
+
+ return Status;
+}
diff --git a/ReferenceCode/ME/Heci/Pei/HeciInit.dxs b/ReferenceCode/ME/Heci/Pei/HeciInit.dxs
new file mode 100644
index 0000000..2db83cd
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciInit.dxs
@@ -0,0 +1,45 @@
+/** @file
+ Dependency expression file for Heci Init PEIM.
+
+@copyright
+ Copyright (c) 2010 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains 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
+
+**/
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "PeimDepex.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"
+
+#endif
+
+
+DEPENDENCY_START
+
+ TRUE
+DEPENDENCY_END
+
+
+
+
diff --git a/ReferenceCode/ME/Heci/Pei/HeciInit.h b/ReferenceCode/ME/Heci/Pei/HeciInit.h
new file mode 100644
index 0000000..a8dab69
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciInit.h
@@ -0,0 +1,390 @@
+/** @file
+ Framework PEIM to provide Heci.
+
+@copyright
+ Copyright (c) 2008 - 2012 Intel Corporation. All rights reserved
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#ifndef _HECI_INIT_H_
+#define _HECI_INIT_H_
+
+#include "EdkIIGluePeim.h"
+#include "MeAccess.h"
+#include "HeciRegs.h"
+#include "MeState.h"
+#include "CoreBiosMsg.h"
+#include "Pci22.h"
+
+//
+// Driver Consumed PPI Prototypes
+//
+#include EFI_PPI_DEPENDENCY (CpuIo)
+#include EFI_PPI_DEPENDENCY (PciCfg)
+#include EFI_PPI_DEPENDENCY (Heci)
+#include EFI_PPI_DEPENDENCY (MemoryDiscovered)
+
+//
+// Prototypes
+//
+
+/**
+ Enable Hpet function.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval UINT32 Return the High Precision Event Timer base address
+**/
+VOLATILE
+UINT32 *
+EnableHpet (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+;
+
+/**
+ 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] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI
+ @param[in][out] HeciMemBar HECI Memory BAR
+
+ @retval None
+**/
+VOID
+CheckAndFixHeciForAccess (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN OUT UINT32 *HeciMemBar
+ )
+;
+
+/**
+ Determines if the HECI device is present and, if present, initializes it for
+ use by the BIOS.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI
+ @param[in][out] HeciMemBar HECI Memory BAR
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_DEVICE_ERROR No HECI device
+ @retval EFI_TIMEOUT HECI does not return the buffer before timeout
+ @exception EFI_UNSUPPORTED HECI MSG is unsupported
+**/
+EFI_STATUS
+EFIAPI
+InitializeHeci (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN OUT UINT32 *HeciMemBar
+ )
+;
+
+/**
+ Waits for the ME to report that it is ready for communication over the HECI
+ interface.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_TIMEOUT If 5 second timeout has expired, return fail.
+**/
+EFI_STATUS
+WaitForMEReady (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 HeciMemBar
+ )
+;
+
+/**
+ Read the HECI Message from Intel ME with size in Length into
+ buffer Message. Set Blocking to BLOCKING and code will wait
+ until one message packet is received. When set to
+ NON_BLOCKING, if the circular buffer is empty at the time, the
+ code not wait for the message packet read.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] Blocking Used to determine if the read is BLOCKING or NON_BLOCKING.
+ @param[in] MessageBody Pointer to a buffer used to receive a message.
+ @param[in][out] Length Pointer to the length of the buffer on input and the length
+ of the message on return. (in bytes)
+
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support this function
+ @retval EFI_SUCCESS One message packet read
+ @retval EFI_TIMEOUT HECI is not ready for communication
+ @retval EFI_DEVICE_ERROR Zero-length message packet read
+ @retval EFI_BUFFER_TOO_SMALL The caller's buffer was not large enough
+**/
+EFI_STATUS
+EFIAPI
+HeciReadMsg (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 Blocking,
+ IN UINT32 HeciMemBar,
+ IN UINT32 *MessageBody,
+ IN OUT UINT32 *Length
+ )
+;
+
+/**
+ Function to pull one messsage packet off the HECI circular buffer.
+ Corresponds to HECI HPS (part of) section 4.2.4
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] Blocking Used to determine if the read is BLOCKING or NON_BLOCKING.
+ @param[out] MessageHeader Pointer to a buffer for the message header.
+ @param[out] MessageData Pointer to a buffer to recieve the message in.
+ @param[in][out] Length On input is the size of the callers buffer in bytes. On
+ output this is the size of the packet in bytes.
+
+ @retval EFI_SUCCESS One message packet read.
+ @retval EFI_DEVICE_ERROR The circular buffer is overflowed.
+ @retval EFI_NO_RESPONSE The circular buffer is empty
+ @retval EFI_TIMEOUT Failed to receive a full message
+ @retval EFI_BUFFER_TOO_SMALL Message packet is larger than caller's buffer
+**/
+EFI_STATUS
+HeciPacketRead (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 Blocking,
+ IN UINT32 HeciMemBar,
+ OUT HECI_MESSAGE_HEADER *MessageHeader,
+ OUT UINT32 *MessageData,
+ IN OUT UINT32 *Length
+ )
+;
+
+/**
+ Function sends one messsage (of any length) through the HECI circular buffer.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] Message Pointer to the message data to be sent.
+ @param[in] Length Length of the message in bytes.
+ @param[in] HostAddress The address of the host processor.
+ @param[in] MeAddress Address of the ME subsystem the message is being sent to.
+
+ @retval EFI_SUCCESS One message packet sent.
+ @retval EFI_DEVICE_ERROR Failed to initialize HECI
+ @retval EFI_TIMEOUT HECI is not ready for communication
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support send message through HEC
+**/
+EFI_STATUS
+HeciSendMsg (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 *Message,
+ IN UINT32 HeciMemBar,
+ IN UINT32 Length,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+;
+
+/**
+ Function sends one messsage packet through the HECI circular buffer
+ Corresponds to HECI HPS (part of) section 4.2.3
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in] MessageHeader Pointer to the message header.
+ @param[in] MessageData Pointer to the actual message data.
+
+ @retval EFI_SUCCESS One message packet sent
+ @retval EFI_DEVICE_ERROR ME is not ready
+ @retval EFI_TIMEOUT HECI is not ready for communication
+**/
+EFI_STATUS
+HeciPacketWrite (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN UINT32 HeciMemBar,
+ IN HECI_MESSAGE_HEADER *MessageHeader,
+ IN UINT32 *MessageData
+ )
+;
+
+/**
+ Function sends one messsage through the HECI circular buffer and waits
+ for the corresponding ACK message.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] This The address of HECI PPI.
+ @param[in][out] Message Pointer to the message buffer.
+ @param[in] HeciMemBar HECI Memory BAR.
+ @param[in][out] Length Length of the message in bytes.
+ @param[in] HostAddress Address of the sending entity.
+ @param[in] MeAddress Address of the ME entity that should receive the message.
+
+ @retval EFI_SUCCESS Command succeeded
+ @retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
+ @retval EFI_TIMEOUT HECI does not return the bufferbefore timeout
+ @retval EFI_BUFFER_TOO_SMALL Message Buffer is too small for the Acknowledge
+ @exception EFI_UNSUPPORTED Current ME mode doesn't support send message through HECI
+**/
+EFI_STATUS
+HeciSendwAck (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_HECI_PPI *This,
+ IN OUT UINT32 *Message,
+ IN UINT32 HeciMemBar,
+ IN OUT UINT32 *Length,
+ IN UINT8 HostAddress,
+ IN UINT8 MeAddress
+ )
+;
+
+/**
+ Calculate if the circular buffer has overflowed
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ @param[in] ReadPointer Value read from host/me read pointer
+ @param[in] WritePointer Value read from host/me write pointer
+ @param[in] BufferDepth Value read from buffer depth register
+
+ @retval EFI_DEVICE_ERROR The circular buffer has overflowed
+ @retval EFI_SUCCESS The circular buffer does not overflowed
+**/
+EFI_STATUS
+OverflowCB (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer,
+ IN UINT32 BufferDepth
+ )
+;
+
+/**
+ Used for calculating timeouts
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] Start Snapshot of the HPET timer
+ @param[in] End Calculated time when timeout period will be done
+ @param[in] Time Timeout period in microseconds
+
+ @retval None
+**/
+VOLATILE
+UINT32 *
+StartTimer (
+ IN EFI_PEI_SERVICES **PeiServices,
+ OUT UINT32 *Start,
+ OUT UINT32 *End,
+ IN UINT32 Time
+ )
+;
+
+/**
+ Used to determine if a timeout has occured.
+
+ @param[in] Start Snapshot of the HPET timer when the timeout period started.
+ @param[in] End Calculated time when timeout period will be done.
+ @param[in] HpetTimer The value of High Precision Event Timer
+
+ @retval EFI_TIMEOUT Timeout occured.
+ @retval EFI_SUCCESS Not yet timed out
+**/
+EFI_STATUS
+Timeout (
+ IN UINT32 Start,
+ IN UINT32 End,
+ IN VOLATILE UINT32 *HpetTimer
+ )
+;
+
+/**
+ Get an abstract Intel ME Status from Firmware Status Register.
+ This is used to control BIOS flow for different Intel ME
+ functions.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] MeStatus Pointer for status report,
+ see MeState.h - Abstract ME status definitions.
+
+ @retval EFI_SUCCESS MeStatus copied
+ @retval EFI_INVALID_PARAMETER Pointer of MeStatus is invalid
+**/
+EFI_STATUS
+EFIAPI
+HeciGetMeStatus (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 *MeStatus
+ )
+;
+
+/**
+ Get an abstract ME operation mode from firmware status
+ register. This is used to control BIOS flow for different
+ Intel ME functions.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] MeMode Pointer for ME Mode report,
+ see MeState.h - Abstract ME Mode definitions.
+
+ @retval EFI_SUCCESS MeMode copied
+ @retval EFI_INVALID_PARAMETER Pointer of MeMode is invalid
+**/
+EFI_STATUS
+EFIAPI
+HeciGetMeMode (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT32 *MeMode
+ )
+;
+
+/**
+ Initialize ME after reset
+
+ @param[in] FfsHeader Not used.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS Heci initialization completed successfully.
+ @retval All other error conditions encountered result in an ASSERT.
+**/
+EFI_STATUS
+PeimHeciInit (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+;
+
+/**
+ Calculate if the circular buffer has overflowed.
+ Corresponds to HECI HPS (part of) section 4.2.1
+
+ @param[in] ReadPointer Location of the read pointer.
+ @param[in] WritePointer Location of the write pointer.
+
+ @retval UINT8 Number of filled slots.
+**/
+UINT8
+FilledSlots (
+ IN UINT32 ReadPointer,
+ IN UINT32 WritePointer
+ )
+;
+#endif // _HECI_INIT_H_
diff --git a/ReferenceCode/ME/Heci/Pei/HeciInit.inf b/ReferenceCode/ME/Heci/Pei/HeciInit.inf
new file mode 100644
index 0000000..2181282
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciInit.inf
@@ -0,0 +1,82 @@
+## @file
+# Component description file for HeciInit module
+#
+#@copyright
+# Copyright (c) 2010 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains 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
+#
+
+[defines]
+BASE_NAME = HeciInit
+FILE_GUID = 4862aff3-667c-5458-b274-a1c62df8ba80
+COMPONENT_TYPE = PE32_PEIM
+
+[sources.common]
+ HeciInit.c
+ HeciInit.h
+ HeciCore.c
+ ../Include/HeciRegs.h
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGluePeimEntryPoint.c
+
+[includes.common]
+ $(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
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+
+
+[libraries.common]
+ EdkFrameworkPpiLib
+ MeLibPpi
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGluePeiDebugLibReportStatusCode
+ EdkIIGluePeiReportStatusCodeLib
+ EdkIIGluePeiServicesLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGlueBasePciExpressLib
+ EdkPpiLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = HeciInit.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PeimHeciInit
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_PEI_SERVICES_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
diff --git a/ReferenceCode/ME/Heci/Pei/HeciPei.cif b/ReferenceCode/ME/Heci/Pei/HeciPei.cif
new file mode 100644
index 0000000..c009607
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciPei.cif
@@ -0,0 +1,14 @@
+<component>
+ name = "HeciPei"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\ME\Heci\Pei\"
+ RefName = "HeciPei"
+[files]
+"HeciPei.sdl"
+"HeciPei.mak"
+"HeciCore.c"
+"HeciInit.c"
+"HeciInit.dxs"
+"HeciInit.h"
+"HeciInit.inf"
+<endComponent>
diff --git a/ReferenceCode/ME/Heci/Pei/HeciPei.mak b/ReferenceCode/ME/Heci/Pei/HeciPei.mak
new file mode 100644
index 0000000..990bcf1
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciPei.mak
@@ -0,0 +1,48 @@
+# MAK file for the ModulePart:HeciPei
+
+all: HeciPei
+
+$(BUILD_DIR)\HeciPei.mak : $(HeciPei_DIR)\HeciPei.cif $(BUILD_RULES)
+ $(CIF2MAK) $(HeciPei_DIR)\HeciPei.cif $(CIF2MAK_DEFAULTS)
+
+HeciPei: $(BUILD_DIR)\HeciPei.mak HeciPeiBin
+
+HeciPei_INCLUDES=\
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(ME_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)
+
+
+HeciPei_DEFINES=$(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PeimHeciInit"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__\
+ /D __EDKII_GLUE_PEI_SERVICES_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+
+HeciPei_LIBS =\
+ $(EDKPROTOCOLLIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseLibIA32_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\
+ $(EdkIIGluePeiReportStatusCodeLib_LIB)\
+ $(EdkIIGluePeiServicesLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+
+
+HeciPeiBin : $(EDKFRAMEWORKPPILIB) $(MeLibPpi_LIB) $(HeciPei_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\HeciPei.mak all\
+ NAME=HeciPei\
+ MAKEFILE=$(BUILD_DIR)\HeciPei.mak \
+ GUID=9cf30325-dc5c-4556-a8b0-74215c5f7fc4\
+ "MY_INCLUDES=$(HeciPei_INCLUDES)" \
+ "MY_DEFINES=$(HeciPei_DEFINES)"\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=PEIM \
+ EDKIIModule=PEIM\
+ DEPEX1=$(HeciPei_DIR)\HeciInit.dxs DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ COMPRESS=0
diff --git a/ReferenceCode/ME/Heci/Pei/HeciPei.sdl b/ReferenceCode/ME/Heci/Pei/HeciPei.sdl
new file mode 100644
index 0000000..e193446
--- /dev/null
+++ b/ReferenceCode/ME/Heci/Pei/HeciPei.sdl
@@ -0,0 +1,24 @@
+TOKEN
+ Name = HeciPei_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable HeciPei support in Project"
+End
+MODULE
+ Help = "Includes HeciPei.mak to Project"
+ File = "HeciPei.mak"
+End
+
+PATH
+ Name = "HeciPei_DIR"
+ Help = "Me Heci Pei file source directory"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\HeciPei.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End \ No newline at end of file