diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/ME/PchMeUma | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/ME/PchMeUma')
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.c | 765 | ||||
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.cif | 13 | ||||
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.dxs | 50 | ||||
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.h | 178 | ||||
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.inf | 88 | ||||
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.mak | 62 | ||||
-rw-r--r-- | ReferenceCode/ME/PchMeUma/PchMeUma.sdl | 41 |
7 files changed, 1197 insertions, 0 deletions
diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.c b/ReferenceCode/ME/PchMeUma/PchMeUma.c new file mode 100644 index 0000000..dd8b51b --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.c @@ -0,0 +1,765 @@ +/** @file + Framework PEIM to PchMeUma + +@copyright + Copyright (c) 2010 - 2013 Intel Corporation. All rights + reserved This software and associated documentation (if any) + is furnished under a license and may only be used or copied in + accordance with the terms of the license. Except as permitted + by such license, no part of this software or documentation may + be reproduced, stored in a retrieval system, or transmitted in + any form or by any means without the express written consent + of Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement + +**/ + +// +// Statements that include other files +// +#include "EdkIIGluePeim.h" +#include "MeAccess.h" +#include "HeciRegs.h" +#include "Pci22.h" +#include "PchMeUma.h" +#include "PchPlatformLib.h" +#include "PttHciDeviceLib.h" +#include "PttHciRegs.h" +#include EFI_PPI_DEFINITION (PchMeUma) +#ifdef PTT_FLAG +#include EFI_PPI_DEFINITION (MePlatformPolicyPei) +#endif +#include EFI_PPI_DEFINITION (Stall) +#include EFI_PPI_CONSUMER (Wdt) + +// +// Function Declarations +// +static PCH_ME_UMA_PPI mPchMeUmaPpi = { + MeSendUmaSize, + CpuReplacementCheck, + MeConfigDidReg, + HandleMeBiosAction +}; + +static EFI_PEI_PPI_DESCRIPTOR mPchMeUmaPpiList[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPchMeUmaPpiGuid, + &mPchMeUmaPpi + } +}; + +/** + This procedure will read and return the amount of ME UMA requested + by ME ROM from the HECI device. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Pointer to the FFS file header + + @retval UINT32 Return ME UMA Size + @retval EFI_SUCCESS Do not check for ME UMA +**/ +UINT32 +MeSendUmaSize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + UINT32 Timeout; + HECI_MISC_SHDW_REGISTER MeMiscShdw; + HECI_FWS_REGISTER MeHfs; + EFI_STATUS Status; + PEI_STALL_PPI *StallPpi; + + MeMiscShdw.ul = HeciPciRead32 (R_ME_MISC_SHDW); + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + Timeout = 0x0; + + if (MeHfs.r.MeOperationMode == ME_OPERATION_MODE_DEBUG) { + DEBUG ((EFI_D_INFO, "ME debug mode, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + + if (MeHfs.r.ErrorCode != 0) { + DEBUG ((EFI_D_INFO, "ME error, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + /// + /// Poll on MUSZV until it indicates a valid size is present or 5s timeout expires. + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + + PERF_START_EX (FfsHeader, L"MUSZV", NULL, AsmReadTsc (), 0x4000); + while ((MeMiscShdw.r.MUSZV == 0) && (Timeout < MUSZV_TIMEOUT_MULTIPLIER)) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND); + MeMiscShdw.ul = HeciPciRead32 (R_ME_MISC_SHDW); + Timeout++; + } + + if (Timeout >= MUSZV_TIMEOUT_MULTIPLIER) { + DEBUG ((EFI_D_INFO, "Timeout occurred waiting for MUSZV. \n")); + return EFI_SUCCESS; + } + PERF_END_EX (FfsHeader, L"MUSZV", NULL, AsmReadTsc (), 0x4001); + + /// + /// Return MeUmaSize value + /// + DEBUG ((EFI_D_INFO, "ME UMA Size Requested: %x\n", MeMiscShdw.r.MUSZ)); + + return MeMiscShdw.r.MUSZ; +} + +/** + Init and Install ME Hob + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +InstallMeHob ( + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + ME_DATA_HOB *MeDataHob; + + /// + /// Create HOB for ME Data + /// + Status = (**PeiServices).CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof (ME_DATA_HOB), + &MeDataHob + ); + ASSERT_EFI_ERROR (Status); + + /// + /// Initialize default HOB data + /// + MeDataHob->EfiHobGuidType.Name = gMeDataHobGuid; + ZeroMem (&(MeDataHob->FtpmBufferAddress), sizeof (UINT64)); + + DEBUG ((EFI_D_INFO, "ME Data HOB installed\n")); + + return EFI_SUCCESS; +} + +#ifdef PTT_FLAG +/** + Internal function performing Heci platform ME Debug Dump in PEI phase + + @param[in] PeiMePolicyPpi Policy Ppi + + @retval None +**/ +VOID +DumpMePlatformPolicyPei ( + IN PEI_ME_PLATFORM_POLICY_PPI *PeiMePolicyPpi + ) +{ + DEBUG ((EFI_D_INFO, "\n------------------------ MePlatformPolicyPpi Dump Begin -----------------\n")); + DEBUG ((EFI_D_INFO, " Revision : 0x%x\n", PeiMePolicyPpi->Revision)); + DEBUG ((EFI_D_INFO, " FTpmSwitch : 0x%x\n", PeiMePolicyPpi->FTpmSwitch)); + DEBUG ((EFI_D_INFO, "\n------------------------ MePlatformPolicyPpi Dump End -------------------\n")); +} +#endif + +/** + This procedure will determine whether or not the CPU was replaced + during system power loss or via dynamic fusing. + Calling this procedure could result in a warm reset (if ME FW is requesting one). + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Not used. + @param[out] ForceFullTraining When set = 0x1, MRC will be forced to perform a full + memory training cycle. + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +CpuReplacementCheck ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT UINT8 *ForceFullTraining + ) +{ + HECI_GS_SHDW_REGISTER MeFwsts2; + EFI_STATUS Status; + UINT32 Timeout; + PEI_STALL_PPI *StallPpi; + Status = EFI_SUCCESS; + Timeout = 0x0; + + /// + /// Read ME FWS2 + /// + MeFwsts2.ul = HeciPciRead32 (R_ME_GS_SHDW); + DEBUG ((EFI_D_INFO, "MeFwsts2 = %x.\n", MeFwsts2.r)); + + /// + /// Locate Stall Ppi + /// + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + + PERF_START_EX (FfsHeader, L"CPURLOP", NULL, AsmReadTsc (), 0x4010); + /// + /// Poll 50 ms on CPU Replaced Valid bit + /// + while ((((MeFwsts2.r.CpuReplacedValid == 0) && Timeout < CPURV_TIMEOUT_MULTIPLIER)) + ) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND); + MeFwsts2.ul = HeciPciRead32 (R_ME_GS_SHDW); + Timeout++; + } + PERF_END_EX (FfsHeader, L"CPURLOP", NULL, AsmReadTsc (), 0x4011); + + DEBUG ((EFI_D_INFO, "CpuReplacedValid = %x, ", MeFwsts2.r.CpuReplacedValid)); + DEBUG ((EFI_D_INFO, "CpuReplacedStatus = %x, ", MeFwsts2.r.CpuReplacedSts)); + DEBUG ((EFI_D_INFO, "WarmRstReqForDF = %x.\n", MeFwsts2.r.WarmRstReqForDF)); + + if (Timeout >= CPURV_TIMEOUT_MULTIPLIER || MeFwsts2.r.CpuReplacedValid == 0x0) { + DEBUG ((EFI_D_ERROR, "Timeout occurred, the CPU Replacement Valid Bit is not set.\n")); + *ForceFullTraining = 0x1; + } else { + if (MeFwsts2.r.CpuReplacedValid == 0x1) { + if (MeFwsts2.r.WarmRstReqForDF == 0x1) { + /// + /// Clear DISB and Issue a Non-Power Cycle Reset + /// + Status = ClearDisb (); + Status = PerformReset (PeiServices, CBM_DIR_NON_PCR); + } + + if ((MeFwsts2.r.CpuReplacedSts == 0x1 && MeFwsts2.r.WarmRstReqForDF == 0x0)) { + *ForceFullTraining = 0x1; + } + } + } + + return Status; +} + +/** + This procedure will configure the ME Host General Status register, + indicating that DRAM Initialization is complete and ME FW may + begin using the allocated ME UMA space. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Pointer to the FFS file header + @param[in] MrcBootMode MRC BootMode + @param[in] InitStat H_GS[27:24] Status + @param[in] FtpmStolenBase The base of FTPM + @retval EFI_SUCCESS +**/ +EFI_STATUS +MeConfigDidReg ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN MRC_BOOT_MODE_T MrcBootMode, + IN UINT8 InitStat, + IN UINT32 FtpmStolenBase, + IN UINT32 MeUmaSize + ) +{ + UINT32 MeUmaBase; + UINT32 MeUmaBaseExt; + UINT32 MeHgs; + UINT32 Timeout; + HECI_FWS_REGISTER MeHfs; + EFI_STATUS Status; + PEI_STALL_PPI *StallPpi; +#ifdef PTT_FLAG + PEI_ME_PLATFORM_POLICY_PPI *PeiMePolicyPpi; + EFI_GUID gPeiMePlatformPolicyPpiGuid = PEI_ME_PLATFORM_POLICY_PPI_GUID; + ME_DATA_HOB *MeDataHob; + EFI_GUID gMeDataHobGuid = ME_DATA_HOB_GUID; + UINT32 RegRead; + UINT32 WaitTime; +#endif //PTT_FLAG + +#ifdef PTT_FLAG + /// + /// Get platform policy settings through the MePlatformPolicy PPI + /// + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiMePlatformPolicyPpiGuid, + 0, + NULL, + (VOID **) &PeiMePolicyPpi + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + DumpMePlatformPolicyPei (PeiMePolicyPpi); +#endif //PTT_FLAG + + + Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, (VOID **) &StallPpi); + ASSERT_PEI_ERROR (PeiServices, Status); + + MeHgs = 0x0; + Timeout = 0x0; + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + + DEBUG ((EFI_D_INFO, "ME status: 0x%08x\n", MeHfs.ul)); + + if (MeHfs.r.MeOperationMode == ME_OPERATION_MODE_DEBUG) { + DEBUG ((EFI_D_INFO, "ME debug mode, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + + if (MeHfs.r.ErrorCode != 0) { + DEBUG ((EFI_D_INFO, "ME error, do not check for ME UMA. \n")); + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_INFO, "Entered ME DRAM Init Done procedure.\n")); + +#ifdef PTT_FLAG + if ((GetPchSeries() == PchLp) && + (MmioRead32 (R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_STS)& BIT0) && + (PeiMePolicyPpi->FTpmSwitch == 0) && + (InitStat != 0x1)) { + /// + /// Install ME HOBs + /// + InstallMeHob (PeiServices); + + MeDataHob = NULL; + MeDataHob = GetFirstGuidHob (&gMeDataHobGuid); + + if (MeDataHob != NULL) { + MeDataHob->FtpmBufferAddress = FtpmStolenBase; + DEBUG ((EFI_D_INFO, " Ftpm Allocated Buffer Address: %x\n", MeDataHob->FtpmBufferAddress )); + + /// + /// Poll Ready Bit + /// + RegRead = 0; + for (WaitTime = 0; WaitTime < PTT_HCI_TIMEOUT_B * 3; WaitTime += PTT_HCI_POLLING_PERIOD){ + RegRead = MmioRead32 (R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_STS); + DEBUG ((EFI_D_INFO, " Ftpm Waiting on Ready Bit, HCI_STS Register = %x\n", RegRead)); + if((BIT1 & RegRead) != 0){ + MmioWrite64 ((UINTN)(R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CRB),(UINTN) MeDataHob->FtpmBufferAddress ); + /// + /// Issue command to start. + /// + MmioWrite32 ((UINTN)R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CA_START, V_PTT_HCI_BUFFER_ADDRESS_RDY); + if( MeUmaSize == 32 ) + { + /// + /// Trigger interrupt command processing only for 5MB sku + /// + MmioWrite32 ((UINTN)R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CMD, 0); + } + break; + } + StallPpi->Stall (PeiServices, StallPpi, PTT_HCI_POLLING_PERIOD); + } + + /// + /// Poll state, wait for Ftpm to finish processing + /// + for (WaitTime = 0; WaitTime < PTT_HCI_TIMEOUT_B; WaitTime += PTT_HCI_POLLING_PERIOD){ + RegRead = MmioRead32 (R_PTT_HCI_BASE_ADDRESS + R_PTT_HCI_CA_START); + if (RegRead == 0){ + break; + } + StallPpi->Stall (PeiServices, StallPpi, PTT_HCI_POLLING_PERIOD); + } + } else { + DEBUG ((EFI_D_INFO, "ME DataHob error, MeDataHob not found\n")); + } + } +#endif + + /// + /// Read MESEGBASE value + /// + MeUmaBase = PciRead32 (PCI_LIB_ADDRESS (0, 0, 0, R_MESEG_BASE)); + MeUmaBaseExt = PciRead32 (PCI_LIB_ADDRESS (0, 0, 0, R_MESEG_BASE + 0x04)); + DEBUG ((EFI_D_INFO, " MeUmaBase read: %x\n", MeUmaBase)); + + /// + /// Write DRAM Init Done (DID) data to the ME H_GS[23:0]. + /// H_GS[23:16] = extended UMA base address (reserved) + /// H_GS[15:0] = 1M aligned UMA base address + /// ME FW will 0 extend these values to determine MeUmaBase + /// + MeUmaBase = ((MeUmaBaseExt << 28) + (MeUmaBase >> 4)) >> 16; + MeHgs = MeUmaBase; + + /// + /// Set H_GS[31:28] = 0x1 indicating DRAM Init Done + /// + MeHgs |= B_ME_DID_TYPE_MASK; + + /// + /// RapidStart + /// + if (InitStat & 0x80) { + MeHgs |= B_ME_DID_RAPID_START_BIT; + } + + InitStat &= 0x7F; + + /// + /// Set H_GS[27:24] = Status + /// 0x0 = Success + /// 0x1 = No Memory in channels + /// 0x2 = Memory Init Error + /// 0x3 = Memory not preserved across reset + /// 0x4-0xF = Reserved + /// + MeHgs |= (InitStat << 24); + + PERF_START_EX (FfsHeader, L"DID", NULL, AsmReadTsc (), 0x4020); + HeciPciAndThenOr32 (R_ME_H_GS, 0, MeHgs); + DEBUG ((EFI_D_INFO, " ME H_GS written: %x\n", MeHgs)); + + /// + /// ME FW typically responds with the DID ACK w/in 1ms + /// Adding short delay to avoid wasting time in the timeout loop + /// + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND + STALL_100_MICROSECONDS); + + /// + /// Read the ME H_FS Register to look for DID ACK. + /// + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + DEBUG ((EFI_D_INFO, " HFS read before DID ACK: %x\n", MeHfs.r)); + + /// + /// ~5 second Timeout for DID ACK + /// + while (((MeHfs.r.BiosMessageAck == 0) && Timeout < DID_TIMEOUT_MULTIPLIER) + ) { + StallPpi->Stall (PeiServices, StallPpi, STALL_1_MILLISECOND); + MeHfs.ul = HeciPciRead32 (R_ME_HFS); + Timeout++; + } + + if ((Timeout >= DID_TIMEOUT_MULTIPLIER) + ) { + DEBUG ((EFI_D_ERROR, "Timeout occurred waiting for DID ACK.\n")); + } else { + DEBUG ((EFI_D_INFO, "ME DRAM Init Done ACK received.\n")); + DEBUG ((EFI_D_INFO, "HFS read after DID ACK: %x\n", MeHfs.r)); + } + PERF_END_EX (FfsHeader, L"DID", NULL, AsmReadTsc (), 0x4021); + + DEBUG ((EFI_D_ERROR, "BiosAction = %x\n", MeHfs.r.AckData)); + + return HandleMeBiosAction (PeiServices, MrcBootMode, (UINT8) MeHfs.r.AckData); +} + +/** + This procedure will enforce the BIOS Action that was requested by ME FW + as part of the DRAM Init Done message. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] MrcBootMode MRC BootMode + @param[in] BiosAction Me requests BIOS to act + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +HandleMeBiosAction ( + IN EFI_PEI_SERVICES **PeiServices, + IN MRC_BOOT_MODE_T MrcBootMode, + IN UINT8 BiosAction + ) +{ + EFI_STATUS Status; + HECI_GS_SHDW_REGISTER MeFwsts2; + /// + /// Read ME FWS2 + /// + MeFwsts2.ul = HeciPciRead32 (R_ME_GS_SHDW); + DEBUG ((EFI_D_INFO, "MeFwsts2 = %x.\n", MeFwsts2.r)); + + switch (BiosAction) { + case 0: + /// + /// Case: DID ACK was not received + /// + DEBUG ((EFI_D_ERROR, "DID Ack was not received, no BIOS Action to process.\n")); + break; + + case CBM_DIR_NON_PCR: + /// + /// Case: Perform Non-Power Cycle Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW has requested a Non-PCR.\n")); + Status = PerformReset (PeiServices, CBM_DIR_NON_PCR); + break; + + case CBM_DIR_PCR: + /// + /// Case: Perform Power Cycle Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW has requested a PCR.\n")); + Status = PerformReset (PeiServices, CBM_DIR_PCR); + break; + + case 3: + /// + /// Case: Go To S3 + /// + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested entry to S3. Not defined, continuing to POST.\n")); + break; + + case 4: + /// + /// Case: Go To S4 + /// + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested entry to S4. Not defined, continuing to POST.\n")); + break; + + case 5: + /// + /// Case: Go To S5 + /// + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested entry to S5. Not defined, continuing to POST.\n")); + break; + + case CBM_DIR_GLOBAL_RESET: + /// + /// Case: Perform Global Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW has requested a Global Reset.\n")); + Status = PerformReset (PeiServices, CBM_DIR_GLOBAL_RESET); + break; + + case CBM_DIR_CONTINUE_POST: + /// + /// Case: Continue to POST + /// + DEBUG ((EFI_D_INFO, "ME FW DID Ack requested to continue to POST.\n")); + break; + } + + return EFI_SUCCESS; +} + +/** + This procedure will issue a Non-Power Cycle, Power Cycle, or Global Rest. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] ResetType Type of reset to be issued. + + @retval EFI_SUCCESS The function completed successfully. + @retval All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +PerformReset ( + IN EFI_PEI_SERVICES **PeiServices, + UINT8 ResetType + ) +{ + EFI_STATUS Status; + UINT32 ETR3; + UINT32 GpioBase; + UINT8 Reset; + WDT_PPI *Wdt; + PCH_SERIES PchSeries; + + ETR3 = 0; + Reset = 0; + GpioBase = 0; + Wdt = NULL; + PchSeries = GetPchSeries(); + + /// + /// Locate WDT PPI for access to Wdt->AllowKnownReset() + /// + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gWdtPpiGuid, + 0, + NULL, + (VOID **) &Wdt + ); + ASSERT_PEI_ERROR (PeiServices, Status); + + /// + /// Clear CF9GR of PCH (B0/D31/f0 offset 0x0AC[20] = 1b) to indicate Host reset + /// Make sure CWORWRE (CF9 Without Resume Well Reset Enable) is cleared + /// + ETR3 = PciRead32 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_PMIR)); + ETR3 = ETR3 &~BIT20; + ETR3 = ETR3 &~BIT18; + PciWrite32 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_PMIR), ETR3); + + Reset = IoRead8 (R_PCH_RST_CNT); + Reset &= 0xF1; + + /// + /// If global reset required + /// + if (ResetType == CBM_DIR_GLOBAL_RESET) { + /// + /// Get GPIO Base Address + /// + GpioBase = PciRead32 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GPIO_BASE)) &~BIT0; + } + + switch (ResetType) { + case CBM_DIR_NON_PCR: + /// + /// Case: Non Power Cycle Reset requested + /// + DEBUG ((EFI_D_ERROR, "ME FW DID ACK has requested a Non Power Cycle Reset.\n")); + Reset |= 0x06; + break; + + case CBM_DIR_PCR: + /// + /// Case: Power Cycle Reset requested + /// + Wdt->ReloadAndStart (2); + DEBUG ((EFI_D_INFO, "ME FW DID ACK has requested a Power Cycle Reset.\n")); + Reset |= 0x0E; + break; + + case CBM_DIR_GLOBAL_RESET: + /// + /// Case: Global Reset + /// + DEBUG ((EFI_D_ERROR, "ME FW DID Ack requested a global reset.\n")); + + /// + /// Drive GPIO[30] (SPDNA#) low prior to 0xCF9 write + /// + if (PchSeries == PchH) { + /// 1. Set GPIOBASE + offset 00h[30] = 1b (for non-Deep Sx enabled platforms) + /// 2. Set GPIOBASE + offset 04h[30] = 0b (for non-Deep Sx enabled platforms) + /// 3. Set GPIOBASE + offset 0Ch[30] = 0b (for non-Deep Sx enabled platforms) + /// 4. Set GPIOBASE + offset 60h[30] = 1b (for non-Deep Sx enabled platforms) + /// NOTE: For Deep Sx enabled platforms steps 1,2 and 3 should be skipped and pin should be left in native mode + /// 5. Set CF9GR bit, D31:F0:ACh[20], issue a Global Reset through a 0xCF9 write of either 06h or 0Eh commands. + /// Global Reset MEI Message + /// 1. BIOS makes sure GPIO30 is left in native mode (default mode) before sending a Global Reset MEI message. + /// + IoOr32 ((UINTN) (GpioBase + R_PCH_GPIO_USE_SEL), (UINT32) (BIT30)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GPIO_IO_SEL), (UINT32) (~BIT30)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GPIO_LVL), (UINT32) (~BIT30)); + } + + if (PchSeries == PchLp) { + /// 1. Set GPIOBASE + offset 1F0h[0] = 1b (for non-Deep Sx enabled platforms) + /// 2. Set GPIOBASE + offset 1F0h[2] = 0b (for non-Deep Sx enabled platforms) + /// 3. Set GPIOBASE + offset 1F0h[31] = 0b (for non-Deep Sx enabled platforms) + /// 4. Set GPIOBASE + offset 60h[30] = 1h (for non-Deep Sx enabled platforms) + /// NOTE: For Deep Sx enabled platforms steps 1,2 and 3 should be skipped and pin should be left in native mode + /// 5. Set CF9GR bit, D31:F0:ACh[20], issue a Global Reset through a 0xCF9 write of either 06h or 0Eh commands. + /// Global Reset MEI Message + /// 1. BIOS makes sure GPIO30 is left in native mode (default mode) before sending a Global Reset MEI message. + /// + IoOr32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (B_PCH_GPIO_OWN0_GPIO_USE_SEL)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (~B_PCH_GPIO_OWN0_GPIO_IO_SEL)); + IoAnd32 ((UINTN) (GpioBase + R_PCH_GP_30_CONFIG0), (UINT32) (~B_PCH_GPIO_OWN0_GPO_LVL)); + } + + IoOr32 ((UINTN) (GpioBase + R_PCH_GP_RST_SEL), (UINT32) (BIT30)); + + PciOr32 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_PMIR), + (UINT32) (B_PCH_LPC_PMIR_CF9GR) + ); + + /// + /// Issue global reset CF9 = 0x0E + /// + DEBUG ((EFI_D_ERROR, "Issuing global reset.\n")); + Reset |= 0x0E; + break; + } + /// + /// Write PCH RST CNT, Issue Reset + /// + Wdt->AllowKnownReset (); + + IoWrite8 (R_PCH_RST_CNT, Reset); + + return EFI_SUCCESS; +} + +/** + This procedure will clear the DISB. + + @param[in] None + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +ClearDisb ( + VOID + ) +{ + UINT16 Data16; + + Data16 = PciRead16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2)); + Data16 = Data16 &~B_PCH_LPC_GEN_PMCON_DRAM_INIT; + PciWrite16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2), Data16); + + return EFI_SUCCESS; +} + +/** + This procedure will clear the DISB. + + @param[in] None + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +SetDISB ( + VOID + ) +{ + UINT16 Data16; + + Data16 = PciRead16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2)); + Data16 = Data16 & B_PCH_LPC_GEN_PMCON_DRAM_INIT; + PciWrite16 (PCI_LIB_ADDRESS (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_GEN_PMCON_2), Data16); + + return EFI_SUCCESS; +} + +/** + This function is the entry point for this PEI. + + @param[in] FfsHeader Pointer to the FFS file header + @param[in] PeiServices Pointer to the PEI services table + + @retval Return Status based on errors that occurred while waiting for time to expire. +**/ +EFI_STATUS +EFIAPI +PchMeUmaEntry ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + Status = EFI_SUCCESS; + Status = (*PeiServices)->InstallPpi (PeiServices, mPchMeUmaPpiList); + + return Status; +} diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.cif b/ReferenceCode/ME/PchMeUma/PchMeUma.cif new file mode 100644 index 0000000..4a3d2b0 --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.cif @@ -0,0 +1,13 @@ +<component> + name = "PchMeUma" + category = ModulePart + LocalRoot = "ReferenceCode\ME\PchMeUma\" + RefName = "PchMeUma" +[files] +"PchMeUma.sdl" +"PchMeUma.mak" +"PchMeUma.c" +"PchMeUma.h" +"PchMeUma.dxs" +"PchMeUma.inf" +<endComponent>
\ No newline at end of file diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.dxs b/ReferenceCode/ME/PchMeUma/PchMeUma.dxs new file mode 100644 index 0000000..0d942cb --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.dxs @@ -0,0 +1,50 @@ +/** @file + Dependency expression file for PchMeUma Init PEIM. + +@copyright + Copyright (c) 2010 - 2013 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains 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 + +#include EFI_PPI_DEPENDENCY (Wdt) +#include EFI_PPI_DEPENDENCY (Stall) +#include EFI_PPI_DEFINITION (MePlatformPolicyPei) + +DEPENDENCY_START + WDT_PPI_GUID AND + PEI_STALL_PPI_GUID AND + PEI_ME_PLATFORM_POLICY_PPI_GUID +DEPENDENCY_END + + + + diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.h b/ReferenceCode/ME/PchMeUma/PchMeUma.h new file mode 100644 index 0000000..6530b23 --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.h @@ -0,0 +1,178 @@ +/** @file + Header file for Framework PEIM to PchMeUma + +@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 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 _PCH_ME_UMA_H_ +#define _PCH_ME_UMA_H_ + +#include EFI_PPI_DEFINITION (PchMeUma) +#include EFI_GUID_DEFINITION (MeDataHob) + +/// +/// LPT PCI Register Definition(s) +/// +#define R_MESEG_BASE 0x70 + +// +// ME FW communication timeout value definitions +// +#define DID_TIMEOUT_MULTIPLIER 0x1388 +#define MUSZV_TIMEOUT_MULTIPLIER 0x1388 +#define CPURV_TIMEOUT_MULTIPLIER 0x32 +#define STALL_1_MILLISECOND 1000 +#define STALL_100_MICROSECONDS 100 + +// +// Function Prototype(s) +// + +/** + This procedure will read and return the amount of ME UMA requested + by ME ROM from the HECI device. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Pointer to the FFS file header + + @retval UINT32 Return ME UMA Size + @retval EFI_SUCCESS Do not check for ME UMA +**/ +UINT32 +MeSendUmaSize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +/** + Init and Install ME Hob + + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS +**/ +EFI_STATUS +InstallMeHob ( + IN EFI_PEI_SERVICES **PeiServices + ) +; + +/** + This procedure will determine whether or not the CPU was replaced + during system power loss or via dynamic fusing. + Calling this procedure could result in a warm reset (if ME FW is requesting one). + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Not used. + @param[out] ForceFullTraining When set = 0x1, MRC will be forced to perform a full + memory training cycle. + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFI_STATUS +CpuReplacementCheck ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT UINT8 *ForceFullTraining + ) +; + +/** + This procedure will configure the ME Host General Status register, + indicating that DRAM Initialization is complete and ME FW may + begin using the allocated ME UMA space. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] FfsHeader Pointer to the FFS file header + @param[in] MrcBootMode MRC BootMode + @param[in] InitStat H_GS[27:24] Status + @param[in] FtpmStolenBase The base of FTPM + + @retval EFI_SUCCESS +**/ +EFI_STATUS +MeConfigDidReg ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN MRC_BOOT_MODE_T MrcBootMode, + IN UINT8 InitStat, + IN UINT32 FtpmStolenBase, + IN UINT32 MeUmaSize + ) +; + +/** + This procedure will enforce the BIOS Action that was requested by ME FW + as part of the DRAM Init Done message. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] MrcBootMode MRC BootMode + @param[in] BiosAction Me requests BIOS to act + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +HandleMeBiosAction ( + IN EFI_PEI_SERVICES **PeiServices, + IN MRC_BOOT_MODE_T MrcBootMode, + IN UINT8 BiosAction + ) +; + +/** + This procedure will issue a Non-Power Cycle, Power Cycle, or Global Rest. + + @param[in] PeiServices General purpose services available to every PEIM. + @param[in] ResetType Type of reset to be issued. + + @retval EFI_SUCCESS The function completed successfully. + @retval All other error conditions encountered result in an ASSERT. +**/ +EFI_STATUS +PerformReset ( + IN EFI_PEI_SERVICES **PeiServices, + UINT8 ResetType + ) +; + +/** + This procedure will clear the DISB. + + @param[in] None + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +ClearDisb ( + VOID + ) +; + +/** + This procedure will clear the DISB. + + @param[in] None + + @retval EFI_SUCCESS Always return EFI_SUCCESS +**/ +EFI_STATUS +SetDISB ( + VOID + ) +; +#endif diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.inf b/ReferenceCode/ME/PchMeUma/PchMeUma.inf new file mode 100644 index 0000000..5aae62d --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.inf @@ -0,0 +1,88 @@ +## @file +# Component description file for PchMeUma module +# +#@copyright +# Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved +# This software and associated documentation (if any) is furnished +# under a license and may only be used or copied in accordance +# with the terms of the license. Except as permitted by such +# license, no part of this software or documentation may be +# reproduced, stored in a retrieval system, or transmitted in any +# form or by any means without the express written consent of +# Intel Corporation. +# +# This file contains 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 = PchMeUma +FILE_GUID = b6a2aff3-767c-5658-c37a-d1c82ef76543 +COMPONENT_TYPE = PE32_PEIM + +[sources.common] + PchMeUma.c + PchMeUma.h + +# +# Edk II Glue Driver Entry Point +# + EdkIIGluePeimEntryPoint.c + +[includes.common] + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Heci/Include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/Include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/Include + $(EFI_SOURCE)/$(PROJECT_ME_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Guid/MeDataHob + $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/Ptt/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/Pei/Include + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + + +[libraries.common] + EdkFrameworkPpiLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGluePeiDebugLibReportStatusCode + EdkIIGluePeiReportStatusCodeLib + EdkIIGluePeiServicesLib + EdkIIGlueBasePciLibPciExpress + EdkIIGlueBasePciExpressLib + PeiLib + $(PROJECT_PCH_FAMILY)PpiLib + MeLibPpi + EdkIIGluePeiFirmwarePerformanceLib + PchPlatformLib + MeGuidLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchMeUma.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PchMeUmaEntry + 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/PchMeUma/PchMeUma.mak b/ReferenceCode/ME/PchMeUma/PchMeUma.mak new file mode 100644 index 0000000..426692e --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.mak @@ -0,0 +1,62 @@ +# MAK file for the ModulePart:PchMeUma + +all: PchMeUma + +$(BUILD_DIR)\PchMeUma.mak : $(PchMeUma_DIR)\PchMeUma.cif $(BUILD_RULES) + $(CIF2MAK) $(PchMeUma_DIR)\PchMeUma.cif $(CIF2MAK_DEFAULTS) + +PchMeUma: $(BUILD_DIR)\PchMeUma.mak PchMeUmaBin + +PchMeUma_Pei_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + $(ME_INCLUDES)\ + /I$(MePttLibrary_DIR)\Pei + + +PchMeUma_DEFINES=$(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PchMeUmaEntry"\ + /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__ \ +!IF "$(IntelPTT_SUPPORT)"=="1" + /D PTT_FLAG +!ENDIF + +PchMeUma_LIBS =\ + $(EDKPROTOCOLLIB)\ + $(EDKFRAMEWORKPPILIB)\ + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueBaseLibIA32_LIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\ + $(EdkIIGluePeiReportStatusCodeLib_LIB)\ + $(EdkIIGluePeiServicesLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(IntelPchPpiLib_LIB)\ + $(EFIDRIVERLIB)\ + $(PEILIB)\ + $(MeLibPpi_LIB)\ + $(PchPlatformPeiLib_LIB)\ + $(MeGuidLib_LIB)\ + $(EdkIIGluePeiHobLib_LIB)\ + $(EFIGUIDLIB)\ + $(EFIPROTOCOLLIB) +## $(EdkIIGluePeiFirmwarePerformanceLib_LIB) + +PchMeUmaBin : $(PchMeUma_LIBS) $(HeciPei_LIBS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchMeUma.mak all\ + NAME=PchMeUma\ + MAKEFILE=$(BUILD_DIR)\PchMeUma.mak \ + GUID=8C376010-2400-4d7d-B47B-9D851DF3C9D1\ + "MY_INCLUDES=$(PchMeUma_Pei_INCLUDES)" \ + "MY_DEFINES=$(PchMeUma_DEFINES)"\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=PEIM \ + EDKIIModule=PEIM\ + DEPEX1=$(PchMeUma_DIR)\PchMeUma.dxs DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \ + COMPRESS=0 diff --git a/ReferenceCode/ME/PchMeUma/PchMeUma.sdl b/ReferenceCode/ME/PchMeUma/PchMeUma.sdl new file mode 100644 index 0000000..fc09086 --- /dev/null +++ b/ReferenceCode/ME/PchMeUma/PchMeUma.sdl @@ -0,0 +1,41 @@ +TOKEN + Name = PchMeUma_SUPPORT + Value = 1 + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes + Help = "Main switch to enable PchMeUma support in Project" +End +MODULE + Help = "Includes PchMeUma.mak to Project" + File = "PchMeUma.mak" +End + +PATH + Name = "PchMeUma_DIR" + Help = "PCH ME UMA file source directory" +End + +ELINK + Name = "PchMeUma_INCLUDES" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "/I$(PchMeUma_DIR)" + Parent = "PchMeUma_INCLUDES" + InvokeOrder = AfterParent +End + +ELINK + Name = "$(BUILD_DIR)\PchMeUma.ffs" + Parent = "FV_BB" + InvokeOrder = AfterParent +End + +ELINK + Name = "/I$(ME_DIR)" + Parent = "PchMeUma_INCLUDES" + InvokeOrder = AfterParent +End |