diff --git a/.gitignore b/.gitignore index deb81882de7..a456dca8db3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ payloads/external/U-Boot/u-boot/ payloads/external/Memtest86Plus/memtest86plus/ payloads/external/iPXE/ipxe/ payloads/external/sortbootorder/sortbootorder +payloads/external/skl/secure-kernel-loader/ util/crossgcc/acpica-unix-*/ util/crossgcc/binutils-*/ util/crossgcc/build-*BINUTILS/ diff --git a/configs/config.pcengines_apu2_drtm_payload b/configs/config.pcengines_apu2_drtm_payload new file mode 100644 index 00000000000..9cdec2c00ef --- /dev/null +++ b/configs/config.pcengines_apu2_drtm_payload @@ -0,0 +1,27 @@ +CONFIG_LOCALVERSION="v4.9.0.4" +CONFIG_VENDOR_PCENGINES=y +CONFIG_FMDFILE="$(top)/src/mainboard/$(CONFIG_MAINBOARD_DIR)/board.fmd" +CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x20000 +CONFIG_BOARD_PCENGINES_APU2=y +CONFIG_BOTTOMIO_POSITION=0xD0000000 +CONFIG_UART_PCI_ADDR=0x0 +CONFIG_LAUNCH_DRTM_PAYLOAD=y +CONFIG_HUDSON_SATA_MODE=2 +CONFIG_AGESA_BINARY_PI_LOCATION=0xFFE00000 +CONFIG_NO_GFX_INIT=y +CONFIG_SUBSYSTEM_VENDOR_ID=0x0000 +CONFIG_SUBSYSTEM_DEVICE_ID=0x0000 +CONFIG_I2C_TRANSFER_TIMEOUT_US=500000 +CONFIG_SMMSTORE_V2=y +CONFIG_SMMSTORE_SIZE=0x40000 +CONFIG_TPM2=y +CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y +CONFIG_POST_IO_PORT=0x80 +CONFIG_PAYLOAD_TIANOCORE=y +CONFIG_TIANOCORE_CUSTOM=y +CONFIG_TIANOCORE_REPOSITORY="https://github.com/3mdeb/edk2" +CONFIG_TIANOCORE_TAG_OR_REV="origin/drtm_payload" +CONFIG_TIANOCORE_DEBUG=y +CONFIG_TIANOCORE_CUSTOM_BUILD_PARAMS="-DSECURE_BOOT_ENABLE -DNETWORK_ENABLE -DSHELL_TYPE=BUILD_SHELL -DSERIAL_TERMINAL=TRUE" +CONFIG_SORTBOOTORDER_SECONDARY_PAYLOAD=y +CONFIG_SORTBOOTORDER_MASTER=y diff --git a/payloads/external/Makefile.inc b/payloads/external/Makefile.inc index 7873c071de3..265b8c26960 100644 --- a/payloads/external/Makefile.inc +++ b/payloads/external/Makefile.inc @@ -475,3 +475,14 @@ doom.wad-file := $(strip $(CONFIG_COREDOOM_WAD_FILE)) doom.wad-type := raw doom.wad-compression := $(CBFS_SECONDARY_PAYLOAD_COMPRESS_FLAG) endif + +# SKL + +payloads/external/skl/secure-kernel-loader/skl.bin: + $(MAKE) -C payloads/external/skl CC="$(HOSTCC)" + +cbfs-files-$(CONFIG_LAUNCH_DRTM_PAYLOAD) += $(CONFIG_CBFS_PREFIX)/drtm_payload +$(CONFIG_CBFS_PREFIX)/drtm_payload-file := payloads/external/skl/secure-kernel-loader/skl.bin +$(CONFIG_CBFS_PREFIX)/drtm_payload-type := raw +$(CONFIG_CBFS_PREFIX)/drtm_payload-compression := $(CBFS_PAYLOAD_COMPRESS_FLAG) +$(CONFIG_CBFS_PREFIX)/drtm_payload-options := $(ADDITIONAL_PAYLOAD_CONFIG) diff --git a/payloads/external/skl/Makefile b/payloads/external/skl/Makefile new file mode 100644 index 00000000000..2ae018fbd6d --- /dev/null +++ b/payloads/external/skl/Makefile @@ -0,0 +1,20 @@ +## SPDX-License-Identifier: GPL-2.0-only +project_git_repo=https://github.com/TrenchBoot/secure-kernel-loader.git +project_dir=secure-kernel-loader + +all: skl + +checkout: + test -d $(project_dir) || \ + git clone $(project_git_repo) $(project_dir) + +skl: checkout + $(MAKE) -C $(project_dir) DEBUG=y + +clean: + test -d $(project_dir) && $(MAKE) -C $(project_dir) clean || exit 0 + +distclean: + rm -rf $(project_dir) + +.PHONY: checkout skl clean distclean diff --git a/src/cpu/amd/pi/00730F01/model_16_init.c b/src/cpu/amd/pi/00730F01/model_16_init.c index 1a9a2e3a639..dd568f9d915 100644 --- a/src/cpu/amd/pi/00730F01/model_16_init.c +++ b/src/cpu/amd/pi/00730F01/model_16_init.c @@ -43,10 +43,12 @@ static void model_16_init(struct device *dev) msr.hi &= ~(1 << (46 - 32)); wrmsr(NB_CFG_MSR, msr); - /* Write protect SMM space with SMMLOCK. */ - msr = rdmsr(HWCR_MSR); - msr.lo |= (1 << 0); - wrmsr(HWCR_MSR, msr); + /* Write protect SMM space with SMMLOCK, or let SMI handler do it if any. */ + if (!CONFIG(HAVE_SMI_HANDLER)) { + msr = rdmsr(HWCR_MSR); + msr.lo |= (1 << 0); + wrmsr(HWCR_MSR, msr); + } amd_update_microcode_from_cbfs(); diff --git a/src/cpu/amd/pi/Kconfig b/src/cpu/amd/pi/Kconfig index 2336d68f968..e457b64cbca 100644 --- a/src/cpu/amd/pi/Kconfig +++ b/src/cpu/amd/pi/Kconfig @@ -10,7 +10,11 @@ config CPU_AMD_PI select UDELAY_LAPIC select LAPIC_MONOTONIC_TIMER select SPI_FLASH if HAVE_ACPI_RESUME - select NO_SMM + select SMM_TSEG + select PARALLEL_MP_AP_WORK + select SOC_AMD_COMMON_BLOCK_SMM + select SOC_AMD_COMMON_BLOCK_SMI + select SOC_AMD_COMMON_BLOCK_ACPI select SSE2 if CPU_AMD_PI @@ -35,6 +39,21 @@ config DCACHE_BSP_STACK_SIZE hex default 0x4000 +config SMM_MODULE_STACK_SIZE + default 0x800 + +config SMM_TSEG_SIZE + default 0x100000 if HAVE_SMI_HANDLER + default 0 + +config LAUNCH_DRTM_PAYLOAD + bool "Launch DRTM payload before the real one" + default n + depends on MEMORY_MAPPED_TPM + help + Launch DRTM payload before the real one. This makes it possible to + put root of trust in hardware for platforms that don't support SRTM. + endif # CPU_AMD_PI source "src/cpu/amd/pi/00730F01/Kconfig" diff --git a/src/cpu/amd/pi/Makefile.inc b/src/cpu/amd/pi/Makefile.inc index ae042532150..bb7d09b3ad1 100644 --- a/src/cpu/amd/pi/Makefile.inc +++ b/src/cpu/amd/pi/Makefile.inc @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only subdirs-$(CONFIG_CPU_AMD_PI_00730F01) += 00730F01 + +ramstage-$(CONFIG_LAUNCH_DRTM_PAYLOAD) += skinit.c diff --git a/src/cpu/amd/pi/skinit.c b/src/cpu/amd/pi/skinit.c new file mode 100644 index 00000000000..cb36d10bbf3 --- /dev/null +++ b/src/cpu/amd/pi/skinit.c @@ -0,0 +1,145 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +#include + +static uintptr_t payload_start, payload_size; + +/* For SELF, prog->start and prog->size are not set so obtain it differently. */ +void platform_segment_loaded(uintptr_t start, size_t size, int flags) +{ + /* FIXME: need to differentiate between payload and other loaded segments */ + if (/*payload_start != 0 || payload_size != 0 || */flags != SEG_FINAL) + die("ELF payload must have only one loadable segment for DRTM!\n"); + + payload_start = start; + payload_size = size; +} + +/* TODO: include tags.h from SKL somehow */ +#define SKL_TAG_CLASS_MASK 0xF0 + +/* Tags with no particular class */ +#define SKL_TAG_NO_CLASS 0x00 +#define SKL_TAG_END 0x00 +#define SKL_TAG_SETUP_INDIRECT 0x01 +#define SKL_TAG_TAGS_SIZE 0x0F /* Always first */ + +/* Tags specifying kernel type */ +#define SKL_TAG_BOOT_CLASS 0x10 +#define SKL_TAG_BOOT_LINUX 0x10 +#define SKL_TAG_BOOT_MB2 0x11 +#define SKL_TAG_BOOT_SIMPLE 0x12 + +struct skl_tag_hdr { + uint8_t type; + uint8_t len; +} __packed; + +struct skl_tag_tags_size { + struct skl_tag_hdr hdr; + uint16_t size; +} __packed; + +struct skl_tag_boot_simple_payload { + struct skl_tag_hdr hdr; + uint32_t base; + uint32_t size; + uint32_t entry; + uint32_t arg; +} __packed; + +struct skl_tag_evtlog { + struct skl_tag_hdr hdr; + uint32_t address; + uint32_t size; +} __packed; + +struct skl_tag_hash { + struct skl_tag_hdr hdr; + uint16_t algo_id; + uint8_t digest[]; +} __packed; + +static inline void *next_tag(void* t) +{ + void *x = t + ((struct skl_tag_hdr*)t)->len; + return x; +} + +void platform_prog_run(struct prog *prog) +{ + void *skl = NULL; + uint16_t bootloader_data_offset; + struct skl_tag_tags_size *tags; + struct skl_tag_boot_simple_payload *sp; + struct skl_tag_hdr *end; + + /* + * Check if we're on 32b platform. + * TODO: add support for 64b? + */ + assert(sizeof(skl) == 4); + + hexdump(prog, sizeof(*prog)); + + /* + * APs have to be in wait-for-SIPI state for at least 1000 cycles before + * SKINIT. Send INIT now and assume that loading SKL from CBFS is long + * enough. + */ + lapic_send_ipi_others(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT); + + skl = memalign(64*KiB, 64*KiB); + + cbfs_load(CONFIG_CBFS_PREFIX "/drtm_payload", skl, 64*KiB); + + bootloader_data_offset = ((uint16_t *)skl)[1]; + tags = (struct skl_tag_tags_size *)(skl + bootloader_data_offset); + + memset(tags, 0, 64*KiB - (skl - (void *)tags)); + + tags->hdr.type = SKL_TAG_TAGS_SIZE; + tags->hdr.len = sizeof(struct skl_tag_tags_size); + tags->size += tags->hdr.len; + + sp = next_tag(tags); + sp->hdr.type = SKL_TAG_BOOT_SIMPLE; + sp->hdr.len = sizeof(struct skl_tag_boot_simple_payload); + sp->base = payload_start; + sp->size = payload_size; + sp->entry = (uint32_t)prog->entry; + sp->arg = (uint32_t)prog->arg; + tags->size += sp->hdr.len; + + /* TODO: DRTM TPM event log and SKL hash(es) */ + + end = next_tag(sp); + end->type = SKL_TAG_END; + end->len = sizeof(struct skl_tag_hdr); + tags->size += end->len; + + msr_t msr; + + msr = rdmsr(SMM_BASE_MSR); + printk(BIOS_DEBUG, "SMM_BASE_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + msr = rdmsr(SMM_ADDR_MSR); + printk(BIOS_DEBUG, "SMM_ADDR_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + msr = rdmsr(SMM_MASK_MSR); + printk(BIOS_DEBUG, "SMM_MASK_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + msr = rdmsr(HWCR_MSR); + printk(BIOS_DEBUG, "HWCR_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + tis_close(); + + asm volatile ("skinit" :: "a"(skl)); +} diff --git a/src/cpu/x86/lapic/Makefile.inc b/src/cpu/x86/lapic/Makefile.inc index 91a41f76a59..d457b35182e 100644 --- a/src/cpu/x86/lapic/Makefile.inc +++ b/src/cpu/x86/lapic/Makefile.inc @@ -6,6 +6,9 @@ bootblock-$(CONFIG_UDELAY_LAPIC) += apic_timer.c romstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c ramstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c postcar-$(CONFIG_UDELAY_LAPIC) += apic_timer.c +# Use TSC for SMM, should be safer than LAPIC after OS takes over +smm-$(CONFIG_UDELAY_LAPIC) += ../tsc/delay_tsc.c + bootblock-y += boot_cpu.c verstage_x86-y += boot_cpu.c romstage-y += boot_cpu.c diff --git a/src/cpu/x86/tsc/delay_tsc.c b/src/cpu/x86/tsc/delay_tsc.c index 9607c2c6eb2..0a4b554c9ac 100644 --- a/src/cpu/x86/tsc/delay_tsc.c +++ b/src/cpu/x86/tsc/delay_tsc.c @@ -29,7 +29,7 @@ void udelay(unsigned int us) } } -#if CONFIG(TSC_MONOTONIC_TIMER) +#if CONFIG(TSC_MONOTONIC_TIMER) || (CONFIG(LAPIC_MONOTONIC_TIMER) && ENV_SMM) #include static struct monotonic_counter { diff --git a/src/drivers/uart/uart8250io.c b/src/drivers/uart/uart8250io.c index d8955779eeb..8dd7b773533 100644 --- a/src/drivers/uart/uart8250io.c +++ b/src/drivers/uart/uart8250io.c @@ -89,6 +89,8 @@ uintptr_t uart_platform_base(unsigned int idx) return 0; } +__weak int check_com2(void) { return 0; } + void uart_init(unsigned int idx) { if (!CONFIG(DRIVERS_UART_8250IO_SKIP_INIT)) { diff --git a/src/mainboard/pcengines/apu2/Kconfig b/src/mainboard/pcengines/apu2/Kconfig index 1316a90f93d..f2c733d8fbe 100644 --- a/src/mainboard/pcengines/apu2/Kconfig +++ b/src/mainboard/pcengines/apu2/Kconfig @@ -23,6 +23,7 @@ config BOARD_SPECIFIC_OPTIONS select PCIEXP_CLK_PM select PCIEXP_COMMON_CLOCK select PCIEXP_L1_SUB_STATE + select HAVE_SMI_HANDLER config MAINBOARD_DIR default "pcengines/apu2" diff --git a/src/mainboard/pcengines/apu2/bios_knobs.c b/src/mainboard/pcengines/apu2/bios_knobs.c index 5ae0da8e3a5..736ccaed091 100644 --- a/src/mainboard/pcengines/apu2/bios_knobs.c +++ b/src/mainboard/pcengines/apu2/bios_knobs.c @@ -98,6 +98,9 @@ static u8 check_knob_value(const char *s) u8 check_iommu(void) { + if (CONFIG(LAUNCH_DRTM_PAYLOAD)) + return 1; + u8 iommu; iommu = check_knob_value("iommu"); diff --git a/src/mainboard/pcengines/apu2/board.fmd b/src/mainboard/pcengines/apu2/board.fmd index 0f344e580ca..8e46bcc74b6 100644 --- a/src/mainboard/pcengines/apu2/board.fmd +++ b/src/mainboard/pcengines/apu2/board.fmd @@ -2,8 +2,8 @@ FLASH 8M { SI_BIOS@0x0 0x800000 { BOOTORDER(PRESERVE)@0x0 0x1000 RW_VPD(PRESERVE)@0x1000 0x4000 - SMMSTORE(PRESERVE)@0x5000 0x20000 - RW_UNUSED@0x25000 0x1db000 + SMMSTORE(PRESERVE)@0x10000 0x40000 + RW_UNUSED@0x50000 0x1b0000 WP_RO@0x200000 0x600000{ RO_VPD(PRESERVE)@0x0 0x4000 RO_SECTION@0x4000 0x5fc000{ diff --git a/src/northbridge/amd/pi/00730F01/northbridge.c b/src/northbridge/amd/pi/00730F01/northbridge.c index 6c3d214aaaa..7942cd1697d 100644 --- a/src/northbridge/amd/pi/00730F01/northbridge.c +++ b/src/northbridge/amd/pi/00730F01/northbridge.c @@ -28,6 +28,8 @@ #include "mainboard/pcengines/apu2/bios_knobs.h" +#include + #define MAX_NODE_NUMS MAX_NODES #define PCIE_CAP_AER BIT(5) #define PCIE_CAP_ACS BIT(6) @@ -982,6 +984,9 @@ static int get_cpu_count(void) static const struct mp_ops mp_ops = { .pre_mp_init = pre_mp_init, .get_cpu_count = get_cpu_count, + .relocation_handler = smm_relocation_handler, + .get_smm_info = get_smm_info, + .post_mp_init = global_smi_enable, }; void mp_init_cpus(struct bus *cpu_bus) diff --git a/src/northbridge/amd/pi/00730F01/state_machine.c b/src/northbridge/amd/pi/00730F01/state_machine.c index 9215f7a86b3..7f20387d65e 100644 --- a/src/northbridge/amd/pi/00730F01/state_machine.c +++ b/src/northbridge/amd/pi/00730F01/state_machine.c @@ -32,9 +32,9 @@ void platform_AfterInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) * UMA may or may not be cacheable, so Sub4GCacheTop could be * higher than UmaBase. With UMA_NONE we see UmaBase==0. */ if (Post->MemConfig.UmaBase) - backup_top_of_low_cacheable(Post->MemConfig.UmaBase << 16); + backup_top_of_low_cacheable((Post->MemConfig.UmaBase << 16) - CONFIG_SMM_TSEG_SIZE); else - backup_top_of_low_cacheable(Post->MemConfig.Sub4GCacheTop); + backup_top_of_low_cacheable(Post->MemConfig.Sub4GCacheTop - CONFIG_SMM_TSEG_SIZE); } void platform_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) diff --git a/src/southbridge/amd/pi/hudson/Makefile.inc b/src/southbridge/amd/pi/hudson/Makefile.inc index c3e9c76988d..aef5e8e4fb3 100644 --- a/src/southbridge/amd/pi/hudson/Makefile.inc +++ b/src/southbridge/amd/pi/hudson/Makefile.inc @@ -56,6 +56,7 @@ all-y += reset.c smm-y += smihandler.c smm-y += smi_util.c +smm-y += lpc_simpledev.c # ROMSIG At ROMBASE + 0x20000: # +-----------+---------------+----------------+------------+ diff --git a/src/southbridge/amd/pi/hudson/hudson.c b/src/southbridge/amd/pi/hudson/hudson.c index e9b26e0ad0d..4367d344513 100644 --- a/src/southbridge/amd/pi/hudson/hudson.c +++ b/src/southbridge/amd/pi/hudson/hudson.c @@ -17,13 +17,6 @@ #include "smi.h" #include "fchec.h" -int acpi_get_sleep_type(void) -{ - u16 tmp = inw(ACPI_PM1_CNT_BLK); - tmp = ((tmp & (7 << 10)) >> 10); - return (int)tmp; -} - void hudson_enable(struct device *dev) { printk(BIOS_DEBUG, "%s()\n", __func__); diff --git a/src/southbridge/amd/pi/hudson/lpc_simpledev.c b/src/southbridge/amd/pi/hudson/lpc_simpledev.c new file mode 100644 index 00000000000..7feedd27229 --- /dev/null +++ b/src/southbridge/amd/pi/hudson/lpc_simpledev.c @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include + +#include "hudson.h" +#include "pci_devs.h" + +uintptr_t lpc_get_spibase(void) +{ + u32 base; + + base = pci_read_config32(PCI_DEV(0, LPC_DEV, LPC_FUNC), + SPIROM_BASE_ADDRESS_REGISTER); + base &= 0xffffffc0; + return (uintptr_t)base; +} diff --git a/src/southbridge/amd/pi/hudson/smi.c b/src/southbridge/amd/pi/hudson/smi.c index 560b66679b5..193e64d2c84 100644 --- a/src/southbridge/amd/pi/hudson/smi.c +++ b/src/southbridge/amd/pi/hudson/smi.c @@ -4,16 +4,11 @@ * Utilities for SMM setup */ -#include +#include #include -#include "smi.h" - -/** Set the EOS bit and enable SMI generation from southbridge */ -void global_smi_enable(void) +void smm_region(uintptr_t *start, size_t *size) { - uint32_t reg = smi_read32(SMI_REG_SMITRIG0); - reg &= ~SMITRG0_SMIENB; /* Enable SMI generation */ - reg |= SMITRG0_EOS; /* Set EOS bit */ - smi_write32(SMI_REG_SMITRIG0, reg); + *start = (uintptr_t)cbmem_top(); + *size = CONFIG_SMM_TSEG_SIZE; } diff --git a/src/southbridge/amd/pi/hudson/smihandler.c b/src/southbridge/amd/pi/hudson/smihandler.c index a942c24adae..34105603db7 100644 --- a/src/southbridge/amd/pi/hudson/smihandler.c +++ b/src/southbridge/amd/pi/hudson/smihandler.c @@ -4,130 +4,36 @@ * SMI handler for Hudson southbridges */ -#include +#include +#include +#include #include #include -#include "hudson.h" -#include "smi.h" - -#define SMI_0x88_ACPI_COMMAND (1 << 11) - -enum smi_source { - SMI_SOURCE_SCI = (1 << 0), - SMI_SOURCE_GPE = (1 << 1), - SMI_SOURCE_0x84 = (1 << 2), - SMI_SOURCE_0x88 = (1 << 3), - SMI_SOURCE_IRQ_TRAP = (1 << 4), - SMI_SOURCE_0x90 = (1 << 5) -}; - -static void hudson_apmc_smi_handler(void) +static void fch_apmc_smi_handler(void) { - u32 reg32; - const uint8_t cmd = inb(ACPI_SMI_CTL_PORT); + const uint8_t cmd = inb(pm_acpi_smi_cmd_port()); switch (cmd) { - case ACPI_SMI_CMD_ENABLE: - reg32 = inl(ACPI_PM1_CNT_BLK); - reg32 |= (1 << 0); /* SCI_EN */ - outl(reg32, ACPI_PM1_CNT_BLK); - break; - case ACPI_SMI_CMD_DISABLE: - reg32 = inl(ACPI_PM1_CNT_BLK); - reg32 &= ~(1 << 0); /* clear SCI_EN */ - outl(ACPI_PM1_CNT_BLK, reg32); + case APM_CNT_SMMSTORE: + if (CONFIG(SMMSTORE)) + handle_smi_store(); break; } mainboard_smi_apmc(cmd); } -int southbridge_io_trap_handler(int smif) -{ - return 0; -} - -static void process_smi_sci(void) -{ - const uint32_t status = smi_read32(0x10); - - /* Clear events to prevent re-entering SMI if event isn't handled */ - smi_write32(0x10, status); -} - -static void process_gpe_smi(void) -{ - const uint32_t status = smi_read32(0x80); - const uint32_t gevent_mask = (1 << 24) - 1; - - /* Only Bits [23:0] indicate GEVENT SMIs. */ - if (status & gevent_mask) { - /* A GEVENT SMI occurred */ - mainboard_smi_gpi(status & gevent_mask); - } - - /* Clear events to prevent re-entering SMI if event isn't handled */ - smi_write32(0x80, status); -} - -static void process_smi_0x84(void) -{ - const uint32_t status = smi_read32(0x84); - - /* Clear events to prevent re-entering SMI if event isn't handled */ - smi_write32(0x84, status); -} - -static void process_smi_0x88(void) -{ - const uint32_t status = smi_read32(0x88); - - if (status & SMI_0x88_ACPI_COMMAND) { - /* Command received via ACPI SMI command port */ - hudson_apmc_smi_handler(); - } - /* Clear events to prevent re-entering SMI if event isn't handled */ - smi_write32(0x88, status); -} - -static void process_smi_0x8c(void) -{ - const uint32_t status = smi_read32(0x8c); - - /* Clear events to prevent re-entering SMI if event isn't handled */ - smi_write32(0x8c, status); -} - -static void process_smi_0x90(void) -{ - const uint32_t status = smi_read32(0x90); - - /* Clear events to prevent re-entering SMI if event isn't handled */ - smi_write32(0x90, status); -} +static const struct smi_sources_t smi_sources[] = { + { .type = SMITYPE_SMI_CMD_PORT, .handler = fch_apmc_smi_handler }, +}; -void southbridge_smi_handler(void) +void *get_smi_source_handler(int source) { - const uint16_t smi_src = smi_read16(0x94); - - if (smi_src & SMI_SOURCE_SCI) - process_smi_sci(); - if (smi_src & SMI_SOURCE_GPE) - process_gpe_smi(); - if (smi_src & SMI_SOURCE_0x84) - process_smi_0x84(); - if (smi_src & SMI_SOURCE_0x88) - process_smi_0x88(); - if (smi_src & SMI_SOURCE_IRQ_TRAP) - process_smi_0x8c(); - if (smi_src & SMI_SOURCE_0x90) - process_smi_0x90(); -} + size_t i; -void southbridge_smi_set_eos(void) -{ - uint32_t reg = smi_read32(SMI_REG_SMITRIG0); - reg |= SMITRG0_EOS; - smi_write32(SMI_REG_SMITRIG0, reg); + for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++) + if (smi_sources[i].type == source) + return smi_sources[i].handler; + return NULL; } diff --git a/src/southbridge/amd/pi/hudson/soc/acpi.h b/src/southbridge/amd/pi/hudson/soc/acpi.h new file mode 100644 index 00000000000..80fcc9921ec --- /dev/null +++ b/src/southbridge/amd/pi/hudson/soc/acpi.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_ACPI_H +#define SOC_ACPI_H + +#endif /* SOC_ACPI_H */ diff --git a/src/southbridge/amd/pi/hudson/soc/nvs.h b/src/southbridge/amd/pi/hudson/soc/nvs.h new file mode 100644 index 00000000000..c4db17e8db7 --- /dev/null +++ b/src/southbridge/amd/pi/hudson/soc/nvs.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_NVS_H +#define SOC_NVS_H + +struct __packed global_nvs { + // TODO + uint8_t rsv0; + uint8_t rsv1; + uint8_t rsv2; + uint32_t rsv3; + uint64_t pm1i; /* 0x07 - 0x0e - System Wake Source - PM1 Index */ + uint64_t gpei; /* 0x0f - 0x16 - GPE Wake Source */ + uint8_t rsv4; + uint8_t rsv5; + uint8_t rsv6; +}; + +#endif /* SOC_NVS_H */ diff --git a/src/southbridge/amd/pi/hudson/soc/smi.h b/src/southbridge/amd/pi/hudson/soc/smi.h index da5ddbc2f73..0ee3721c0f4 100644 --- a/src/southbridge/amd/pi/hudson/soc/smi.h +++ b/src/southbridge/amd/pi/hudson/soc/smi.h @@ -3,9 +3,43 @@ #ifndef SOC_SMI_H #define SOC_SMI_H +/* TODO: include Fch.h and use macros from there? */ + +#define SCI_GPES 32 +#define SCIMAPS 64 +#define SMI_GEVENTS 24 +#define NUMBER_SMITYPES 160 + +#define SMITYPE_SMI_CMD_PORT 0x4b + +#define SMI_EVENT_STATUS 0x00 #define SMI_SCI_TRIG 0x08 #define SMI_SCI_LEVEL 0x0c #define SMI_SCI_STATUS 0x10 #define SMI_SCI_EN 0x14 +#define SMI_SCI_MAP0 0x40 +#define SMI_SCI_MAP(X) (SMI_SCI_MAP0 + (X)) + +#define SMI_REG_SMISTS0 0x80 +#define GEVENT_MASK 0x00ffffff +#define SMI_REG_SMISTS1 0x84 +#define SMI_REG_SMISTS2 0x88 +#define SMI_REG_SMISTS3 0x8c +#define SMI_REG_SMISTS4 0x90 + +#define SMI_REG_POINTER 0x94 +#define SMI_STATUS_SRC_SCI (1 << 0) +#define SMI_STATUS_SRC_0 (1 << 1) +#define SMI_STATUS_SRC_1 (1 << 2) +#define SMI_STATUS_SRC_2 (1 << 3) +#define SMI_STATUS_SRC_3 (1 << 4) +#define SMI_STATUS_SRC_4 (1 << 5) + +#define SMI_REG_SMITRIG0 0x98 +#define SMITRG0_SMIENB (1 << 31) +#define SMITRG0_EOS (1 << 28) + +#define SMI_REG_CONTROL0 0xa0 + #endif /* SOC_SMI_H */ diff --git a/src/southbridge/amd/pi/hudson/soc/southbridge.h b/src/southbridge/amd/pi/hudson/soc/southbridge.h new file mode 100644 index 00000000000..bea21c50e38 --- /dev/null +++ b/src/southbridge/amd/pi/hudson/soc/southbridge.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_SOUTHBRIDGE_H +#define SOC_SOUTHBRIDGE_H + +#define PM1_LIMIT 16 +#define GPE0_LIMIT 32 +#define TOTAL_BITS(a) (8 * sizeof(a)) + +#define PM_ACPI_SMI_CMD 0x6a + +#define PWRBTN_STS (1 << 8) +#define RTC_STS (1 << 10) +#define PCIEXPWAK_STS (1 << 14) +#define WAK_STS (1 << 15) + +#endif /* SOC_SOUTHBRIDGE_H */ diff --git a/src/vendorcode/amd/pi/Makefile.inc b/src/vendorcode/amd/pi/Makefile.inc index 5b8d041afc2..9dcb6075d34 100644 --- a/src/vendorcode/amd/pi/Makefile.inc +++ b/src/vendorcode/amd/pi/Makefile.inc @@ -75,6 +75,7 @@ CC_bootblock := $(CC_bootblock) $(AGESA_INC) $(AGESA_CFLAGS) CC_romstage := $(CC_romstage) $(AGESA_INC) $(AGESA_CFLAGS) CC_postcar:= $(CC_postcar) -I$(src)/southbridge/amd/pi/hudson -I$(AGESA_ROOT)/binaryPI CC_ramstage := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) +CC_smm := $(CC_ramstage) $(AGESA_INC) $(AGESA_CFLAGS) CC_x86_32 := $(CC_x86_32) $(AGESA_INC) $(AGESA_CFLAGS) CC_x86_64 := $(CC_x86_64) $(AGESA_INC) $(AGESA_CFLAGS)