/** @file
PCH SPI PEI Library implements the SPI Host Controller Compatibility Interface.
Copyright (c) 2019 Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct {
EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
SPI_INSTANCE SpiInstance;
} PEI_SPI_INSTANCE;
/**
PCI Enumeratuion is not done till later in DXE
Initlialize SPI BAR0 to a default value till enumeration is done
also enable memory space decoding for SPI
**/
VOID
InitSpiBar0 (
VOID
)
{
UINT64 PchSpiBase;
PchSpiBase = PCI_SEGMENT_LIB_ADDRESS (
DEFAULT_PCI_SEGMENT_NUMBER_PCH,
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_SPI,
PCI_FUNCTION_NUMBER_PCH_SPI,
0
);
PciSegmentAnd8 (PchSpiBase + PCI_COMMAND_OFFSET, (UINT8) ~EFI_PCI_COMMAND_MEMORY_SPACE);
PciSegmentWrite32 (PchSpiBase + R_SPI_CFG_BAR0, PCH_SPI_BASE_ADDRESS);
PciSegmentOr8 (PchSpiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
}
/**
This function Initial SPI services
@retval EFI_STATUS Results of the installation of the SPI services
**/
EFI_STATUS
EFIAPI
SpiServiceInit (
VOID
)
{
EFI_STATUS Status;
PEI_SPI_INSTANCE *PeiSpiInstance;
SPI_INSTANCE *SpiInstance;
PCH_SPI_PPI *SpiPpi;
Status = PeiServicesLocatePpi (
&gPchSpiPpiGuid,
0,
NULL,
(VOID **)&SpiPpi
);
if (Status != EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "SpiServiceInit() Start\n"));
//
// PCI Enumeratuion is not done till later in DXE
// Initlialize SPI BAR0 to a default value till enumeration is done
// also enable memory space decoding for SPI
//
InitSpiBar0 ();
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 = &gPchSpiPpiGuid;
PeiSpiInstance->PpiDescriptor.Ppi = &(SpiInstance->SpiProtocol);
///
/// Install the SPI PPI
///
DEBUG ((DEBUG_INFO, "SPI PPI Installed\n"));
Status = PeiServicesInstallPpi (&PeiSpiInstance->PpiDescriptor);
ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_INFO, "SpiServiceInit() End\n"));
}
else {
DEBUG ((DEBUG_INFO, "SPI PPI already installed\n"));
}
return Status;
}
/**
Acquire pch spi mmio address.
@param[in] SpiInstance Pointer to SpiInstance to initialize
@retval PchSpiBar0 return SPI MMIO address
**/
UINTN
AcquireSpiBar0 (
IN SPI_INSTANCE *SpiInstance
)
{
return PciSegmentRead32 (SpiInstance->PchSpiBase + R_SPI_CFG_BAR0) & ~(B_SPI_CFG_BAR0_MASK);
}
/**
Release pch spi mmio address. Do nothing.
@param[in] SpiInstance Pointer to SpiInstance to initialize
@retval None
**/
VOID
ReleaseSpiBar0 (
IN SPI_INSTANCE *SpiInstance
)
{
}
/**
This function is a hook for Spi to disable BIOS Write Protect
@retval EFI_SUCCESS The protocol instance was properly initialized
@retval EFI_ACCESS_DENIED The BIOS Region can only be updated in SMM phase
**/
EFI_STATUS
EFIAPI
DisableBiosWriteProtect (
VOID
)
{
UINT64 SpiBaseAddress;
SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
DEFAULT_PCI_SEGMENT_NUMBER_PCH,
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_SPI,
PCI_FUNCTION_NUMBER_PCH_SPI,
0
);
if ((PciSegmentRead8 (SpiBaseAddress + R_SPI_CFG_BC) & B_SPI_CFG_BC_EISS) != 0) {
return EFI_ACCESS_DENIED;
}
///
/// Enable the access to the BIOS space for both read and write cycles
///
PciSegmentOr8 (
SpiBaseAddress + R_SPI_CFG_BC,
B_SPI_CFG_BC_WPD
);
return EFI_SUCCESS;
}
/**
This function is a hook for Spi to enable BIOS Write Protect
**/
VOID
EFIAPI
EnableBiosWriteProtect (
VOID
)
{
UINT64 SpiBaseAddress;
SpiBaseAddress = PCI_SEGMENT_LIB_ADDRESS (
DEFAULT_PCI_SEGMENT_NUMBER_PCH,
DEFAULT_PCI_BUS_NUMBER_PCH,
PCI_DEVICE_NUMBER_PCH_SPI,
PCI_FUNCTION_NUMBER_PCH_SPI,
0
);
///
/// Disable the access to the BIOS space for write cycles
///
PciSegmentAnd8 (
SpiBaseAddress + R_SPI_CFG_BC,
(UINT8) (~B_SPI_CFG_BC_WPD)
);
}
/**
Check if it's granted to do flash write.
@retval TRUE It's secure to do flash write.
@retval FALSE It's not secure to do flash write.
**/
BOOLEAN
IsSpiFlashWriteGranted (
VOID
)
{
return TRUE;
}