Allow options for the PMBASE (ACPI Base Address)

How this value is determined is dependent on the platform.
This patch allows the developer to manually set the address;
get it from the BIOS resource list, which is set during
initialization by coreboot; or read it from the chipset registers.

Signed-off-by: Eugene D. Myers <edmyers@tycho.nsa.gov>
This commit is contained in:
Eugene D. Myers 2021-02-16 12:24:44 -05:00
parent 65bd757686
commit 396e497f38
2 changed files with 87 additions and 123 deletions

View File

@ -5,6 +5,7 @@ project(stm C ASM)
if("${BIOS}" STREQUAL "coreboot")
add_definitions( -DCOREBOOT32 )
add_definitions( -DPMBASE_BIOS_RESOURCE )
message("Building for Coreboot")
endif()
@ -40,6 +41,10 @@ if("${STMPE_ENABLED}")
message("STM/PE Enabled")
endif()
if("${PMBASE}")
add_definitions( -DCONFIG_PMBASE=${PMBASE} )
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Xlinker -Map=stm.map -Xlinker --build-id=none -Xlinker --no-dynamic-linker -Xlinker --noinhibit-exec -Os -falign-functions -ffreestanding -s -pie --entry _ModuleEntryPoint -u _ModuleEntryPoint -nostdlib -n -z common-page-size=0x40 -fno-asynchronous-unwind-tables -fno-jump-tables -fPIC -fno-stack-protector -fno-stack-check -include PcdData.h -T ${PROJECT_SOURCE_DIR}/StmPkg/Core/Stm.lds")
set(CMAKE_ASM_FLAGS "-include BaseAsm.h -fPIC")

View File

@ -14,21 +14,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "StmRuntime.h"
#include "PeStm.h"
#include "Library/PciExpressLib.h"
void SetTimerRate(UINT16 value);
// interval timer support
//#define CONFIG_MMCONF_BASE_ADDRESS 0xF8000000///
//#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS // frm sandybridge.h
// from pci_devs.h
#define PCU_DEV 0x1F
// from lcp.h
/* D30:F0 LPC bridge */
#define D31F0_PMBASE 0x40
#define D31F0_GEN_PMCON_1 0xA0
#define D31F0_GEN_PMCON_3 0xA4
@ -45,72 +34,25 @@ void SetTimerRate(UINT16 value);
#define SWSMI_TMR_STS (1<<6)
#define PERIODIC_STS (1<<14)
// from arch/io.h
#define PCI_DEV(SEGBUS, DEV, FN) ( \
(((SEGBUS) & 0xFFF) << 20) | \
(((DEV) & 0x1F) << 15) | \
(((FN) & 0x07) <<12))
void PrintSmiEnRegister(UINT32 Index);
void PrintSmiEnRegister (UINT32 Index);
extern STM_GUEST_CONTEXT_COMMON mGuestContextCommonSmm[];
typedef int device_t;
static UINT16 pmbase = 0x0;
static UINT16 read16(UINTN addr)
{
return *((volatile UINT16 *) (addr));
}
static void write16(UINTN addr, UINT16 Reg16)
{
*((volatile UINT16 *) (addr)) = Reg16;
}
static UINT32 read32(UINTN addr)
{
return *((volatile UINT32 *) (addr));
}
static UINT16 pcie_read_config16(device_t dev, unsigned int whereat)
{
UINTN addr;
addr = ((UINTN) mHostContextCommon.PciExpressBaseAddress) | dev | whereat;
//DEBUG((EFI_D_DEBUG, "pcie_read_config16 %x\n", addr));
return read16(addr);
}
static UINT32 pcie_read_config32(device_t dev, unsigned int whereat)
{
UINTN addr;
addr = ((UINTN) mHostContextCommon.PciExpressBaseAddress) | dev | whereat;
//DEBUG((EFI_D_DEBUG, "pcie_read_config32 %x\n", addr));
return read32(addr);
}
static void pcie_write_config16(device_t dev, unsigned int whereat, UINT16 Reg16)
{
UINTN addr;
addr = ((UINTN) mHostContextCommon.PciExpressBaseAddress) | dev | whereat;
write16(addr, Reg16);
return;
}
static device_t get_pcu_dev(void)
{
//DEBUG((EFI_D_DEBUG, "get_pcu_dev - return %x\n", PCI_DEV(0, PCU_DEV, 0)));
return PCI_DEV(0, PCU_DEV, 0);
}
UINT16 get_pmbase(void)
UINT16 get_pmbase (void)
{
if (pmbase == 0)
{
#ifdef CONFIG_PMBASE
pmbase = CONFIG_PMBASE;
DEBUG ((EFI_D_INFO,
"get_pmbase - (from CONFIG_PMBASE) set at 0x%x\n",
pmbase));
#else
#ifdef PMBASE_BIOS_RESOURCE
// find the pmbase in the BIOS resource list
STM_RSC *Resource;
@ -119,20 +61,39 @@ UINT16 get_pmbase(void)
Resource = GetStmFirstResource (
(STM_RSC *)mGuestContextCommonSmm[SMI_HANDLER].BiosHwResourceRequirementsPtr,
IO_RANGE);
if(Resource == NULL)
DEBUG((EFI_D_ERROR,
if (Resource == NULL)
DEBUG ((EFI_D_ERROR,
"get_pmbase - Error pmbase not found in resource list\n"));
else
{
pmbase = Resource->Io.Base;
DEBUG((EFI_D_INFO,
"get_pmbase - pmbase set at 0x%x\n", pmbase));
DEBUG ((EFI_D_INFO,
"get_pmbase - (from BIOS RSC) pmbase set at 0x%x\n",
pmbase));
}
}
#else
pmbase = PciExpressRead16 (PCI_EXPRESS_LIB_ADDRESS (0, 0x1f, 0, D31F0_PMBASE));
if ((pmbase & 0x1) != 0x1)
{
DEBUG((EFI_D_ERROR,
"get_pmbase - Error in pmbase value: 0x%x\n",
pmbase));
pmbase = 0;
}
pmbase &= 0xFFFC;
DEBUG ((EFI_D_INFO,
"get_pmbase - (from PCI Memory) pmbase set at 0x%x\n",
pmbase));
#endif
#endif
}
return pmbase;
}
void StartTimer(void)
void StartTimer (void)
{
UINT16 pmbase = get_pmbase();
UINT32 smi_en = IoRead32(pmbase + SMI_EN);
@ -140,66 +101,65 @@ void StartTimer(void)
smi_en |= PERIODIC_EN;
#if 0
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"StartTimer - smi_en: 0x%08lx smi_sts: 0x%08lx\n",
smi_en,
smi_sts));
#endif
IoWrite32(pmbase + SMI_STS, PERIODIC_STS);
IoWrite32(pmbase + SMI_EN, smi_en);
IoWrite32 (pmbase + SMI_STS, PERIODIC_STS);
IoWrite32 (pmbase + SMI_EN, smi_en);
}
void SetEndOfSmi(void)
void SetEndOfSmi (void)
{
UINT16 pmbase = get_pmbase();
UINT32 smi_en = IoRead32(pmbase + SMI_EN);
UINT16 pmbase = get_pmbase ();
UINT32 smi_en = IoRead32 (pmbase + SMI_EN);
smi_en |= EOS_EN; // set the bit
#if 0
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"-- SetEndOfSmi pmbase: %x smi_en: %x \n",
pmbase,
smi_en));
#endif
IoWrite32(pmbase + SMI_EN, smi_en);
IoWrite32 (pmbase + SMI_EN, smi_en);
#if 0
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"SetEndOfSmi smi_en: 0x%08lx smi_sts: 0x%08lx\n",
IoRead32(pmbase + SMI_EN),
IoRead32(pmbase + SMI_STS)));
IoRead32 (pmbase + SMI_EN),
IoRead32 (pmbase + SMI_STS)));
#endif
}
void PrintSmiEnRegister(UINT32 Index)
void PrintSmiEnRegister (UINT32 Index)
{
UINT16 pmbase = get_pmbase();
DEBUG((EFI_D_INFO,
UINT16 pmbase = get_pmbase ();
DEBUG ((EFI_D_INFO,
"%ld PrintSmiEnRegister smi_en: 0x%08x smi_sts: 0x%08x\n",
Index,
IoRead32(pmbase + SMI_EN),
IoRead32(pmbase + SMI_STS)));
IoRead32 (pmbase + SMI_EN),
IoRead32 (pmbase + SMI_STS)));
}
void AckTimer(void)
void AckTimer (void)
{
UINT16 pmbase = get_pmbase();
IoWrite32(pmbase + SMI_STS, PERIODIC_STS);
UINT16 pmbase = get_pmbase ();
IoWrite32 (pmbase + SMI_STS, PERIODIC_STS);
#if 0
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"AckTimer - smi_en: 0x%08lx smi_sts: 0x%08lx\n",
IoRead32(pmbase + SMI_EN),
IoRead32(pmbase + SMI_STS)));
IoRead32 (pmbase + SMI_EN),
IoRead32 (pmbase + SMI_STS)));
#endif
}
void StopSwTimer(void)
void StopSwTimer (void)
{
UINT16 pmbase = get_pmbase();
UINT32 smi_en = IoRead32(pmbase + SMI_EN);
UINT16 pmbase = get_pmbase ();
UINT32 smi_en = IoRead32 (pmbase + SMI_EN);
smi_en &= ~PERIODIC_EN;
IoWrite32(pmbase + SMI_EN, smi_en);
IoWrite32 (pmbase + SMI_EN, smi_en);
}
/*
@ -213,21 +173,21 @@ void StopSwTimer(void)
* 2 - Timer interrupt plus additional SMI
*/
int CheckTimerSTS(UINT32 Index)
int CheckTimerSTS (UINT32 Index)
{
UINT16 pmbase = get_pmbase();
UINT32 smi_sts = IoRead32(pmbase + SMI_STS);
UINT16 pmbase = get_pmbase ();
UINT32 smi_sts = IoRead32 (pmbase + SMI_STS);
#if 0
DEBUG((EFI_D_ERROR, "%ld CheckTimerSTS - 0x%08lx\n", Index, smi_sts));
#endif
if((smi_sts & PERIODIC_STS) == PERIODIC_STS)
if ((smi_sts & PERIODIC_STS) == PERIODIC_STS)
{
UINT32 smi_en = IoRead32(pmbase + SMI_EN);
UINT32 smi_en = IoRead32 (pmbase + SMI_EN);
UINT32 other_smi = (smi_en & smi_sts) & ~PERIODIC_STS;
if(other_smi == 0)
if (other_smi == 0)
{
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"%ld CheckTimerSTS - Timer Interrupt Detected\n",
Index,
smi_sts));
@ -235,7 +195,7 @@ int CheckTimerSTS(UINT32 Index)
}
else
{
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"%ld CheckTimerSTS - Timer + other SMI found\n",
Index,
smi_sts));
@ -245,7 +205,7 @@ int CheckTimerSTS(UINT32 Index)
else
{
#if 0
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"%ld CheckTimerSTS - No Timer Interrupt Detected\n",
Index,
smi_sts));
@ -254,36 +214,35 @@ int CheckTimerSTS(UINT32 Index)
}
}
void ClearTimerSTS()
void ClearTimerSTS ()
{
UINT16 pmbase = get_pmbase();
UINT16 pmbase = get_pmbase ();
// just want to clear the status - do not touch the rest
IoWrite32(pmbase + SMI_STS, PERIODIC_STS);
IoWrite32 (pmbase + SMI_STS, PERIODIC_STS);
}
void SetMaxSwTimerInt()
void SetMaxSwTimerInt ()
{
SetTimerRate(3);
SetTimerRate (0);
}
void SetMinSwTimerInt()
void SetMinSwTimerInt ()
{
SetTimerRate(0);
SetTimerRate (3);
}
void SetTimerRate(UINT16 value)
void SetTimerRate (UINT16 value)
{
UINT16 Reg16;
UINT16 TimeOut;
device_t PcuDev = get_pcu_dev();
if( value > 3)
if (value > 3)
{
value = 3;
}
TimeOut = (value << 0);
Reg16 = pcie_read_config16(PcuDev, D31F0_GEN_PMCON_1);
pcie_write_config16(PcuDev, D31F0_GEN_PMCON_1, Reg16|TimeOut);
Reg16 = PciExpressRead16 (PCI_EXPRESS_LIB_ADDRESS (0, 0x1f, 0, D31F0_GEN_PMCON_1));
PciExpressWrite16 (PCI_EXPRESS_LIB_ADDRESS (0, 0x1f, 0, D31F0_GEN_PMCON_1), Reg16|TimeOut);
}