Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/79880?usp=email )
Change subject: sb/intel/common: Get memory map from SPI controller ......................................................................
sb/intel/common: Get memory map from SPI controller
Instead of always assuming that the top of a flash matches the top of 4G use the real memory map that's configured in the IFD and is reflected in the SPI registers.
One possible use case is to cleanly generate images for some hacks rather than having to apply some 'dd' trickery: e.g. on HP Sure Start a part of the flash is checked by EC.
UNTESTED. This might break some hacks people use to work around SPI locked images by modifying the IFD when booted with a recovery strap pulled. Those would also need a specifically crafted FMAP.
Signed-off-by: Arthur Heymans arthur@aheymans.xyz Change-Id: I5f31c175345ec3efab02255a7063054eb0ad29e4 --- M src/southbridge/intel/common/Kconfig.common M src/southbridge/intel/common/Makefile.inc M src/southbridge/intel/common/rcba.h A src/southbridge/intel/common/spi_memmap.c 4 files changed, 86 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/80/79880/1
diff --git a/src/southbridge/intel/common/Kconfig.common b/src/southbridge/intel/common/Kconfig.common index e138f5e..ede5c06 100644 --- a/src/southbridge/intel/common/Kconfig.common +++ b/src/southbridge/intel/common/Kconfig.common @@ -33,6 +33,12 @@ select SPI_FLASH select BOOT_DEVICE_SUPPORTS_WRITES
+config SOUTHBRIDGE_INTEL_COMMON_SPI_IFD_MMAP + def_bool y + depends on SOUTHBRIDGE_INTEL_COMMON_SPI && (!SOUTHBRIDGE_INTEL_COMMON_SPI_ICH7 || !SOUTHBRIDGE_INTEL_COMMON_SPI_SILVERMONT) + select SPI_FLASH + select X86_CUSTOM_BOOTMEDIA + config SOUTHBRIDGE_INTEL_COMMON_SPI_ICH7 def_bool n select SOUTHBRIDGE_INTEL_COMMON_SPI diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc index 2f4c777..2ad042d 100644 --- a/src/southbridge/intel/common/Makefile.inc +++ b/src/southbridge/intel/common/Makefile.inc @@ -53,3 +53,6 @@ smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_FINALIZE) += finalize.c
all-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_RTC) += rtc.c + +all-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI_IFD_MMAP) += spi_memmap.c +smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI_IFD_MMAP) += spi_memmap.c diff --git a/src/southbridge/intel/common/rcba.h b/src/southbridge/intel/common/rcba.h index 4a9847a..e079c43 100644 --- a/src/southbridge/intel/common/rcba.h +++ b/src/southbridge/intel/common/rcba.h @@ -9,6 +9,9 @@ #define RCBA 0xf0 #define RCBA_ENABLE 0x01
+/* RCBA registers */ +#define RCBA_GCS 0x4310 + #define RCBA8(x) (*((volatile u8 *)(DEFAULT_RCBA + (x)))) #define RCBA16(x) (*((volatile u16 *)(DEFAULT_RCBA + (x)))) #define RCBA32(x) (*((volatile u32 *)(DEFAULT_RCBA + (x)))) diff --git a/src/southbridge/intel/common/spi_memmap.c b/src/southbridge/intel/common/spi_memmap.c new file mode 100644 index 0000000..e29df27 --- /dev/null +++ b/src/southbridge/intel/common/spi_memmap.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <boot_device.h> +#include <device/device.h> +#include <fmap_config.h> +#include <southbridge/intel/common/rcba.h> +#include <spi_flash.h> + +/* + * The ROM is memory mapped just below 4GiB. Form a pointer for the base. + * At most 16MB is mapped. + */ +#define rom_base ((void *)(uintptr_t)(0x100000000ULL-MIN(CONFIG_ROM_SIZE, 16 * MiB))) + +#define SPIBAR_BASE 0x3800 +#define BFPR 0x0 + +union bfpr { + uint32_t raw; + struct { + uint32_t prb : 13; + uint32_t _reserved : 3; + uint32_t prl : 13; + uint32_t _reserved2: 3; + }; +}; + +static uint32_t bios_flash_base; +static uint32_t bios_size; + +static void ich_boot_device_init(struct mem_region_device *boot_dev) +{ + const uint32_t gcs = RCBA32(RCBA_GCS); + + const bool spi_boot = ((gcs >> 10) & 3) == 3; + if (!spi_boot) + return; + + const union bfpr bfpr = { .raw = RCBA32(SPIBAR_BASE + BFPR) }; + bios_flash_base = bfpr.prb << 12; + + const uint32_t bios_flash_limit = (bfpr.prl << 12) + 0xfff; + bios_size = bios_flash_limit + 1 - bios_flash_base; + /* Do some basic validation of FMAP */ + assert(FMAP_SECTION_COREBOOT_START - FMAP_SECTION_FLASH_START + + FMAP_SECTION_COREBOOT_SIZE == bios_flash_limit + 1); + + struct mem_region_device spi_boot_dev = MEM_REGION_DEV_RO_INIT(UINT32_MAX - bios_size, + bios_size); + *boot_dev = spi_boot_dev; +} + +const struct region_device *boot_device_ro(void) +{ + /* Somehow cbfstool segfaults if this variable is in .data rather than .bss */ + static struct mem_region_device boot_dev; + /* Assume a default mapping based on ROM size only. */ + struct mem_region_device default_boot_dev = MEM_REGION_DEV_RO_INIT(rom_base, CONFIG_ROM_SIZE); + boot_dev = default_boot_dev; + + ich_boot_device_init(&boot_dev); + + return &boot_dev.rdev; +} + +uint32_t spi_flash_get_mmap_windows(struct flash_mmap_window *table) +{ + table->flash_base = bios_flash_base; + table->host_base = (uint32_t)(uintptr_t)UINT32_MAX - bios_size + 1; + table->size = CONFIG_ROM_SIZE; + + return 1; +}