diff options
Diffstat (limited to 'ReferenceCode/Chipset/LynxPoint/Spi')
26 files changed, 3845 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif new file mode 100644 index 0000000..5b922d8 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.cif @@ -0,0 +1,11 @@ +<component> + name = "PchSpiCommonLib" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\Common" + RefName = "PchSpiCommonLib" +[files] +"PchSpiCommonLib.sdl" +"PchSpiCommonLib.mak" +"SpiCommon.c" +"SpiCommon.h" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak new file mode 100644 index 0000000..b781d72 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.mak @@ -0,0 +1,125 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.mak 1 2/08/12 9:22a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:22a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.mak $ +# +# 1 2/08/12 9:22a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +all : PchSpiCommonLib + +PchSpiCommonLib : PchSpiCommonDxeLib PchSpiCommonSmmLib PchSpiCommonPeiLib + +$(PchSpiCommonSmmLib_LIB) : PchSpiCommonSmmLib +$(PchSpiCommonDxeLib_LIB) : PchSpiCommonDxeLib +$(PchSpiCommonPeiLib_LIB) : PchSpiCommonPeiLib + +PchSpiCommonSmmLib : $(BUILD_DIR)\PchSpiCommonLib.mak PchSpiCommonLibSmmBin + +PchSpiCommonDxeLib : $(BUILD_DIR)\PchSpiCommonLib.mak PchSpiCommonLibDxeBin + +PchSpiCommonPeiLib : $(BUILD_DIR)\PchSpiCommonLib.mak PchSpiCommonLibPeiBin + +$(BUILD_DIR)\PchSpiCommonLib.mak : $(PchSpiCommonLib_DIR)\$(@B).cif $(PchSpiCommonLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchSpiCommonLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchSpiCommonLib_INCLUDES=\ + $(EDK_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + +PchSpiCommonLibSmm_INCLUDES=\ + $(PchSpiCommonLib_INCLUDES) $(PCH_SPI_INCLUDES) + +PchSpiCommonLibDxe_INCLUDES=\ + $(PchSpiCommonLib_INCLUDES) $(PCH_SPI_INCLUDES) + +PchSpiCommonLibPeim_INCLUDES=\ + $(PchSpiCommonLib_INCLUDES) $(PCH_SPI_INCLUDES) + +PchSpiCommonLib_DEFINES = \ + $(CFLAGS) + +DxeCpuBuildDefine = \ +!IF "$(x64_BUILD)"=="1" + /DMDE_CPU_X64\ +!ELSE + /DMDE_CPU_IA32\ +!ENDIF + +PeimCpuBuildDefine = \ + /DMDE_CPU_IA32\ + +PchSpiCommonLibPeim_DEFINES = \ + $(PchSpiCommonLib_DEFINES)\ + $(PeimCpuBuildDefine)\ + +PchSpiCommonLibDxe_DEFINES = \ + $(PchSpiCommonLib_DEFINES)\ + $(DxeCpuBuildDefine)\ + +PchSpiCommonLibSmm_DEFINES = \ + $(PchSpiCommonLibDxe_DEFINES)\ + +PchSpiCommonLibDxeBin : + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \ + /f $(BUILD_DIR)\PchSpiCommonLib.mak all\ + "MY_INCLUDES=$(PchSpiCommonLibDxe_INCLUDES)" \ + "CFLAGS=$(PchSpiCommonLibDxe_DEFINES)"\ + TYPE=LIBRARY \ + LIBRARY_NAME=$(PchSpiCommonDxeLib_LIB) + +PchSpiCommonLibSmmBin : + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \ + /f $(BUILD_DIR)\PchSpiCommonLib.mak all\ + "MY_INCLUDES=$(PchSpiCommonLibSmm_INCLUDES)" \ + "CFLAGS=$(PchSpiCommonLibSmm_DEFINES)"\ + TYPE=LIBRARY \ + BUILD_DIR=$(BUILD_DIR)\Smm\ + LIBRARY_NAME=$(PchSpiCommonSmmLib_LIB) + +PchSpiCommonLibPeiBin : +!IF "$(x64_BUILD)"=="1" + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32 \ +!ELSE + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) \ +!ENDIF + /f $(BUILD_DIR)\PchSpiCommonLib.mak all\ + "MY_INCLUDES=$(PchSpiCommonLibPeim_INCLUDES)" \ + "CFLAGS=$(PchSpiCommonLibPeim_DEFINES)"\ + TYPE=PEI_LIBRARY \ + LIBRARY_NAME=$(PchSpiCommonPeiLib_LIB) +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl new file mode 100644 index 0000000..33582be --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/PchSpiCommonLib.sdl @@ -0,0 +1,92 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.sdl 1 2/08/12 9:22a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:22a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiCommonLib/PchSpiCommonLib.sdl $ +# +# 1 2/08/12 9:22a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchSpiCommonLib_SUPPORT" + Value = "1" + Help = "Main switch to enable PchSpiCommonLib support in Project" + TokenType = Boolean + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchSpiCommonLib_DIR" +End + +MODULE + Help = "Includes PchSpiCommonLib.mak to Project" + File = "PchSpiCommonLib.mak" +End + +ELINK + Name = "PchSpiCommonDxeLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchSpiCommonDxeLib.lib" + Parent = "PchSpiCommonDxeLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PchSpiCommonPeiLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchSpiCommonPeiLib.lib" + Parent = "PchSpiCommonPeiLib_LIB" + InvokeOrder = AfterParent +End + +ELINK + Name = "PchSpiCommonSmmLib_LIB" + InvokeOrder = ReplaceParent +End + +ELINK + Name = "$(BUILD_DIR)\PchSpiCommonSmmLib.lib" + Parent = "PchSpiCommonSmmLib_LIB" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c new file mode 100644 index 0000000..2797bd9 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.c @@ -0,0 +1,1425 @@ +/** @file + PCH SPI Common Driver implements the SPI Host Controller Compatibility Interface. + +@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 "PchSpi.h" + +/** + Initialize an SPI protocol instance. + The function will assert in debug if PCH RCBA has not been initialized + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval EFI_SUCCESS The protocol instance was properly initialized + @exception EFI_UNSUPPORTED The PCH is not supported by this module +**/ +EFI_STATUS +SpiProtocolConstructor ( + SPI_INSTANCE *SpiInstance + ) +{ + /// + /// Check if the current PCH is known and supported by this code + /// + if (!IsPchSupported ()) { + DEBUG ((EFI_D_ERROR, "PCH SPI Protocol not supported due to no proper PCH LPC found!\n")); + return EFI_UNSUPPORTED; + } + /// + /// Initialize the SPI protocol instance + /// + SpiInstance->Signature = PCH_SPI_PRIVATE_DATA_SIGNATURE; + SpiInstance->Handle = NULL; + SpiInstance->SpiProtocol.ReadId = SpiProtocolReadId; + SpiInstance->SpiProtocol.Init = SpiProtocolInit; + SpiInstance->SpiProtocol.Execute = SpiProtocolExecute; + + /// + /// Sanity check to ensure PCH RCBA initialization has occurred previously. + /// + SpiInstance->PchRootComplexBar = PCH_RCRB_BASE; + ASSERT (SpiInstance->PchRootComplexBar != 0); + + return EFI_SUCCESS; +} + +/** + JEDEC Read IDs from SPI flash part, this function will return 1-byte Vendor ID and 2-byte Device ID + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] Address This value is for determines the command is sent to SPI Component 1 or 2 + @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle. + + @retval EFI_SUCCESS Read Jedec Id completed. + @retval EFI_DEVICE_ERROR Device error, operation failed. + @exception EFI_UNSUPPORTED This function is unsupport after SpiProtocolInit is called +**/ +EFI_STATUS +EFIAPI +SpiProtocolReadId ( + IN EFI_SPI_PROTOCOL *This, + IN UINTN Address, + IN OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + SPI_INSTANCE *SpiInstance; + UINTN PchRootComplexBar; + UINT16 OpcodeType; + UINT8 Code; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + if (SpiInstance->SpiIdTable[0].VendorId != 0) { + DEBUG ((EFI_D_ERROR, "This function is unsupport after SpiProtocolInit is called, please use SpiProtocolExecute to get Jedec ID!\n")); + return EFI_UNSUPPORTED; + } + + PchRootComplexBar = SpiInstance->PchRootComplexBar; + SpiInstance->SpiInitTable.SpiCmdConfig[0].Operation = EnumSpiOperationJedecId; + SpiInstance->SpiInitTable.SpiCmdConfig[0].Frequency = EnumSpiCycle50MHz; + OpcodeType = (UINT16) (V_PCH_SPI_OPTYPE_RDNOADDR); + Code = PCH_SPI_COMMAND_READ_ID; + + /// + /// Set Opcode Menu Configuration registers. + /// Need to be done before sending any SPI command + /// + MmioWrite8 (PchRootComplexBar + R_PCH_SPI_OPMENU, Code); + MmioRead8 (PchRootComplexBar + R_PCH_SPI_OPMENU); + /// + /// Set Opcode Type Configuration registers. + /// + MmioWrite16 (PchRootComplexBar + R_PCH_SPI_OPTYPE, OpcodeType); + MmioRead16 (PchRootComplexBar + R_PCH_SPI_OPTYPE); + + Status = SpiProtocolExecute ( + This, + 0, + 0, + TRUE, + TRUE, + FALSE, + Address, + 3, + Buffer, + EnumSpiRegionAll + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +/** + Get Descriptor values from the Descriptor Region. + + @param[in] This A pointer to "EFI_SPI_PROTOCOL" for issuing commands + + @retval None +**/ +VOID +EFIAPI +GetDescriptorValues ( + IN EFI_SPI_PROTOCOL *This + ) +{ + SPI_INSTANCE *SpiInstance; + UINTN PchRootComplexBar; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + PchRootComplexBar = SpiInstance->PchRootComplexBar; + + /// + /// Select to Flash Map 0 Register to get the number of flash Component + /// + MmioAndThenOr32 ( + PchRootComplexBar + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)), + (UINT32) (V_PCH_SPI_FDOC_FDSS_FSDM | R_PCH_SPI_FDBAR_FLASH_MAP0) + ); + + /// + /// Copy Zero based Number Of Components + /// + SpiInstance->SpiDescriptor.NumberComponents = (UINT8) ((MmioRead16 (PchRootComplexBar + R_PCH_SPI_FDOD) & B_PCH_SPI_FDBAR_NC) >> N_PCH_SPI_FDBAR_NC); + + /// + /// Select to Flash Components Register to get the Component 1 Density + /// + MmioAndThenOr32 ( + PchRootComplexBar + R_PCH_SPI_FDOC, + (UINT32) (~(B_PCH_SPI_FDOC_FDSS_MASK | B_PCH_SPI_FDOC_FDSI_MASK)), + (UINT32) (V_PCH_SPI_FDOC_FDSS_COMP | R_PCH_SPI_FCBA_FLCOMP) + ); + + /// + /// Copy Component 1 Density + /// + SpiInstance->SpiDescriptor.Comp1Density = (UINT8) MmioRead32 (PchRootComplexBar + R_PCH_SPI_FDOD) & B_PCH_SPI_FLCOMP_COMP1_MASK; +} + +/** + Get VSCC values from the Descriptor Region (VSCC Table). + + @param[in] This A pointer to "EFI_SPI_PROTOCOL" for issuing commands + @param[in] ReadDataCmdOpcodeIndex The index of the opcode - "PCH_SPI_COMMAND_READ_DATA" + @param[in, out] Vscc0Value VSCC0 (Vendor Specific Component Capabilities) Value + @param[in, out] Vscc1Value VSCC1 (Vendor Specific Component Capabilities) Value + + @retval EFI_SUCCESS Found the VSCC values on Descriptor Region + @retval EFI_NOT_FOUND Couldn't find the VSCC values on Descriptor Region + @exception EFI_UNSUPPORTED ReadDataCmdOpcodeIndex is out of range +**/ +EFI_STATUS +EFIAPI +GetDescriptorVsccValues ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 ReadDataCmdOpcodeIndex, + IN OUT UINT32 *Vscc0Value, + IN OUT UINT32 *Vscc1Value + ) +{ + UINT32 SpiDescFlashUpperMap1; + UINT32 VsccTableBaseAddr; + UINT32 VsccTableLength; + UINT32 JedecIdRegIndex; + EFI_STATUS Status; + UINT32 FlashDescriptor; + SPI_INSTANCE *SpiInstance; + BOOLEAN MatchedVtbEntryFound; + UINT8 SpiIndex; + UINT32 Data32; + Data32 = 0; + + if (ReadDataCmdOpcodeIndex >= SPI_NUM_OPCODE) { + return EFI_UNSUPPORTED; + } + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + + Status = SpiProtocolExecute ( + This, + ReadDataCmdOpcodeIndex, + 0, + TRUE, + TRUE, + FALSE, + (UINTN) R_PCH_SPI_FLASH_UMAP1, + sizeof (SpiDescFlashUpperMap1), + (UINT8 *) &SpiDescFlashUpperMap1, + EnumSpiRegionDescriptor + ); + if ((EFI_ERROR (Status)) || (SpiDescFlashUpperMap1 == 0xFFFFFFFF)) { + return EFI_NOT_FOUND; + } + /// + /// B_PCH_SPI_FLASH_UMAP1_VTBA represents address bits [11:4] + /// + VsccTableBaseAddr = ((SpiDescFlashUpperMap1 & B_PCH_SPI_FLASH_UMAP1_VTBA) << 4); + /// + /// Multiplied by 4? B_PCH_SPI_FDBAR_VTL is the 1-based number of DWORDs. + /// + VsccTableLength = (((SpiDescFlashUpperMap1 & B_PCH_SPI_FLASH_UMAP1_VTL) >> 8) << 2); + if (VsccTableLength < SIZE_OF_SPI_VTBA_ENTRY) { + /// + /// Non-existent or invalid Vscc Table + /// + return EFI_NOT_FOUND; + } + + for (SpiIndex = 0; SpiIndex <= SpiInstance->SpiDescriptor.NumberComponents; SpiIndex++) { + JedecIdRegIndex = 0; + MatchedVtbEntryFound = FALSE; + while (JedecIdRegIndex <= (VsccTableLength - SIZE_OF_SPI_VTBA_ENTRY)) { + Status = SpiProtocolExecute ( + This, + ReadDataCmdOpcodeIndex, + 0, + TRUE, + TRUE, + FALSE, + (UINTN) (VsccTableBaseAddr + JedecIdRegIndex), + sizeof (UINT32), + (UINT8 *) &FlashDescriptor, + EnumSpiRegionDescriptor + ); + + if ((EFI_ERROR (Status)) || (FlashDescriptor == 0xFFFFFFFF)) { + break; + } + + if (((FlashDescriptor & B_PCH_SPI_VTBA_JID0_VID) != SpiInstance->SpiIdTable[SpiIndex].VendorId) || + (((FlashDescriptor & B_PCH_SPI_VTBA_JID0_DID0) >> N_PCH_SPI_VTBA_JID0_DID0) + != SpiInstance->SpiIdTable[SpiIndex].DeviceId0) || + (((FlashDescriptor & B_PCH_SPI_VTBA_JID0_DID1) >> N_PCH_SPI_VTBA_JID0_DID1) + != SpiInstance->SpiIdTable[SpiIndex].DeviceId1)) { + JedecIdRegIndex += SIZE_OF_SPI_VTBA_ENTRY; + } else { + MatchedVtbEntryFound = TRUE; + break; + } + } + + if (!MatchedVtbEntryFound) { + return EFI_NOT_FOUND; + } + + Status = SpiProtocolExecute ( + This, + ReadDataCmdOpcodeIndex, + 0, + TRUE, + TRUE, + FALSE, + (UINTN) (VsccTableBaseAddr + JedecIdRegIndex + R_PCH_SPI_VTBA_VSCC0), + sizeof (UINT32), + (UINT8 *) &Data32, + EnumSpiRegionDescriptor + ); + if ((EFI_ERROR (Status)) || (Data32 == 0xFFFFFFFF)) { + return EFI_NOT_FOUND; + } + /// + /// Copy correct VSCCn value + /// + if (SpiIndex == 0) { + *Vscc0Value = Data32; + } else { + *Vscc1Value = Data32; + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} + +/** + Discover if the flash parts supports 4KB Block/Sector erase size. + + @param[in] This A pointer to "EFI_SPI_PROTOCOL" for issuing commands + + @retval EFI_SUCCESS The flash part supports 4KB erase size. + @exception EFI_UNSUPPORTED The flash part does not support 4KB erase size. +**/ +EFI_STATUS +EFIAPI +SpiDiscoveryParameters ( + IN EFI_SPI_PROTOCOL *This + ) +{ + UINT16 ParameterTableIndex; + UINT32 Data32; + SPI_INSTANCE *SpiInstance; + UINT8 SpiIndex; + UINTN PchRootComplexBar; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + PchRootComplexBar = SpiInstance->PchRootComplexBar; + + /// + /// Check if valid SFDP table is present for SPI0 + /// + Data32 = MmioRead32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC0)) & B_PCH_SPI_VSCC0_CPPTV; + if (Data32 == 0) { + return EFI_UNSUPPORTED; + } + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + + /// + /// Check if valid SFDP table is present for SPI1 + /// + if (SpiInstance->SpiDescriptor.NumberComponents) { + Data32 = MmioRead32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC1)) & B_PCH_SPI_VSCC1_CPPTV; + if (Data32 == 0) { + /// + /// Program VSCCn values from Flash Descriptor or internal BIOS table + /// if both parts do not support SFDP + /// + return EFI_UNSUPPORTED; + } + } + + for (SpiIndex = 0; SpiIndex <= SpiInstance->SpiDescriptor.NumberComponents; SpiIndex++) { + /// + /// Read Block/Sector Erase Size in 1st dword in the Flash Parameter Table. + /// + ParameterTableIndex = (SpiIndex << N_PCH_SPI_PINTX_SPT) | (V_PCH_SPI_PINTX_HORD_DATA << N_PCH_SPI_PINTX_HORD); + MmioWrite32 (PchRootComplexBar + R_PCH_SPI_PINTX, ParameterTableIndex); + Data32 = MmioRead32 (PchRootComplexBar + R_PCH_SPI_PTDATA) & B_PCH_SPI_VSCC0_BSES_MASK; + + /// + /// Program VSCCn.EO from Flash Descriptor or internal BIOS table + /// if erase size other than 4KB. + /// + if (Data32 != V_PCH_SPI_VSCC0_BSES_4K) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + +/** + Initialize the host controller to execute SPI command. + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] InitData Initialization data to be programmed into the SPI host controller. + + @retval EFI_SUCCESS Initialization completed. + @retval EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down. + @retval EFI_INVALID_PARAMETER Bad input parameters. + @exception EFI_UNSUPPORTED Can't get Descriptor mode VSCC values +**/ +EFI_STATUS +EFIAPI +SpiProtocolInit ( + IN EFI_SPI_PROTOCOL *This, + IN SPI_INIT_DATA *InitData + ) +{ + EFI_STATUS Status; + UINT8 Index; + UINT16 OpcodeType; + SPI_INSTANCE *SpiInstance; + SPI_SPECIAL_OPCODE_ENTRY *SpecialOpcodeEntry; + UINT32 Vscc0Value; + UINT32 Vscc1Value; + UINTN PchRootComplexBar; + UINT8 UnlockCmdOpcodeIndex; + UINT8 ReadDataCmdOpcodeIndex; + UINT8 JedecIdCmdOpcodeIndex; + UINT8 Code; + UINT8 FlashPartId[3]; + UINT32 Data32; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + PchRootComplexBar = SpiInstance->PchRootComplexBar; + Vscc0Value = 0; + Vscc1Value = 0; + + if (InitData == NULL) { + return EFI_INVALID_PARAMETER; + } + /// + /// Check if the SPI interface has been locked-down. + /// + if ((MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFS) & B_PCH_SPI_HSFS_FLOCKDN) != 0) { + ASSERT_EFI_ERROR (EFI_ACCESS_DENIED); + return EFI_ACCESS_DENIED; + } + /// + /// Copy Flash Descriptor Values into SPI driver Private data structure + /// + SpiInstance->DescriptorMode = PchIsSpiDescriptorMode (PchRootComplexBar); + if (SpiInstance->DescriptorMode == TRUE) { + GetDescriptorValues (This); + } + /// + /// Clear all the status bits for hardware regs. + /// + MmioOr16 ( + (UINTN) (PchRootComplexBar + R_PCH_SPI_HSFS), + (UINT16) ((B_PCH_SPI_HSFS_AEL | B_PCH_SPI_HSFS_FCERR | B_PCH_SPI_HSFS_FDONE)) + ); + MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFS); + + /// + /// Clear all the status bits for software regs. + /// + MmioOr8 ( + (UINTN) (PchRootComplexBar + R_PCH_SPI_SSFS), + (UINT8) ((B_PCH_SPI_SSFS_FCERR | B_PCH_SPI_SSFS_CDS)) + ); + MmioRead8 (PchRootComplexBar + R_PCH_SPI_SSFS); + + ReadDataCmdOpcodeIndex = SPI_NUM_OPCODE; + UnlockCmdOpcodeIndex = SPI_NUM_OPCODE; + JedecIdCmdOpcodeIndex = SPI_NUM_OPCODE; + /// + /// Set Opcode Type Configuration registers. + /// Need to be done before sending any SPI command + /// + for (Index = 0, OpcodeType = 0; Index < SPI_NUM_OPCODE; Index++) { + /// + /// Copy Operation and Frequency into SPI driver Private data structure + /// + SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation = InitData->SpiCmdConfig[Index].Operation; + SpiInstance->SpiInitTable.SpiCmdConfig[Index].Frequency = InitData->SpiCmdConfig[Index].Frequency; + + switch (SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation) { + case EnumSpiOperationReadData: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_READ_DATA; + ReadDataCmdOpcodeIndex = Index; + break; + + case EnumSpiOperationFastRead: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_FAST_READ; + ReadDataCmdOpcodeIndex = Index; + break; + + case EnumSpiOperationDualOutputFastRead: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_DUAL_FAST_READ; + ReadDataCmdOpcodeIndex = Index; + break; + + case EnumSpiOperationDiscoveryParameters: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_DISCOVERY_PARAMETERS; + break; + + case EnumSpiOperationProgramData_1_Byte: + case EnumSpiOperationProgramData_64_Byte: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_PROGRAM_BYTE; + break; + + case EnumSpiOperationErase_256_Byte: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_256B_ERASE; + break; + + case EnumSpiOperationErase_4K_Byte: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_4KB_ERASE; + break; + + case EnumSpiOperationErase_64K_Byte: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_64KB_ERASE; + break; + + case EnumSpiOperationWriteStatus: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_WRITE_STATUS; + UnlockCmdOpcodeIndex = Index; + break; + + case EnumSpiOperationWriteDisable: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_WRITE_DISABLE; + break; + + case EnumSpiOperationWriteEnable: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_WRITE_ENABLE; + break; + + case EnumSpiOperationEnableWriteStatus: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_ENABLE_WRITE_STATUS; + break; + + case EnumSpiOperationFullChipErase: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_WRNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_FULL_CHIP_ERASE; + break; + + case EnumSpiOperationReadStatus: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_READ_STATUS; + break; + + case EnumSpiOperationJedecId: + OpcodeType |= (UINT16) (V_PCH_SPI_OPTYPE_RDNOADDR << (Index * 2)); + Code = PCH_SPI_COMMAND_READ_ID; + JedecIdCmdOpcodeIndex = Index; + break; + + case EnumSpiOperationErase_8K_Byte: + case EnumSpiOperationOther: + Code = 0; + break; + + default: + Code = 0; + ASSERT (FALSE); + break; + } + /// + /// Overrided Opcode Type and Menu Configuration registers per SpecialOpcodeEntry + /// + if (InitData->SpecialOpcodeEntry != NULL) { + SpecialOpcodeEntry = InitData->SpecialOpcodeEntry; + + while (SpecialOpcodeEntry->OpcodeIndex != 0xFF) { + if (SpecialOpcodeEntry->OpcodeIndex == Index) { + OpcodeType &= (UINT16)~(B_PCH_SPI_OPTYPE0_MASK << (Index * 2)); + OpcodeType |= (UINT16) (SpecialOpcodeEntry->Type << (Index * 2)); + Code = SpecialOpcodeEntry->Code; + } + + SpecialOpcodeEntry++; + } + } + /// + /// Set Opcode Menu Configuration registers. + /// Need to be done before sending any SPI command + /// + MmioWrite8 ( + PchRootComplexBar + R_PCH_SPI_OPMENU + Index, + Code + ); + MmioRead8 (PchRootComplexBar + R_PCH_SPI_OPMENU + Index); + } + /// + /// Set Opcode Type Configuration registers. + /// + MmioWrite16 (PchRootComplexBar + R_PCH_SPI_OPTYPE, OpcodeType); + MmioRead16 (PchRootComplexBar + R_PCH_SPI_OPTYPE); + + if (JedecIdCmdOpcodeIndex >= SPI_NUM_OPCODE) { + return EFI_UNSUPPORTED; + } else { + /// + /// Read VendorId/DeviceId from SPI Component 1 + /// + Status = SpiProtocolExecute ( + This, + JedecIdCmdOpcodeIndex, + 0, + TRUE, + TRUE, + FALSE, + (UINTN) 0, + 3, + FlashPartId, + EnumSpiRegionDescriptor + ); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Copy VendorId, DeviceId0, DeviceId1 and BiosStartOffset into SPI + /// driver Private data structure + /// + SpiInstance->SpiIdTable[0].VendorId = FlashPartId[0]; + SpiInstance->SpiIdTable[0].DeviceId0 = FlashPartId[1]; + SpiInstance->SpiIdTable[0].DeviceId1 = FlashPartId[2]; + SpiInstance->SpiInitTable.BiosStartOffset = InitData->BiosStartOffset; + if (SpiInstance->SpiDescriptor.NumberComponents == 0x01) { + /// + /// If SPI Descriptor indicates two SPI components then + /// read VendorId/DeviceId from SPI Component 2. + /// Calculate SPI Component 2 address. The secondary SPI's address is equal to the first SPI's size + /// Note: 512KB (BIT19) is the minimum Componenty Density. + /// + Data32 = (UINT32) (UINTN) (V_PCH_SPI_FLCOMP_COMP_512KB << SpiInstance->SpiDescriptor.Comp1Density); + Status = SpiProtocolExecute ( + This, + JedecIdCmdOpcodeIndex, + 0, + TRUE, + TRUE, + FALSE, + (UINTN) Data32, + 3, + FlashPartId, + EnumSpiRegionAll + ); + if (!EFI_ERROR (Status)) { + /// + /// Copy VendorId, DeviceId0, DeviceId1 into SPI + /// driver Private data structure + /// + SpiInstance->SpiIdTable[1].VendorId = FlashPartId[0]; + SpiInstance->SpiIdTable[1].DeviceId0 = FlashPartId[1]; + SpiInstance->SpiIdTable[1].DeviceId1 = FlashPartId[2]; + } + } + /// + /// Set the Prefix Opcode registers. + /// + MmioWrite16 ( + PchRootComplexBar + R_PCH_SPI_PREOP, + (InitData->PrefixOpcode[1] << 8) | InitData->PrefixOpcode[0] + ); + MmioRead16 (PchRootComplexBar + R_PCH_SPI_PREOP); + + /// + /// Copy PrefixOpcode into SPI driver Private data structure + /// + for (Index = 0; Index < SPI_NUM_PREFIX_OPCODE; Index++) { + SpiInstance->SpiInitTable.PrefixOpcode[Index] = InitData->PrefixOpcode[Index]; + } + /// + /// Copy BiosSize into SPI driver Private data structure + /// + SpiInstance->SpiInitTable.BiosSize = InitData->BiosSize; + } + /// + /// Get VSCC values from VTBA table in the Descriptor. + /// + if (SpiInstance->DescriptorMode == TRUE) { + Status = GetDescriptorVsccValues ( + This, + ReadDataCmdOpcodeIndex, + &Vscc0Value, + &Vscc1Value + ); + + if (EFI_ERROR (Status)) { + /// + /// Program the VSCC0 & VSCC1 registers by getting the data from SpiInitTable + /// + for (Index = 0; Index < SPI_NUM_OPCODE; Index++) { + /// + /// For every platform that supports ME, only 4 KB erase is supported + /// Get the opcode from SpiInitTable if the operation is 4 KB erase + /// + if (SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation == EnumSpiOperationErase_4K_Byte) { + Vscc0Value = Vscc0Value | (UINT32) (V_PCH_SPI_VSCC0_BSES_4K); + Vscc0Value = Vscc0Value | (UINT32) (PCH_SPI_COMMAND_4KB_ERASE << 8); + } else if (SpiInstance->SpiInitTable.SpiCmdConfig[Index].Operation == EnumSpiOperationProgramData_64_Byte) { + Vscc0Value = Vscc0Value | (UINT32) (B_PCH_SPI_VSCC0_WG_64B); + } + } + /// + /// Bit WSR and WEWS should NOT be both set to 1, so we check if there is any "Write enable on Write status" prefix opcode + /// from SpiInitTable at first, then check "Write Status Enable" prefix opcode + /// + if ((SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_ENABLE) || + (SpiInstance->SpiInitTable.PrefixOpcode[1] == PCH_SPI_COMMAND_WRITE_ENABLE)) { + Vscc0Value = Vscc0Value | (UINT32) (B_PCH_SPI_VSCC0_WEWS); + } else if ((SpiInstance->SpiInitTable.PrefixOpcode[0] == PCH_SPI_COMMAND_WRITE_STATUS_EN) || + (SpiInstance->SpiInitTable.PrefixOpcode[1] == PCH_SPI_COMMAND_WRITE_STATUS_EN)) { + Vscc0Value = Vscc0Value | (UINT32) (B_PCH_SPI_VSCC0_WSR); + } + + Vscc1Value = Vscc0Value; + } + /// + /// The VCL locks itself when set, it will assert because we have no way to update VSCC value + /// + if ((MmioRead32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC0)) & B_PCH_SPI_VSCC0_VCL) != 0) { + ASSERT_EFI_ERROR (EFI_ACCESS_DENIED); + return EFI_ACCESS_DENIED; + } + + ASSERT (Vscc0Value != 0); + MmioWrite32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC0), Vscc0Value); + if (SpiInstance->SpiDescriptor.NumberComponents) { + MmioWrite32 ((UINTN) (PchRootComplexBar + R_PCH_SPI_VSCC1), Vscc1Value); + } + } + + SpiPhaseInit (); + + return EFI_SUCCESS; +} + +/** + Execute SPI commands from the host controller. + This function would be called by runtime driver, please do not use any MMIO marco here + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] OpcodeIndex Index of the command in the OpCode Menu. + @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence. + @param[in] DataCycle TRUE if the SPI cycle contains data + @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed. + @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in. + @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform + Region, this value specifies the offset from the Region Base; for BIOS Region, + this value specifies the offset from the start of the BIOS Image. In Non + Descriptor Mode, this value specifies the offset from the start of the BIOS Image. + Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is + supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the + data transfer into multiple operations. This function ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a stricter address boundary requirement + (e.g., its write page size is < 256 byte), then the caller cannot rely on this + function to cut the data transfer at proper address boundaries, and it's the + caller's reponsibility to pass in a properly cut DataByteCount parameter. + @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the + SPI cycle. + @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative + to base of the 1st flash device (i.e., it is a Flash Linear Address). + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @exception EFI_UNSUPPORTED Command not supported. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolExecute ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 OpcodeIndex, + IN UINT8 PrefixOpcodeIndex, + IN BOOLEAN DataCycle, + IN BOOLEAN Atomic, + IN BOOLEAN ShiftOut, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer, + IN SPI_REGION_TYPE SpiRegionType + ) +{ + EFI_STATUS Status; + UINT8 BiosCtlSave; + UINT32 Data32; + UINT32 PmBase; + UINT32 SmiEnSave; + + BiosCtlSave = 0; + SmiEnSave = 0; + + /// + /// Check if the parameters are valid. + /// + if ((OpcodeIndex >= SPI_NUM_OPCODE) || (PrefixOpcodeIndex >= SPI_NUM_PREFIX_OPCODE)) { + return EFI_INVALID_PARAMETER; + } + /// + /// Make sure it's safe to program the command. + /// Poll both Hardware Sequencing and Software Sequencing Status + /// + if (!WaitForSpiCycleComplete (This, TRUE, FALSE)) { + return EFI_DEVICE_ERROR; + } + + if (!WaitForSpiCycleComplete (This, FALSE, FALSE)) { + return EFI_DEVICE_ERROR; + } + /// + /// Acquire access to the SPI interface is not required any more. + /// + /// + /// Disable SMIs to make sure normal mode flash access is not interrupted by an SMI + /// whose SMI handler accesses flash (e.g. for error logging) + /// + /// *** NOTE: if the SMI_LOCK bit is set (i.e., B0:D31:F0:Offset A0h [4]='1'), + /// clearing B_GBL_SMI_EN will not have effect. In this situation, some other + /// synchronization methods must be applied either here or in the consumer of the + /// EFI_SPI_PROTOCOl.Execute(). An example method is disabling the specific SMI sources + /// whose SMI handlers access flash before calling Execute() and re-enabling the SMI + /// sources after the call. + /// + PmBase = PciRead32 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_ACPI_BASE) + ) & B_PCH_LPC_ACPI_BASE_BAR; + + SmiEnSave = IoRead32 ((UINTN) (PmBase + R_PCH_SMI_EN)); + Data32 = SmiEnSave &~B_PCH_SMI_EN_GBL_SMI; + IoWrite32 ((UINTN) (PmBase + R_PCH_SMI_EN), Data32); + /// + /// If shifts the data out, disable Prefetching and Caching. + /// + if (ShiftOut) { + BiosCtlSave = PciRead8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL) + ) & V_PCH_LPC_BIOS_CNTL_SRC; + PciAndThenOr8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (~V_PCH_LPC_BIOS_CNTL_SRC), + (UINT8) ((V_PCH_SRC_PREF_DIS_CACHE_DIS)) + ); + } + /// + /// Sends the command to the SPI interface to execute. + /// + Status = SendSpiCmd ( + This, + OpcodeIndex, + PrefixOpcodeIndex, + DataCycle, + Atomic, + ShiftOut, + Address, + DataByteCount, + Buffer, + SpiRegionType + ); + /// + /// Restore the settings for SPI Prefetching and Caching. + /// + if (ShiftOut) { + PciAndThenOr8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (~V_PCH_LPC_BIOS_CNTL_SRC), + (UINT8) (BiosCtlSave) + ); + } + /// + /// Restore SMIs. + /// + IoWrite32 ((UINTN) (PmBase + R_PCH_SMI_EN), SmiEnSave); + + return Status; +} + +/** + Convert SPI offset to Physical address of SPI hardware + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] SpiRegionOffset In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform + Region, this value specifies the offset from the Region Base; for BIOS Region, + this value specifies the offset from the start of the BIOS Image. In Non + Descriptor Mode, this value specifies the offset from the start of the BIOS Image. + Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is + supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param[in] BaseAddress Base Address of the region. + @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative + to base of the 1st flash device (i.e., it is a Flash Linear Address). + @param[in, out] HardwareSpiAddress Return absolution SPI address (i.e., Flash Linear Address) + @param[in, out] BaseAddress Return base address of the region type + @param[in, out] LimitAddress Return limit address of the region type + + @retval EFI_SUCCESS Command succeed. +**/ +VOID +SpiOffset2Physical ( + IN EFI_SPI_PROTOCOL *This, + IN UINTN SpiRegionOffset, + IN SPI_REGION_TYPE SpiRegionType, + OUT UINTN *HardwareSpiAddress, + OUT UINTN *BaseAddress, + OUT UINTN *LimitAddress + ) +{ + SPI_INSTANCE *SpiInstance; + UINTN PchRootComplexBar; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + PchRootComplexBar = SpiInstance->PchRootComplexBar; + + if (SpiInstance->DescriptorMode == TRUE) { + switch (SpiRegionType) { + + case EnumSpiRegionBios: + *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG1_BIOS) + & B_PCH_SPI_FREG1_LIMIT_MASK) >> 16) + 1) << 12; + *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG1_BIOS) + & B_PCH_SPI_FREG1_BASE_MASK) << 12; + break; + + case EnumSpiRegionGbE: + *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG3_GBE) & B_PCH_SPI_FREG3_BASE_MASK) << 12; + *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG3_GBE) + & B_PCH_SPI_FREG3_LIMIT_MASK) >> 16) + 1) << 12; + break; + + case EnumSpiRegionMe: + *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG2_ME) & B_PCH_SPI_FREG2_BASE_MASK) << 12; + *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG2_ME) + & B_PCH_SPI_FREG2_LIMIT_MASK) >> 16) + 1) << 12; + break; + + case EnumSpiRegionDescriptor: + *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG0_FLASHD) & B_PCH_SPI_FREG0_BASE_MASK) << 12; + *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG0_FLASHD) + & B_PCH_SPI_FREG0_LIMIT_MASK) >> 16) + 1) << 12; + break; + + case EnumSpiRegionPlatformData: + *BaseAddress = (MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG4_PLATFORM_DATA) & B_PCH_SPI_FREG4_BASE_MASK) << 12; + *LimitAddress = (((MmioRead32 (PchRootComplexBar + R_PCH_SPI_FREG4_PLATFORM_DATA) + & B_PCH_SPI_FREG4_LIMIT_MASK) >> 16) + 1) << 12; + break; + + default: + /// + /// EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash + /// Linear Address) + /// + *BaseAddress = 0; + *LimitAddress = 0; + break; + } + + *HardwareSpiAddress = SpiRegionOffset +*BaseAddress; + } else { + if (SpiRegionType == EnumSpiRegionAll) { + /// + /// EnumSpiRegionAll indicates address is relative to flash device (i.e., address is Flash + /// Linear Address) + /// + *HardwareSpiAddress = SpiRegionOffset; + } else { + /// + /// Otherwise address is relative to BIOS image + /// + *HardwareSpiAddress = SpiRegionOffset + SpiInstance->SpiInitTable.BiosStartOffset; + } + } +} + +/** + This function sends the programmed SPI command to the slave device. + + @param[in] OpcodeIndex Index of the command in the OpCode Menu. + @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence. + @param[in] DataCycle TRUE if the SPI cycle contains data + @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed. + @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in. + @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform + Region, this value specifies the offset from the Region Base; for BIOS Region, + this value specifies the offset from the start of the BIOS Image. In Non + Descriptor Mode, this value specifies the offset from the start of the BIOS Image. + Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is + supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the + data transfer into multiple operations. This function ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a stricter address boundary requirement + (e.g., its write page size is < 256 byte), then the caller cannot rely on this + function to cut the data transfer at proper address boundaries, and it's the + caller's reponsibility to pass in a properly cut DataByteCount parameter. + @param[in, out] Buffer Data received or sent during the SPI cycle. + @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative + to base of the 1st flash device (i.e., it is a Flash Linear Address). + + @retval EFI_SUCCESS SPI command completes successfully. + @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally. + @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. +**/ +EFI_STATUS +SendSpiCmd ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 OpcodeIndex, + IN UINT8 PrefixOpcodeIndex, + IN BOOLEAN DataCycle, + IN BOOLEAN Atomic, + IN BOOLEAN ShiftOut, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer, + IN SPI_REGION_TYPE SpiRegionType + ) +{ + UINT32 Index; + SPI_INSTANCE *SpiInstance; + UINTN HardwareSpiAddr; + UINTN SpiBiosSize; + BOOLEAN UseSoftwareSequence; + UINTN BaseAddress; + UINTN LimitAddress; + UINT32 SpiDataCount; + UINT8 OpCode; + UINT16 OpType; + SPI_OPERATION Operation; + UINTN PchRootComplexBar; + UINT32 SpiSoftFreq; + UINT16 FlashCycle; + UINT8 BiosCntl; + BOOLEAN BiosWriteProtect; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + PchRootComplexBar = SpiInstance->PchRootComplexBar; + SpiBiosSize = SpiInstance->SpiInitTable.BiosSize; + Operation = SpiInstance->SpiInitTable.SpiCmdConfig[OpcodeIndex].Operation; + OpCode = MmioRead8 (PchRootComplexBar + R_PCH_SPI_OPMENU + OpcodeIndex); + OpType = (MmioRead16 (PchRootComplexBar + R_PCH_SPI_OPTYPE) >> OpcodeIndex * 2) & (UINT16) (B_PCH_SPI_OPTYPE0_MASK); + /// + /// Please use PciRead here, it will link to MmioRead + /// if the caller is a Runtime driver, please use PchDxeRuntimePciLibPciExpress library, refer + /// PciExpressRead() on Library\DxeRuntimePciLibPciExpress\DxeRuntimePciLibPciExpress.c for the details. + /// For the rest please use EdkIIGlueBasePciLibPciExpress library + /// + BiosCntl = PciRead8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL)); + /// + /// Check if the value of opcode register is 0 or the BIOS Size of SpiInitTable is 0 while SpiRegionType is EnumSpiRegionBios. + /// + if (OpCode == 0 || (SpiBiosSize == 0 && SpiRegionType == EnumSpiRegionBios)) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + /// + /// Check if need to disable BIOS Write Protect + /// + if ((Operation == EnumSpiOperationProgramData_1_Byte) || + (Operation == EnumSpiOperationProgramData_64_Byte) || + (Operation == EnumSpiOperationErase_256_Byte) || + (Operation == EnumSpiOperationErase_4K_Byte) || + (Operation == EnumSpiOperationErase_8K_Byte) || + (Operation == EnumSpiOperationErase_64K_Byte) || + (Operation == EnumSpiOperationFullChipErase)) { + DisableBiosWriteProtect (); + BiosWriteProtect = FALSE; + } else { + BiosWriteProtect = TRUE; + } + /// + /// Per PCH BIOS Spec Section 3.7 BIOS Region SMM Protection Enabling, + /// If SMM_BWP bit (D31:F0:RegDCh[5]) is set, the BIOS Region can only be updated + /// by following the steps: + /// - Once all threads enter SMM + /// - Read memory location FED30880h OR with 00000001h, place the result in EAX, + /// and write data to lower 32 bits of MSR 1FEh. (This is done in + /// DisableBiosWriteProtect()) + /// + if (((BiosCntl & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) && + (BiosWriteProtect == FALSE) && + ((MmioRead32 ((UINTN) 0xFED30880) & (UINT32) BIT0) == 0)) { + EnableBiosWriteProtect (); + return EFI_ACCESS_DENIED; + } + /// + /// When current code is read id OR current is not descriptor mode, we will use compatible mode + /// + UseSoftwareSequence = FALSE; + if ((Operation == EnumSpiOperationJedecId) || + (Operation == EnumSpiOperationReadStatus) || + (Operation == EnumSpiOperationWriteStatus) || + (Operation == EnumSpiOperationWriteDisable) || + (Operation == EnumSpiOperationWriteEnable) || + (Operation == EnumSpiOperationEnableWriteStatus) || + (Operation == EnumSpiOperationOther) || + (Operation == EnumSpiOperationDiscoveryParameters) || + (SpiInstance->DescriptorMode == FALSE) + ) { + UseSoftwareSequence = TRUE; + } + + SpiOffset2Physical (This, Address, SpiRegionType, &HardwareSpiAddr, &BaseAddress, &LimitAddress); + /// + /// Have direct access to BIOS region in Descriptor mode, + /// + if (OpType == EnumSpiOpcodeRead && SpiRegionType == EnumSpiRegionBios) { + CopyMem ( + Buffer, + (UINT8 *) ((HardwareSpiAddr - BaseAddress) + (UINT32) (~(SpiBiosSize - 1))), + DataByteCount + ); + return EFI_SUCCESS; + } + /// + /// DEBUG((EFI_D_ERROR, "SPIADDR %x, %x, %x, %x\n", Address, HardwareSpiAddr, BaseAddress, + /// LimitAddress)); + /// + if ((DataCycle == FALSE) && (DataByteCount > 0)) { + DataByteCount = 0; + } + + do { + /// + /// Trim at 256 byte boundary per operation, + /// - PCH SPI controller requires trimming at 4KB boundary + /// - Some SPI chips require trimming at 256 byte boundary for write operation + /// - Trimming has limited performance impact as we can read / write atmost 64 byte + /// per operation + /// + if (HardwareSpiAddr + DataByteCount > ((HardwareSpiAddr + BIT8) &~(BIT8 - 1))) { + SpiDataCount = (((UINT32) (HardwareSpiAddr) + BIT8) &~(BIT8 - 1)) - (UINT32) (HardwareSpiAddr); + } else { + SpiDataCount = DataByteCount; + } + /// + /// Calculate the number of bytes to shift in/out during the SPI data cycle. + /// Valid settings for the number of bytes duing each data portion of the + /// PCH SPI cycles are: 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 24, 32, 40, 48, 56, 64 + /// + if ((SpiInstance->DescriptorMode == FALSE) && + (OpCode == PCH_SPI_COMMAND_PROGRAM_BYTE || Operation == EnumSpiOperationProgramData_1_Byte)) { + SpiDataCount = 1; + } else if (SpiDataCount >= 64) { + SpiDataCount = 64; + } else if ((SpiDataCount &~0x07) != 0) { + SpiDataCount = SpiDataCount &~0x07; + } + /// + /// If shifts data out, load data into the SPI data buffer. + /// + if (ShiftOut) { + for (Index = 0; Index < SpiDataCount; Index++) { + MmioWrite8 (PchRootComplexBar + R_PCH_SPI_FDATA00 + Index, Buffer[Index]); + MmioRead8 (PchRootComplexBar + R_PCH_SPI_FDATA00 + Index); + } + } + + MmioWrite32 ( + (PchRootComplexBar + R_PCH_SPI_FADDR), + (UINT32) (HardwareSpiAddr & B_PCH_SPI_FADDR_MASK) + ); + MmioRead32 (PchRootComplexBar + R_PCH_SPI_FADDR); + + /// + /// Execute the command on the SPI compatible mode + /// + if (UseSoftwareSequence) { + /// + /// Software sequencing ... + /// + /// + /// Clear error flags + /// + MmioWrite16 (PchRootComplexBar + R_PCH_SPI_HSFS, (UINT16) B_PCH_SPI_HSFS_AEL); + MmioWrite8 (PchRootComplexBar + R_PCH_SPI_SSFS, (UINT8) B_PCH_SPI_SSFS_FCERR); + + switch (SpiInstance->SpiInitTable.SpiCmdConfig[OpcodeIndex].Frequency) { + case EnumSpiCycle20MHz: + SpiSoftFreq = V_PCH_SPI_SSFC_SCF_20MHZ; + break; + + case EnumSpiCycle33MHz: + SpiSoftFreq = V_PCH_SPI_SSFC_SCF_33MHZ; + break; + + case EnumSpiCycle50MHz: + SpiSoftFreq = V_PCH_SPI_SSFC_SCF_50MHZ; + break; + + default: + /// + /// This is an invalid use of the protocol + /// See definition, but caller must call with valid value + /// + SpiSoftFreq = 0; + ASSERT (!EFI_UNSUPPORTED); + break; + } + /// + /// PCH Chipset EDS 1.1, Section 22.1.19 + /// SSFC BIT23:19 are reserved, BIOS must set this field to '11111'b + /// To change the offset to the right DWORD boundary, so use offset 0x90 as the operation address + /// + if (DataCycle) { + MmioWrite32 ( + (PchRootComplexBar + R_PCH_SPI_SSFC - 1), + ( (UINT32) (BIT23 | BIT22 | BIT21 | BIT20 | BIT19) | + (UINT32) ((SpiSoftFreq << 16) & B_PCH_SPI_SSFC_SCF_MASK) | + (UINT32) (B_PCH_SPI_SSFC_DS) | (UINT32) (((SpiDataCount - 1) << 8) & B_PCH_SPI_SSFC_DBC_MASK) | + (UINT32) ((OpcodeIndex << 4) & B_PCH_SPI_SSFC_COP) | + (UINT32) ((PrefixOpcodeIndex << 3) & B_PCH_SPI_SSFC_SPOP) | + (UINT32) (Atomic ? B_PCH_SPI_SSFC_ACS : 0) | + (UINT32) (B_PCH_SPI_SSFC_SCGO)) << 8); + } else { + MmioWrite32 ( + (PchRootComplexBar + R_PCH_SPI_SSFC - 1), + ( (UINT32) (BIT23 | BIT22 | BIT21 | BIT20 | BIT19) | + (UINT32) ((SpiSoftFreq << 16) & B_PCH_SPI_SSFC_SCF_MASK) | + (UINT32) ((OpcodeIndex << 4) & B_PCH_SPI_SSFC_COP) | + (UINT32) ((PrefixOpcodeIndex << 3) & B_PCH_SPI_SSFC_SPOP) | + (UINT32) (Atomic ? B_PCH_SPI_SSFC_ACS : 0) | + (UINT32) (B_PCH_SPI_SSFC_SCGO)) << 8); + } + + MmioRead32 (PchRootComplexBar + R_PCH_SPI_SSFC - 1); + } else { + /// + /// Hardware sequencing ... + /// + /// + /// check for PCH SPI hardware sequencing required commands + /// + if (Operation == EnumSpiOperationReadData || + Operation == EnumSpiOperationFastRead || + Operation == EnumSpiOperationDualOutputFastRead) { + /// + /// Read Cycle + /// + FlashCycle = (UINT16) (V_PCH_SPI_HSFC_FCYCLE_READ << 1); + } else if (Operation == EnumSpiOperationProgramData_1_Byte || + Operation == EnumSpiOperationProgramData_64_Byte) { + /// + /// Write Cycle + /// + FlashCycle = (UINT16) (V_PCH_SPI_HSFC_FCYCLE_WRITE << 1); + } else if (Operation == EnumSpiOperationErase_256_Byte || + Operation == EnumSpiOperationErase_4K_Byte || + Operation == EnumSpiOperationErase_8K_Byte || + Operation == EnumSpiOperationErase_64K_Byte || + Operation == EnumSpiOperationFullChipErase) { + /// + /// Erase Cycle + /// + FlashCycle = (UINT16) (V_PCH_SPI_HSFC_FCYCLE_ERASE << 1); + } else { + /// + /// Unrecognized Operation + /// + ASSERT (FALSE); + return EFI_ACCESS_DENIED; + } + /// + /// Clear error flags + /// + MmioWrite16 ( + PchRootComplexBar + R_PCH_SPI_HSFS, + (UINT16) (B_PCH_SPI_HSFS_AEL | B_PCH_SPI_HSFS_FCERR) + ); + /// + /// Send the command + /// + MmioWrite16 ( + PchRootComplexBar + R_PCH_SPI_HSFC, + (UINT16) (((SpiDataCount - 1) << 8) & B_PCH_SPI_HSFC_FDBC_MASK) | + FlashCycle | B_PCH_SPI_HSFC_FCYCLE_FGO + ); + /// + /// Read back for posted write to take effect + /// + MmioRead16 (PchRootComplexBar + R_PCH_SPI_HSFC); + } + /// + /// end of command execution + /// + /// Wait the SPI cycle to complete. + /// + if (!WaitForSpiCycleComplete (This, UseSoftwareSequence, TRUE)) { + if (BiosWriteProtect == FALSE) { + /// + /// Enable BIOS Write Protect + /// + EnableBiosWriteProtect (); + } + return EFI_DEVICE_ERROR; + } + /// + /// If shifts data in, get data from the SPI data bufffer. + /// + if (!ShiftOut) { + for (Index = 0; Index < SpiDataCount; Index++) { + Buffer[Index] = MmioRead8 (PchRootComplexBar + R_PCH_SPI_FDATA00 + Index); + } + } + + HardwareSpiAddr += SpiDataCount; + Buffer += SpiDataCount; + DataByteCount -= SpiDataCount; + } while (DataByteCount > 0); + + if (BiosWriteProtect == FALSE) { + /// + /// Enable BIOS Write Protect + /// + EnableBiosWriteProtect (); + } + + return EFI_SUCCESS; +} + +/** + Wait execution cycle to complete on the SPI interface. Check both Hardware + and Software Sequencing status registers + + @param[in] This The SPI protocol instance + @param[in] UseSoftwareSequence TRUE if Software Sequencing + @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check + + @retval TRUE SPI cycle completed on the interface. + @retval FALSE Time out while waiting the SPI cycle to complete. + It's not safe to program the next command on the SPI interface. +**/ +BOOLEAN +WaitForSpiCycleComplete ( + IN EFI_SPI_PROTOCOL *This, + IN BOOLEAN UseSoftwareSequence, + IN BOOLEAN ErrorCheck + ) +{ + UINT64 WaitTicks; + UINT64 WaitCount; + UINT32 StatusRegAddr; + UINT32 CycleInProgressBit; + UINT16 AelBit; + UINT16 FcErrBit; + UINT16 FcycleDone; + UINT16 Data16; + SPI_INSTANCE *SpiInstance; + UINTN PchRootComplexBar; + + SpiInstance = SPI_INSTANCE_FROM_SPIPROTOCOL (This); + PchRootComplexBar = SpiInstance->PchRootComplexBar; + + if (UseSoftwareSequence) { + /// + /// This is Software Sequencing + /// + StatusRegAddr = R_PCH_SPI_SSFS; + CycleInProgressBit = B_PCH_SPI_SSFS_SCIP; + AelBit = B_PCH_SPI_SSFS_AEL; + FcErrBit = B_PCH_SPI_SSFS_FCERR; + FcycleDone = B_PCH_SPI_SSFS_CDS; + } else { + /// + /// This is Hardware Sequencing + /// + StatusRegAddr = R_PCH_SPI_HSFS; + CycleInProgressBit = B_PCH_SPI_HSFS_SCIP; + AelBit = B_PCH_SPI_HSFS_AEL; + FcErrBit = B_PCH_SPI_HSFS_FCERR; + FcycleDone = B_PCH_SPI_HSFS_FDONE; + } + /// + /// Convert the wait period allowed into to tick count + /// + WaitCount = WAIT_TIME / WAIT_PERIOD; + + /// + /// Wait for the SPI cycle to complete. + /// + for (WaitTicks = 0; WaitTicks < WaitCount; WaitTicks++) { + Data16 = MmioRead16 (PchRootComplexBar + StatusRegAddr); + if ((Data16 & CycleInProgressBit) == 0) { + if (UseSoftwareSequence){ + MmioWrite8 (PchRootComplexBar + StatusRegAddr, (UINT8)(AelBit | FcErrBit | FcycleDone)); + }else{ + MmioWrite16 (PchRootComplexBar + StatusRegAddr, (AelBit | FcErrBit | FcycleDone)); + } + if (((Data16 & AelBit) || (Data16 & FcErrBit)) && (ErrorCheck == TRUE)) { + return FALSE; + } else { + return TRUE; + } + } + + PchPmTimerStall (WAIT_PERIOD); + } + + return FALSE; +} diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h new file mode 100644 index 0000000..224ebee --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Common/SpiCommon.h @@ -0,0 +1,300 @@ +/** @file + Header file for the PCH SPI Common Driver. + +@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 _SPI_COMMON_H_ +#define _SPI_COMMON_H_ + +// +// External include files do NOT need to be explicitly specified in real EDKII +// environment +// +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "PchAccess.h" +#include "PchPlatformLib.h" +#endif +// +// Maximum time allowed while waiting the SPI cycle to complete +// Wait Time = 6 seconds = 6000000 microseconds +// Wait Period = 10 microseconds +// +#define WAIT_TIME 6000000 ///< Wait Time = 6 seconds = 6000000 microseconds +#define WAIT_PERIOD 10 ///< Wait Period = 10 microseconds +// +// PCH Required SPI Commands -------- COMMAND SET I ------------ +// SPI flash device must support in order to be compatible with PCH +// +#define PCH_SPI_COMMAND_WRITE_STATUS 0x01 +#define PCH_SPI_COMMAND_PROGRAM_BYTE 0x02 +#define PCH_SPI_COMMAND_READ_DATA 0x03 +#define PCH_SPI_COMMAND_WRITE_DISABLE 0x04 +#define PCH_SPI_COMMAND_READ_STATUS 0x05 +#define PCH_SPI_COMMAND_WRITE_ENABLE 0x06 +#define PCH_SPI_COMMAND_FAST_READ 0x0B +#define PCH_SPI_COMMAND_DUAL_FAST_READ 0x3B ///< Dual Output Fast Read +#define PCH_SPI_COMMAND_ENABLE_WRITE_STATUS 0x50 ///< Enable Write Status Register +#define PCH_SPI_COMMAND_DISCOVERY_PARAMETERS 0x5A ///< Serial Flash Discovery Parameters +#define PCH_SPI_COMMAND_READ_ID 0x9F ///< JEDEC Read ID +#define PCH_SPI_COMMAND_FULL_CHIP_ERASE 0xC7 ///< Full Chip Erase +// +// Need to support at least one of the following three kinds of size of sector for erasing +// +#define PCH_SPI_COMMAND_4KB_ERASE 0x20 +#define PCH_SPI_COMMAND_64KB_ERASE 0xD8 +#define PCH_SPI_COMMAND_256B_ERASE 0xDB +// +// ICH8M Recommended SPI Commands -------- COMMAND SET II ------------ +// SPI flash device best to support +// +#define PCH_SPI_COMMAND_WRITE_STATUS 0x01 +#define PCH_SPI_COMMAND_WRITE_STATUS_EN 0x50 +#define PCH_SPI_COMMAND_FULL_CHIP_ERASE 0xC7 + +#define SIZE_OF_SPI_VTBA_ENTRY (S_PCH_SPI_VTBA_JID0 + S_PCH_SPI_VTBA_VSCC0) + +/// +/// Private data structure definitions for the driver +/// +#define PCH_SPI_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'S', 'P', 'I') + +/// +/// Initialization data table loaded to the SPI host controller +/// PrefixOpcode Prefix opcodes which are loaded into the SPI host controller +/// SpiCmdConfig Determines Opcode Type, Menu and Frequency of the SPI commands +/// BiosStartOffset The offset of the start of the BIOS image relative to the flash device. +/// Please note this is a Flash Linear Address, NOT a memory space address. +/// This value is platform specific and depends on the system flash map. +/// This value is only used on non Descriptor mode. +/// BiosSize The the BIOS Image size in flash. This value is platform specific +/// and depends on the system flash map. Please note BIOS Image size may +/// be smaller than BIOS Region size (in Descriptor Mode) or the flash size +/// (in Non Descriptor Mode), and in this case, BIOS Image is supposed to be +/// placed at the top end of the BIOS Region (in Descriptor Mode) or the flash +/// (in Non Descriptor Mode) +/// +typedef struct _SPI_INIT_TABLE { + UINT8 PrefixOpcode[SPI_NUM_PREFIX_OPCODE]; + SPI_COMMAND_CONFIG SpiCmdConfig[SPI_NUM_OPCODE]; + UINTN BiosStartOffset; + UINTN BiosSize; +} SPI_INIT_TABLE; + +typedef struct _SPI_ID_TABLE { + UINT8 VendorId; + UINT8 DeviceId0; + UINT8 DeviceId1; +} SPI_ID_TABLE; + +typedef struct _SPI_DESCRIPTOR_TABLE { + UINT8 NumberComponents :2; + UINT8 Comp1Density :4; + UINT8 Rsvd :2; +} SPI_DESCRIPTOR_TABLE; + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SPI_PROTOCOL SpiProtocol; + SPI_INIT_TABLE SpiInitTable; + SPI_ID_TABLE SpiIdTable[2]; + UINTN PchRootComplexBar; + SPI_DESCRIPTOR_TABLE SpiDescriptor; + BOOLEAN DescriptorMode; +} SPI_INSTANCE; + +#define SPI_INSTANCE_FROM_SPIPROTOCOL(a) CR (a, SPI_INSTANCE, SpiProtocol, PCH_SPI_PRIVATE_DATA_SIGNATURE) + +// +// Function prototypes used by the SPI protocol. +// + +/** + Initialize an SPI protocol instance. + The function will assert in debug if PCH RCBA has not been initialized + + @param[in] SpiInstance Pointer to SpiInstance to initialize + + @retval EFI_SUCCESS The protocol instance was properly initialized + @exception EFI_UNSUPPORTED The PCH is not supported by this module +**/ +EFI_STATUS +SpiProtocolConstructor ( + SPI_INSTANCE *SpiInstance + ); + +/** + JEDEC Read IDs from SPI flash part, this function will return 1-byte Vendor ID and 2-byte Device ID + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] Address This value is for determines the command is sent to SPI Component 1 or 2 + @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the SPI cycle. + + @retval EFI_SUCCESS Read Jedec Id completed. + @retval EFI_DEVICE_ERROR Device error, operation failed. + @exception EFI_UNSUPPORTED This function is unsupport after SpiProtocolInit is called +**/ +EFI_STATUS +EFIAPI +SpiProtocolReadId ( + IN EFI_SPI_PROTOCOL *This, + IN UINTN Address, + IN OUT UINT8 *Buffer + ); + +/** + Initialize the host controller to execute SPI command. + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] InitData Initialization data to be programmed into the SPI host controller. + + @retval EFI_SUCCESS Initialization completed. + @retval EFI_ACCESS_DENIED The SPI static configuration interface has been locked-down. + @retval EFI_INVALID_PARAMETER Bad input parameters. + @exception EFI_UNSUPPORTED Can't get Descriptor mode VSCC values +**/ +EFI_STATUS +EFIAPI +SpiProtocolInit ( + IN EFI_SPI_PROTOCOL *This, + IN SPI_INIT_DATA *InitData + ); + +/** + Execute SPI commands from the host controller. + This function would be called by runtime driver, please do not use any MMIO marco here + + @param[in] This Pointer to the EFI_SPI_PROTOCOL instance. + @param[in] OpcodeIndex Index of the command in the OpCode Menu. + @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence. + @param[in] DataCycle TRUE if the SPI cycle contains data + @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed. + @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in. + @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform + Region, this value specifies the offset from the Region Base; for BIOS Region, + this value specifies the offset from the start of the BIOS Image. In Non + Descriptor Mode, this value specifies the offset from the start of the BIOS Image. + Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is + supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the + data transfer into multiple operations. This function ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a stricter address boundary requirement + (e.g., its write page size is < 256 byte), then the caller cannot rely on this + function to cut the data transfer at proper address boundaries, and it's the + caller's reponsibility to pass in a properly cut DataByteCount parameter. + @param[in, out] Buffer Pointer to caller-allocated buffer containing the dada received or sent during the + SPI cycle. + @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative + to base of the 1st flash device (i.e., it is a Flash Linear Address). + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @exception EFI_UNSUPPORTED Command not supported. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +EFI_STATUS +EFIAPI +SpiProtocolExecute ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 OpcodeIndex, + IN UINT8 PrefixOpcodeIndex, + IN BOOLEAN DataCycle, + IN BOOLEAN Atomic, + IN BOOLEAN ShiftOut, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer, + IN SPI_REGION_TYPE SpiRegionType + ); + +/** + This function sends the programmed SPI command to the slave device. + + @param[in] OpcodeIndex Index of the command in the OpCode Menu. + @param[in] PrefixOpcodeIndex Index of the first command to run when in an atomic cycle sequence. + @param[in] DataCycle TRUE if the SPI cycle contains data + @param[in] Atomic TRUE if the SPI cycle is atomic and interleave cycles are not allowed. + @param[in] ShiftOut If DataByteCount is not zero, TRUE to shift data out and FALSE to shift data in. + @param[in] Address In Descriptor Mode, for Descriptor Region, GbE Region, ME Region and Platform + Region, this value specifies the offset from the Region Base; for BIOS Region, + this value specifies the offset from the start of the BIOS Image. In Non + Descriptor Mode, this value specifies the offset from the start of the BIOS Image. + Please note BIOS Image size may be smaller than BIOS Region size (in Descriptor + Mode) or the flash size (in Non Descriptor Mode), and in this case, BIOS Image is + supposed to be placed at the top end of the BIOS Region (in Descriptor Mode) or + the flash (in Non Descriptor Mode) + @param[in] DataByteCount Number of bytes in the data portion of the SPI cycle. This function may break the + data transfer into multiple operations. This function ensures each operation does + not cross 256 byte flash address boundary. + *NOTE: if there is some SPI chip that has a stricter address boundary requirement + (e.g., its write page size is < 256 byte), then the caller cannot rely on this + function to cut the data transfer at proper address boundaries, and it's the + caller's reponsibility to pass in a properly cut DataByteCount parameter. + @param[in, out] Buffer Data received or sent during the SPI cycle. + @param[in] SpiRegionType SPI Region type. Values EnumSpiRegionBios, EnumSpiRegionGbE, EnumSpiRegionMe, + EnumSpiRegionDescriptor, and EnumSpiRegionPlatformData are only applicable in + Descriptor mode. Value EnumSpiRegionAll is applicable to both Descriptor Mode + and Non Descriptor Mode, which indicates "SpiRegionOffset" is actually relative + to base of the 1st flash device (i.e., it is a Flash Linear Address). + + @retval EFI_SUCCESS SPI command completes successfully. + @retval EFI_DEVICE_ERROR Device error, the command aborts abnormally. + @retval EFI_ACCESS_DENIED Some unrecognized command encountered in hardware sequencing mode + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. +**/ +EFI_STATUS +SendSpiCmd ( + IN EFI_SPI_PROTOCOL *This, + IN UINT8 OpcodeIndex, + IN UINT8 PrefixOpcodeIndex, + IN BOOLEAN DataCycle, + IN BOOLEAN Atomic, + IN BOOLEAN ShiftOut, + IN UINTN Address, + IN UINT32 DataByteCount, + IN OUT UINT8 *Buffer, + IN SPI_REGION_TYPE SpiRegionType + ); + +/** + Wait execution cycle to complete on the SPI interface. Check both Hardware + and Software Sequencing status registers + + @param[in] This The SPI protocol instance + @param[in] UseSoftwareSequence TRUE if this is a Hardware Sequencing operation + @param[in] ErrorCheck TRUE if the SpiCycle needs to do the error check + + @retval TRUE SPI cycle completed on the interface. + @retval FALSE Time out while waiting the SPI cycle to complete. + It's not safe to program the next command on the SPI interface. +**/ +BOOLEAN +WaitForSpiCycleComplete ( + IN EFI_SPI_PROTOCOL *This, + IN BOOLEAN UseSoftwareSequence, + IN BOOLEAN ErrorCheck + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c new file mode 100644 index 0000000..f5b0062 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.c @@ -0,0 +1,133 @@ +/** @file + PCH SPI PEIM implements the SPI Host Controller Compatibility Interface. + +@copyright + Copyright (c) 2004 - 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 "PchSpi.h" + +/** + Installs PCH SPI PPI + + @param[in] FfsHeader Not used. + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS PCH SPI PPI is installed successfully + @retval EFI_OUT_OF_RESOURCES Can't allocate pool +**/ +EFI_STATUS +InstallPchSpi ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + PEI_SPI_INSTANCE *PeiSpiInstance; + SPI_INSTANCE *SpiInstance; + + DEBUG ((EFI_D_INFO, "InstallPchSpi() Start\n")); + + PeiSpiInstance = (PEI_SPI_INSTANCE *) AllocateZeroPool (sizeof (PEI_SPI_INSTANCE)); + if (NULL == PeiSpiInstance) { + return EFI_OUT_OF_RESOURCES; + } + + SpiInstance = &(PeiSpiInstance->SpiInstance); + SpiProtocolConstructor (SpiInstance); + + PeiSpiInstance->PpiDescriptor.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST; + PeiSpiInstance->PpiDescriptor.Guid = &gPeiSpiPpiGuid; + PeiSpiInstance->PpiDescriptor.Ppi = &(SpiInstance->SpiProtocol); + + /// + /// Install the SPI PPI + /// + Status = (**PeiServices).InstallPpi (PeiServices, &PeiSpiInstance->PpiDescriptor); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "SPI PPI Installed\n")); + + DEBUG ((EFI_D_INFO, "InstallPchSpi() End\n")); + + return Status; +} + +/** + This function is a a hook for Spi Pei phase specific initialization + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +SpiPhaseInit ( + VOID + ) +{ + return; +} + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + /// + /// Enable the access to the BIOS space for both read and write cycles + /// + PciOr8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (B_PCH_LPC_BIOS_CNTL_BIOSWE) + ); +} + +/** + This function is a hook for Spi to enable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ) +{ + /// + /// Disable the access to the BIOS space for write cycles + /// + PciAnd8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (~B_PCH_LPC_BIOS_CNTL_BIOSWE) + ); +} diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs new file mode 100644 index 0000000..a2a2f80 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.dxs @@ -0,0 +1,39 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 2004 - 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/Chipset/LynxPoint/Spi/Pei/PchSpi.h b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.h new file mode 100644 index 0000000..d7be0a2 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpi.h @@ -0,0 +1,74 @@ +/** @file + Header file for the PCH SPI Runtime Driver. + +@copyright + Copyright (c) 2004 - 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_SPI_H_ +#define _PCH_SPI_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGluePeim.h" +#include EFI_PPI_PRODUCER (Spi) +#include "SpiCommon.h" +#endif + +typedef struct { + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; + SPI_INSTANCE SpiInstance; +} PEI_SPI_INSTANCE; + +/** + This function is a hook for Spi Pei phase specific initialization + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +SpiPhaseInit ( + VOID + ); + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +DisableBiosWriteProtect ( + VOID + ); + +/** + This function is a hook for Spi to enable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif new file mode 100644 index 0000000..e6e60c4 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.cif @@ -0,0 +1,13 @@ +<component> + name = "PchSpiPeim" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\Pei" + RefName = "PchSpiPeim" +[files] +"PchSpiPeim.sdl" +"PchSpiPeim.mak" +"PchSpi.c" +"PchSpi.h" +"PchSpi.dxs" +"PchSpiPeim.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf new file mode 100644 index 0000000..44d0485 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.inf @@ -0,0 +1,83 @@ +## @file +# Component description file for the SPI PEIM. +# +#@copyright +# Copyright (c) 2004 - 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 = PchSpiPeim +FILE_GUID = AA652CB9-2D52-4624-9FAE-D4E58B67CA46 +COMPONENT_TYPE = PE32_PEIM + +[sources.common] + PchSpi.h + PchSpi.c + ../Common/SpiCommon.c + +# +# Edk II Glue Driver Entry Point +# + EdkIIGluePeimEntryPoint.c + + +[includes.common] + . + ../Common + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + +[libraries.common] + $(PROJECT_PCH_FAMILY)PpiLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseMemoryLib + EdkIIGluePeiDebugLibReportStatusCode + EdkIIGluePeiReportStatusCodeLib + EdkIIGluePeiServicesLib + EdkIIGluePeiMemoryAllocationLib + EdkIIGlueBasePciLibPciExpress + EdkPpiLib + PchPlatformLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchSpi.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -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_PEI_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak new file mode 100644 index 0000000..5504366 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.mak @@ -0,0 +1,99 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.mak 2 2/24/12 2:24a Victortu $ +# +# $Revision: 2 $ +# +# $Date: 2/24/12 2:24a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.mak $ +# +# 2 2/24/12 2:24a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 9:23a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchSpiPeim Driver +#--------------------------------------------------------------------------- +EDK : PchSpiPeim +PchSpiPeim : $(BUILD_DIR)\PchSpiPeim.mak PchSpiPeimBin + + +$(BUILD_DIR)\PchSpiPeim.mak : $(PchSpiPeim_DIR)\$(@B).cif $(PchSpiPeim_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchSpiPeim_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchSpiPeim_INCLUDES=\ + $(PCH_SPI_INCLUDES)\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + +PchSpiPeim_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + /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_PEI_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ + +PchSpiPeim_LIB_LINKS =\ + $(PchPlatformPeiLib_LIB)\ + $(PchSpiCommonPeiLib_LIB)\ + $(IntelPchPpiLib_LIB)\ + $(IntelPchPpiLib_BIN)\ + $(EDKFRAMEWORKGUIDLIB)\ + $(EdkIIGlueBaseLibIA32_LIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\ + $(EdkIIGluePeiReportStatusCodeLib_LIB)\ + $(EdkIIGluePeiServicesLib_LIB)\ + $(EdkIIGluePeiMemoryAllocationLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + +PchSpiPeimBin: $(PchSpiPeim_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchSpiPeim.mak all\ + NAME=PchSpiPeim\ + MAKEFILE=$(BUILD_DIR)\PchSpiPeim.mak \ + GUID=AA652CB9-2D52-4624-9FAE-D4E58B67CA46\ + "MY_INCLUDES=$(PchSpiPeim_INCLUDES)"\ + "MY_DEFINES=$(MY_DEFINES) $(PchSpiPeim_DEFINES)"\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=PEIM \ + EDKIIModule=PEIM\ + DEPEX1=$(PchSpiPeim_DIR)\PchSpi.dxs DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \ + COMPRESS=0 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl new file mode 100644 index 0000000..526a272 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Pei/PchSpiPeim.sdl @@ -0,0 +1,67 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.sdl 1 2/08/12 9:23a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:23a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiPeim/PchSpiPeim.sdl $ +# +# 1 2/08/12 9:23a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchSpiPeim_SUPPORT" + Value = "1" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes + Help = "Main switch to enable PchSpiPeim support in Project" +End + +PATH + Name = "PchSpiPeim_DIR" + Help = "PchSpiPeim file source directory" +End + +MODULE + File = "PchSpiPeim.mak" + Help = "Includes PchSpiPeim.mak to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchSpiPeim.ffs" + Parent = "FV_BB" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c new file mode 100644 index 0000000..b833b63 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.c @@ -0,0 +1,322 @@ +/** @file + PCH SPI Runtime Driver implements the SPI Host Controller Compatibility Interface. + +@copyright + Copyright (c) 2004 - 2015 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 "PchSpi.h" + +/// +/// Global variables +/// +SPI_INSTANCE *mSpiInstance; +EFI_SPI_DATA_PROTOCOL mSpiDataInfoProtocol; + +static CONST UINT32 mSpiRegister[] = { + R_PCH_SPI_SSFS, + R_PCH_SPI_PREOP, + R_PCH_SPI_OPMENU, + R_PCH_SPI_OPMENU + 4, + R_PCH_SPI_VSCC0, + R_PCH_SPI_VSCC1 +}; + +// +// Function implementations +// + +/** + Fixup internal data pointers so that the services can be called in virtual mode. + + @param[in] Event The event registered. + @param[in] Context Event context. Not used in this event handler. + + @retval None. +**/ +EFI_RUNTIMESERVICE +VOID +PchSpiVirtualAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->PchRootComplexBar)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Init)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiProtocol.Execute)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance->SpiDescriptor)); + gRT->ConvertPointer (EFI_INTERNAL_POINTER, (VOID *) &(mSpiInstance)); +} + +/** + Entry point for the SPI host controller driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @exception EFI_UNSUPPORTED The chipset is unsupported by this driver. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. +**/ +EFI_STATUS +EFIAPI +InstallPchSpi ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT64 BaseAddress; + UINT64 Length; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR LpcMemorySpaceDescriptor; + UINT64 Attributes; + + DEBUG ((EFI_D_INFO, "InstallPchSpi() Start\n")); + + Status = PciLibConstructor (); + ASSERT_EFI_ERROR (Status); + + /// + /// Allocate Runtime memory for the SPI protocol instance. + /// + mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE)); + if (mSpiInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + /// + /// Initialize the SPI protocol instance + /// + Status = SpiProtocolConstructor (mSpiInstance); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Install the EFI_SPI_PROTOCOL interface + /// + Status = gBS->InstallMultipleProtocolInterfaces ( + &(mSpiInstance->Handle), + &gEfiSpiProtocolGuid, + &(mSpiInstance->SpiProtocol), + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (mSpiInstance); + return EFI_DEVICE_ERROR; + } + /// + /// Set RCBA space in GCD to be RUNTIME so that the range will be supported in + /// virtual address mode in EFI aware OS runtime. + /// It will assert if RCBA Memory Space is not allocated + /// The caller is responsible for the existence and allocation of the RCBA Memory Spaces + /// + BaseAddress = (EFI_PHYSICAL_ADDRESS) (mSpiInstance->PchRootComplexBar); + Length = 0x4000; + + Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor); + ASSERT_EFI_ERROR (Status); + + Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME; + + Status = gDS->SetMemorySpaceAttributes ( + BaseAddress, + Length, + Attributes + ); + ASSERT_EFI_ERROR (Status); + + /// + /// LPC memory space + /// + BaseAddress = MmPciAddress(0, + DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0 + ); + Length = 4096; + + Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &LpcMemorySpaceDescriptor); + ASSERT_EFI_ERROR (Status); + + Attributes = LpcMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME; + + Status = gDS->SetMemorySpaceAttributes ( + BaseAddress, + Length, + Attributes + ); + ASSERT_EFI_ERROR (Status); + + Status = PciLibRegisterMemory ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + 0), + (UINTN) Length + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "InstallPchSpi() End\n")); + + return EFI_SUCCESS; +} + +/** + Save SPI VSCC0/VSCC1 register into S3 resume script table. + + @param[in] Event The event that triggered this notification function + @param[in] ParentImageHandle Pointer to the notification functions context +**/ +VOID +EFIAPI +VsccS3SaveRestore ( + IN EFI_EVENT Event, + IN VOID *ParentImageHandle + ) +{ + EFI_STATUS Status; + EFI_BOOT_SCRIPT_SAVE_PROTOCOL *BootScriptSave; + UINTN Index; + + /// + /// Check whether this is real BootScriptSave notification, or just a SignalEvent + /// + Status = gBS->LocateProtocol (&gEfiBootScriptSaveGuid, NULL, (VOID **) &BootScriptSave); + if (EFI_ERROR (Status)) { + return; + } + /// + /// Closed the event to avoid call twice when launch shell + /// + gBS->CloseEvent (Event); + + /// + /// Save SPI Registers for S3 resume usage + /// + INITIALIZE_SCRIPT (ParentImageHandle, gST); + + for (Index = 0; Index < sizeof (mSpiRegister) / sizeof (UINT32); Index++) { + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]), + 1, + (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + mSpiRegister[Index]) + ); + } + + return; +} + +/** + This function is a hook for Spi Dxe phase specific initialization + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +SpiPhaseInit ( + VOID + ) +{ + VOID *Registration; + EFI_STATUS Status; + + /// + /// Create event for the SPI flash VSCC registers S3 save/restore. + /// + EfiCreateProtocolNotifyEvent ( + &gEfiBootScriptSaveGuid, + TPL_CALLBACK, + VsccS3SaveRestore, + NULL, + &Registration + ); + + /// + /// Initialize and Install the SPI Data protocol + /// + mSpiDataInfoProtocol.BiosSize = mSpiInstance->SpiInitTable.BiosSize; + mSpiDataInfoProtocol.BiosStartMemoryAddress = SIZE_4GB - mSpiDataInfoProtocol.BiosSize; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &(mSpiInstance->Handle), + &gEfiSpiDataProtocolGuid, + &mSpiDataInfoProtocol, + NULL + ); + if (EFI_ERROR(Status)) + { + ASSERT(FALSE); + } + + return; +} + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + /// + /// Enable the access to the BIOS space for both read and write cycles + /// + PciOr8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (B_PCH_LPC_BIOS_CNTL_BIOSWE) + ); +} + +/** + This function is a hook for Spi to enable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ) +{ + /// + /// Disable the access to the BIOS space for write cycles + /// + PciAnd8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + PCI_FUNCTION_NUMBER_PCH_LPC, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (~B_PCH_LPC_BIOS_CNTL_BIOSWE) + ); +} diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs new file mode 100644 index 0000000..7a9a510 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.dxs @@ -0,0 +1,39 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 2004 - 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 "DxeDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" +#endif + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h new file mode 100644 index 0000000..aaee7fb --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpi.h @@ -0,0 +1,92 @@ +/** @file + Header file for the PCH SPI Runtime Driver. + +@copyright + Copyright (c) 2004 - 2015 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_SPI_H_ +#define _PCH_SPI_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueDxe.h" +#include EFI_PROTOCOL_PRODUCER (Spi) +#include "SpiCommon.h" +#include "DxeRuntimePciLibPciExpress.h" +#include "EfiScriptLib.h" +#include EFI_PROTOCOL_CONSUMER (BootScriptSave) +#endif + +#define SIZE_4GB 0x0000000100000000ULL + +// +// Function prototypes used by the SPI protocol. +// + +/** + Fixup internal data pointers so that the services can be called in virtual mode. + + @param[in] Event The event registered. + @param[in] Context Event context. Not used in this event handler. + + @retval None. +**/ +VOID +PchSpiVirtualAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + This function is a hook for Spi Dxe phase specific initialization + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +SpiPhaseInit ( + VOID + ); + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +DisableBiosWriteProtect ( + VOID + ); + +/** + This function is a hook for Spi to enable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif new file mode 100644 index 0000000..f721bd8 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.cif @@ -0,0 +1,13 @@ +<component> + name = "PchSpiRuntime" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\RuntimeDxe" + RefName = "PchSpiRuntime" +[files] +"PchSpiRuntime.sdl" +"PchSpiRuntime.mak" +"PchSpi.c" +"PchSpi.h" +"PchSpi.dxs" +"PchSpiRuntime.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf new file mode 100644 index 0000000..cd4ced8 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.inf @@ -0,0 +1,91 @@ +## @file +# Component description file for the SPI Runtime driver. +# +#@copyright +# Copyright (c) 2004 - 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 = PchSpiRuntime +FILE_GUID = C194C6EA-B68C-4981-B64B-9BD271474B20 +COMPONENT_TYPE = RT_DRIVER + +[sources.common] + PchSpi.h + PchSpi.c + ../Common/SpiCommon.c + +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueDxeDriverEntryPoint.c + + +[includes.common] + . + ../Common + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library + +[libraries.common] + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseMemoryLib + EdkIIGlueSmmRuntimeDxeReportStatusCodeLib + EdkIIGlueEdkDxeRuntimeDriverLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueDxeMemoryAllocationLib + EdkIIGlueDxeServicesTableLib + EdkProtocolLib + $(PROJECT_PCH_FAMILY)ProtocolLib + PchDxeRuntimePciLibPciExpress + PchPlatformLib + EfiScriptLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchSpi.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_SET_VIRTUAL_ADDRESS_MAP_EVENT_HANDLER__=PchSpiVirtualAddressChangeEvent + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_EDK_DXE_RUNTIME_DRIVER_LIB__ \ + -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__
\ No newline at end of file diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak new file mode 100644 index 0000000..39646e9 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.mak @@ -0,0 +1,113 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.mak 2 2/24/12 2:27a Victortu $ +# +# $Revision: 2 $ +# +# $Date: 2/24/12 2:27a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.mak $ +# +# 2 2/24/12 2:27a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 9:26a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchSpiRuntime Driver +#--------------------------------------------------------------------------- +EDK : PchSpiRuntime +PchSpiRuntime : $(BUILD_DIR)\PchSpiRuntime.mak PchSpiRuntimeBin + + +$(BUILD_DIR)\PchSpiRuntime.mak : $(PchSpiRuntime_DIR)\$(@B).cif $(PchSpiRuntime_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchSpiRuntime_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchSpiRuntime_INCLUDES=\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(EDK_INCLUDES)\ + $(PCH_SPI_INCLUDES)\ + +PchSpiRuntime_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi"\ + /D "__EDKII_GLUE_SET_VIRTUAL_ADDRESS_MAP_EVENT_HANDLER__=PchSpiVirtualAddressChangeEvent"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + /D __EDKII_GLUE_EDK_DXE_RUNTIME_DRIVER_LIB__ \ + /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + + +PchSpiRuntime_LIB_LINKS =\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGlueEdkDxeRuntimeDriverLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EdkIIGlueDxeServicesTableLib_LIB)\ + $(EDKPROTOCOLLIB)\ + $(INTEL_PCH_PROTOCOL_LIB)\ + $(DxeRuntimePciLibPciExpressLib_LIB)\ + $(PchPlatformDxeLib_LIB)\ + $(EFISCRIPTLIB)\ + $(PchSpiCommonDxeLib_LIB)\ + $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\ + +PchSpiRuntimeBin: $(PchSpiRuntime_LIB_LINKS) + $(ECHO) DEPENDENCY_START > $(BUILD_DIR)\Fake.dxs + $(ECHO) FALSE >> $(BUILD_DIR)\Fake.dxs + $(ECHO) DEPENDENCY_END >> $(BUILD_DIR)\Fake.dxs + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchSpiRuntime.mak all \ + "MY_INCLUDES=$(PchSpiRuntime_INCLUDES)"\ + "MY_DEFINES=$(PchSpiRuntime_DEFINES)"\ + GUID=C194C6EA-B68C-4981-B64B-9BD271474B20\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=RT_DRIVER\ + EDKIIModule=DXEDRIVER\ + DEPEX1=$(BUILD_DIR)\Fake.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ + COMPRESS=1 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl new file mode 100644 index 0000000..02546b0 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/RuntimeDxe/PchSpiRuntime.sdl @@ -0,0 +1,66 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.sdl 1 2/08/12 9:25a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:25a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiRuntime/PchSpiRuntime.sdl $ +# +# 1 2/08/12 9:25a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchSpiRuntime_SUPPORT" + Value = "1" + Help = "Main switch to enable PchSpiRuntime support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchSpiRuntime_DIR" +End + +MODULE + File = "PchSpiRuntime.mak" + Help = "Includes PchSpiRuntime to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchSpiRuntime.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c new file mode 100644 index 0000000..9c041ad --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.c @@ -0,0 +1,244 @@ +/** @file + PCH SPI SMM Driver implements the SPI Host Controller Compatibility Interface. + +@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 "PchSpi.h" + +// +// Global variables +// +EFI_SMM_BASE_PROTOCOL *mSmmBase; +EFI_SMM_SYSTEM_TABLE *mSmst; +SPI_INSTANCE *mSpiInstance; + +/** + Entry point for the SPI host controller driver. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable Global system service table. + + @retval EFI_SUCCESS Initialization complete. + @exception EFI_UNSUPPORTED The chipset is unsupported by this driver. + @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. + @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. +**/ +EFI_STATUS +EFIAPI +InstallPchSpi ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + /// + /// Locate SMM Base Protocol + /// + Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase); + ASSERT_EFI_ERROR (Status); + + /// + /// Initialize our module variables + /// + Status = mSmmBase->GetSmstLocation (mSmmBase, &mSmst); + ASSERT_EFI_ERROR (Status); + + /// + /// Allocate pool for SPI protocol instance + /// + Status = mSmst->SmmAllocatePool ( + EfiRuntimeServicesData, /// MemoryType don't care + sizeof (SPI_INSTANCE), + (VOID **) &mSpiInstance + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mSpiInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem ((VOID *) mSpiInstance, sizeof (SPI_INSTANCE)); + /// + /// Initialize the SPI protocol instance + /// + Status = SpiProtocolConstructor (mSpiInstance); + if (EFI_ERROR (Status)) { + return Status; + } + /// + /// Install the SMM EFI_SPI_PROTOCOL interface + /// + Status = gBS->InstallMultipleProtocolInterfaces ( + &(mSpiInstance->Handle), + &gEfiSmmSpiProtocolGuid, + &(mSpiInstance->SpiProtocol), + NULL + ); + if (EFI_ERROR (Status)) { + mSmst->SmmFreePool (mSpiInstance); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + This function is a a hook for Spi Smm phase specific initialization + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +SpiPhaseInit ( + VOID + ) +{ + UINTN Index; + static CONST UINT32 SpiRegister[] = { + R_PCH_SPI_SSFS, + R_PCH_SPI_PREOP, + R_PCH_SPI_OPMENU, + R_PCH_SPI_OPMENU + 4, + R_PCH_SPI_VSCC0, + R_PCH_SPI_VSCC1 + }; + + /// + /// Save SPI Registers for S3 resume usage + /// + for (Index = 0; Index < sizeof (SpiRegister) / sizeof (UINT32); Index++) { + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint32, + (UINTN) (mSpiInstance->PchRootComplexBar + SpiRegister[Index]), + 1, + (VOID *) (UINTN) (mSpiInstance->PchRootComplexBar + SpiRegister[Index]) + ); + } +} + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +DisableBiosWriteProtect ( + VOID + ) +{ + UINT8 Data8; + UINT32 Data32; + + /// + /// Set BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 1b + /// + PciOr8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (B_PCH_LPC_BIOS_CNTL_BIOSWE) + ); + /// + /// PCH BIOS Spec Rev 0.5.0, Section 3.7 BIOS Region SMM Protection Enabling + /// If the following steps are implemented: + /// - Set the SMM_BWP bit (B0:D31:F0 Offset DCh [5]) = 1b + /// - Follow the 1st recommendation in section 3.6 + /// the BIOS Region can only be updated by following the steps bellow: + /// - Once all threads enter SMM + /// - Read memory location FED30880h OR with 00000001h, place the result in EAX, + /// and write data to lower 32 bits of MSR 1FEh (sample code available) + /// - Set BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 1b + /// - Modify BIOS Region + /// - Clear BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 0b + /// - Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX, + /// and write data to lower 32 bits of MSR 1FEh (sample code available) + /// + Data8 = PciRead8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_BIOS_CNTL) + ); + /// + /// Check if SMM_BWP bit is set + /// + if ((Data8 & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) { + /// + /// Read memory location FED30880h OR with 00000001h, place the result in EAX, + /// and write data to lower 32 bits of MSR 1FEh (sample code available) + /// + Data32 = MmioRead32 ((UINTN) (0xFED30880)) | (UINT32) (BIT0); + AsmWriteMsr32 (0x1FE, Data32); + } +} + +/** + This function is a hook for Spi to enable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ) +{ + UINT8 Data8; + UINT32 Data32; + + /// + /// Clear BIOSWE bit (B0:D31:F0 Offset DCh [0]) = 0b + /// + PciAnd8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_BIOS_CNTL), + (UINT8) (~B_PCH_LPC_BIOS_CNTL_BIOSWE) + ); + + Data8 = PciRead8 ( + PCI_LIB_ADDRESS (DEFAULT_PCI_BUS_NUMBER_PCH, + PCI_DEVICE_NUMBER_PCH_LPC, + 0, + R_PCH_LPC_BIOS_CNTL) + ); + /// + /// Check if SMM_BWP bit is set + /// + if ((Data8 & B_PCH_LPC_BIOS_CNTL_SMM_BWP) == B_PCH_LPC_BIOS_CNTL_SMM_BWP) { + /// + /// Read memory location FED30880h AND with FFFFFFFEh, place the result in EAX, + /// and write data to lower 32 bits of MSR 1FEh (sample code available) + /// + Data32 = MmioRead32 ((UINTN) (0xFED30880)) & (UINT32) (~BIT0); + AsmWriteMsr32 (0x1FE, Data32); + } +} diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs new file mode 100644 index 0000000..0f2e9b0 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.dxs @@ -0,0 +1,45 @@ +/** @file + Dependency expression source file. + +@copyright + Copyright (c) 2004 - 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 "DxeDepex.h" + +// +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase; +// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version +// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase. +// +#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB) +#include "EfiDepex.h" + +#include EFI_PROTOCOL_DEFINITION (SmmBase) +#include EFI_PROTOCOL_DEFINITION (BootScriptSave) +#include EFI_PROTOCOL_DEFINITION (Pfat) +#endif + +DEPENDENCY_START +#ifdef EFI_S3_RESUME + EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND +#endif + EFI_SMM_BASE_PROTOCOL_GUID +DEPENDENCY_END diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h new file mode 100644 index 0000000..1f9244e --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpi.h @@ -0,0 +1,76 @@ +/** @file + Header file for the PCH SPI SMM Driver. + +@copyright + Copyright (c) 2004 - 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_SPI_H_ +#define _PCH_SPI_H_ + +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueDxe.h" +#include EFI_PROTOCOL_PRODUCER (Spi) +#include "SpiCommon.h" +#include "EfiScriptLib.h" + +// +// Driver Dependency Protocols +// +#include EFI_PROTOCOL_DEPENDENCY (SmmBase) +#include EFI_PROTOCOL_CONSUMER (BootScriptSave) +#endif + +/** + This function is a a hook for Spi Smm phase specific initialization + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +SpiPhaseInit ( + VOID + ); + +/** + This function is a hook for Spi to disable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +DisableBiosWriteProtect ( + VOID + ); + +/** + This function is a hook for Spi to enable BIOS Write Protect + + @param[in] None + + @retval None +**/ +VOID +EFIAPI +EnableBiosWriteProtect ( + VOID + ); + +#endif diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif new file mode 100644 index 0000000..8ae77f5 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.cif @@ -0,0 +1,13 @@ +<component> + name = "PchSpiSmm" + category = ModulePart + LocalRoot = "ReferenceCode\Chipset\LynxPoint\Spi\Smm" + RefName = "PchSpiSmm" +[files] +"PchSpiSmm.sdl" +"PchSpiSmm.mak" +"PchSpi.c" +"PchSpi.h" +"PchSpi.dxs" +"PchSpiSmm.inf" +<endComponent> diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf new file mode 100644 index 0000000..5fe34a2 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.inf @@ -0,0 +1,92 @@ +## @file +# Component description file for the SPI SMM driver. +# +#@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 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 = PchSpiSmm +FILE_GUID = 27F4917B-A707-4aad-9676-26DF168CBF0D +COMPONENT_TYPE = BS_DRIVER + +[sources.common] + PchSpi.h + PchSpi.c + ../Common/SpiCommon.c + +# +# Edk II Glue Driver Entry Point +# + EdkIIGlueSmmDriverEntryPoint.c + + +[includes.common] + . + ../Common + $(EDK_SOURCE)/Foundation/Efi + $(EDK_SOURCE)/Foundation/Include + $(EDK_SOURCE)/Foundation/Efi/Include + $(EDK_SOURCE)/Foundation/Framework/Include + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT) + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include + $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library + $(EFI_SOURCE)/$(PROJECT_CPU_ROOT) +# +# EDK II Glue Library utilizes some standard headers from EDK +# + $(EFI_SOURCE) + $(EDK_SOURCE)/Foundation + $(EDK_SOURCE)/Foundation/Framework + $(EDK_SOURCE)/Foundation/Include/IndustryStandard + $(EDK_SOURCE)/Foundation/Core/Dxe + $(EDK_SOURCE)/Foundation/Include/Pei + $(EDK_SOURCE)/Foundation/Library/Dxe/Include + $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include + +[libraries.common] + EdkIIGlueBaseLib + EdkIIGlueBaseIoLibIntrinsic + EdkIIGlueBaseMemoryLib + EdkIIGlueSmmRuntimeDxeReportStatusCodeLib + EdkIIGlueDxeDebugLibReportStatusCode + EdkIIGlueDxeMemoryAllocationLib + EdkIIGlueUefiBootServicesTableLib + EdkIIGlueUefiRuntimeServicesTableLib + EdkIIGlueUefiDevicePathLib + EdkIIGlueBasePciLibPciExpress + EdkFrameworkProtocolLib + EdkProtocolLib + $(PROJECT_PCH_FAMILY)ProtocolLib + PchPlatformLib + EfiScriptLib + +[nmake.common] + IMAGE_ENTRY_POINT = _ModuleEntryPoint + DPX_SOURCE = PchSpi.dxs +# +# Module Entry Point +# + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi + C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + -D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \ + -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \ + -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak new file mode 100644 index 0000000..9b15d4d --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.mak @@ -0,0 +1,112 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.mak 3 9/26/12 3:40a Victortu $ +# +# $Revision: 3 $ +# +# $Date: 9/26/12 3:40a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.mak $ +# +# 3 9/26/12 3:40a Victortu +# Lynx Point PCH Chipset Framework Reference Code Beta 0.7.0 +# +# 2 2/24/12 2:26a Victortu +# Updated to support 4.6.5.3_IntelEDK_1117_Patch7_00. +# +# 1 2/08/12 9:24a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* + +#--------------------------------------------------------------------------- +# Create PchSpi SMM Driver +#--------------------------------------------------------------------------- +EDK : PchSpiSmm +PchSpiSmm : $(BUILD_DIR)\PchSpiSmm.mak PchSpiSmmBin + + +$(BUILD_DIR)\PchSpiSmm.mak : $(PchSpiSmm_DIR)\$(@B).cif $(PchSpiSmm_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(PchSpiSmm_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +PchSpiSmm_INCLUDES=\ + $(INTEL_PCH_INCLUDES)\ + $(EdkIIGlueLib_INCLUDES)\ + $(PCH_SPI_INCLUDES)\ + $(PROJECT_CPU_INCLUDES)\ + +PchSpiSmm_DEFINES = $(MY_DEFINES)\ + /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallPchSpi"\ + /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \ + /D __EDKII_GLUE_BASE_MEMORY_LIB__ \ + /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \ + /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \ + /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \ + /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \ + /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \ + /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \ + /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \ + +PchSpiSmm_LIB_LINKS =\ +!IF "$(x64_BUILD)"=="1" + $(EdkIIGlueBaseLibX64_LIB)\ +!ELSE + $(EdkIIGlueBaseLibIA32_LIB)\ +!ENDIF + $(EdkIIGlueBaseLib_LIB)\ + $(EdkIIGlueBaseIoLibIntrinsic_LIB)\ + $(EdkIIGlueBaseMemoryLib_LIB)\ + $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\ + $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\ + $(EdkIIGlueDxeMemoryAllocationLib_LIB)\ + $(EdkIIGlueUefiBootServicesTableLib_LIB)\ + $(EdkIIGlueUefiDevicePathLib_LIB)\ + $(EdkIIGlueBasePciLibPciExpress_LIB)\ + $(EDKFRAMEWORKPROTOCOLLIB)\ + $(EDKPROTOCOLLIB)\ + $(INTEL_PCH_PROTOCOL_LIB)\ + $(PchPlatformSmmLib_LIB)\ + $(PchSpiCommonSmmLib_LIB)\ + $(EFISCRIPTLIB)\ + $(EdkIIGlueUefiRuntimeServicesTableLib_LIB)\ + +PchSpiSmmBin: $(PchSpiSmm_LIB_LINKS) + $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\ + /f $(BUILD_DIR)\PchSpiSmm.mak all \ + "MY_INCLUDES=$(PchSpiSmm_INCLUDES)"\ + "MY_DEFINES=$(PchSpiSmm_DEFINES)"\ + GUID=27F4917B-A707-4aad-9676-26DF168CBF0D\ + ENTRY_POINT=_ModuleEntryPoint \ + TYPE=BS_DRIVER\ + EDKIIModule=SMMDRIVER\ + DEPEX1=$(PchSpiSmm_DIR)\PchSpi.dxs\ + DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\ + COMPRESS=1 +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* diff --git a/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl new file mode 100644 index 0000000..5310706 --- /dev/null +++ b/ReferenceCode/Chipset/LynxPoint/Spi/Smm/PchSpiSmm.sdl @@ -0,0 +1,66 @@ +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* + +#************************************************************************* +# $Header: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.sdl 1 2/08/12 9:24a Yurenlai $ +# +# $Revision: 1 $ +# +# $Date: 2/08/12 9:24a $ +#************************************************************************* +# Revision History +# ---------------- +# $Log: /Alaska/BIN/Chipset/Intel/SouthBridge/LynxPoint/Intel Pch SB Refcode/PchSpiSmm/PchSpiSmm.sdl $ +# +# 1 2/08/12 9:24a Yurenlai +# Intel Lynx Point/SB eChipset initially releases. +# +#************************************************************************* +TOKEN + Name = "PchSpiSmm_SUPPORT" + Value = "1" + Help = "Main switch to enable PchSpi SMM support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "PchSpiSmm_DIR" +End + +MODULE + File = "PchSpiSmm.mak" + Help = "Includes PchSpi to Project" +End + +ELINK + Name = "$(BUILD_DIR)\PchSpiSmm.ffs" + Parent = "FV_MAIN" + InvokeOrder = AfterParent +End +#************************************************************************* +#************************************************************************* +#** ** +#** (C)Copyright 1985-2011, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#************************************************************************* +#************************************************************************* |