aboutsummaryrefslogtreecommitdiff
path: root/src/soc/intel/common/block/fast_spi/mmap_boot.c
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@google.com>2020-11-22 11:37:44 -0800
committerFurquan Shaikh <furquan@google.com>2020-12-08 22:55:41 +0000
commit886f4e862a0b064d1055aeff8f621f3c5d1ce3ac (patch)
tree127fd50dd597380c6285fa1a564cb55dff0e655a /src/soc/intel/common/block/fast_spi/mmap_boot.c
parentb652aaef990cc3eb481dea7f8d4cc3eecd92ffa1 (diff)
soc/intel/common/fast_spi: Add custom boot media device
This change enables support for a custom boot media device in fast SPI controller driver if the platform supports additional decode window for mapping BIOS regions greater than 16MiB. Following new Kconfigs are added: 1. FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW: SoC can select this to indicate support for extended BIOS window. 2. EXT_BIOS_WIN_BASE: If FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW is selected, this provides the base address of the host space that is reserved for mapping the extended window. 3. EXT_BIOS_WIN_SIZE: If FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW is selected, this provides the size of the host space reserved for mapping extended window. If platform indicates support for extended BIOS decode window, cbfstool add command is provided additional parameters for the decode window using --ext-win-base and --ext-win-size. It is the responsibility of the mainboard fmap author to ensure that the sections in the BIOS region do not cross 16MiB boundary as the host space windows are not contiguous. This change adds a build time check to ensure no sections in FMAP cross the 16MiB boundary. Even though the platform supports extended window, it depends upon the size of BIOS region (which in turn depends on SPI flash size) whether and how much of the additional window is utilized at runtime. This change also provides helper functions for rest of the coreboot components to query how much of the extended window is actually utilized. BUG=b:171534504 Change-Id: I1b564aed9809cf14b40a3b8e907622266fc782e2 Signed-off-by: Furquan Shaikh <furquan@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/47659 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Diffstat (limited to 'src/soc/intel/common/block/fast_spi/mmap_boot.c')
-rw-r--r--src/soc/intel/common/block/fast_spi/mmap_boot.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/fast_spi/mmap_boot.c b/src/soc/intel/common/block/fast_spi/mmap_boot.c
new file mode 100644
index 0000000000..8435a855f5
--- /dev/null
+++ b/src/soc/intel/common/block/fast_spi/mmap_boot.c
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This file provides a custom boot media device for the platforms that support additional
+ * window for BIOS regions greater than 16MiB. If the mainboard uses a smaller BIOS region, then
+ * the additional window is unused.
+ */
+
+#include <boot_device.h>
+#include <commonlib/region.h>
+#include <console/console.h>
+#include <fmap.h>
+#include <intelblocks/fast_spi.h>
+
+enum window_type {
+ /* Fixed decode window of max 16MiB size just below 4G boundary */
+ FIXED_DECODE_WINDOW,
+ /* Additional decode window for mapping BIOS region greater than 16MiB */
+ EXT_BIOS_DECODE_WINDOW,
+ TOTAL_DECODE_WINDOWS,
+};
+
+static struct xlate_region_device real_dev;
+static struct mem_region_device shadow_devs[TOTAL_DECODE_WINDOWS];
+static struct xlate_window real_dev_windows[TOTAL_DECODE_WINDOWS];
+
+static void initialize_window(enum window_type type, uintptr_t host_base,
+ uintptr_t flash_base, size_t size)
+{
+ mem_region_device_ro_init(&shadow_devs[type], (void *)host_base, size);
+ xlate_window_init(&real_dev_windows[type], &shadow_devs[type].rdev,
+ flash_base, size);
+ printk(BIOS_INFO, "MMAP window: SPI flash base=0x%lx, Host base=0x%lx, Size=0x%zx\n",
+ flash_base, host_base, size);
+}
+
+/*
+ *
+ * +--------------+
+ * | |
+ * | |
+ * | |
+ * ^ +------------+--------------------------^--------------------------------+ 0xffffffff
+ * | | | | | |
+ * | | | | | |
+ * | | | + | FIXED |
+ * | | | fixed_win_size | DECODE |
+ * | | BIOS | + | WINDOW |
+ * + | region | | | |
+ * bios_size | (Region 1) | | | |
+ * + | | | | |
+ * | | | | | |
+ * | | | fixed_win_flash_base+----v--------------------------------+ fixed_win_host_base
+ * | | | | | |
+ * | | | | | |
+ * | | | | | Other MMIO |
+ * v | | | | |
+ * bios_start +------------+ ext_win_flash_base | | |
+ * | | + | | |
+ * | | | | | |
+ * | | | | | |
+ * | | | +-----^------------------------------------------------------------^
+ * 0 +------------+ | | | | |
+ * | + | EXT_BIOS | |
+ * SPI flash | ext_win_size | DECODE | |
+ * address | + | WINDOW | +
+ * space | | | | CONFIG_EXT_BIOS_WIN_SIZE
+ * +--------------v-------------------------------+ ext_win_host_base +
+ * | | |
+ * | Unused | |
+ * | | |
+ * +--------------+ CONFIG_EXT_BIOS_WIN_BASE+--v
+ * | |
+ * | |
+ * | |
+ * +--------------+
+ *
+ * Host address
+ * space
+ */
+static void bios_mmap_init(void)
+{
+ static bool init_done;
+
+ size_t bios_size, bios_start;
+
+ uintptr_t fixed_win_host_base, fixed_win_flash_base;
+ uintptr_t ext_win_host_base, ext_win_flash_base;
+ size_t fixed_win_size, ext_win_size;
+
+ size_t win_count = 0;
+
+ if (init_done)
+ return;
+
+ /* Read the offset and size of BIOS region in the SPI flash address space. */
+ bios_start = fast_spi_get_bios_region(&bios_size);
+
+ /*
+ * By default, fixed decode window (maximum size 16MiB) is mapped just below the 4G
+ * boundary. This window maps the top part of the BIOS region in the SPI flash address
+ * space to the host address space.
+ */
+ fixed_win_size = MIN(16 * MiB, bios_size);
+ fixed_win_host_base = 4ULL * GiB - fixed_win_size;
+ fixed_win_flash_base = bios_start + bios_size - fixed_win_size;
+
+ initialize_window(FIXED_DECODE_WINDOW, fixed_win_host_base, fixed_win_flash_base,
+ fixed_win_size);
+ win_count++;
+
+ _Static_assert(CONFIG_EXT_BIOS_WIN_BASE != 0, "Extended BIOS window base cannot be 0!");
+ _Static_assert(CONFIG_EXT_BIOS_WIN_SIZE != 0, "Extended BIOS window size cannot be 0!");
+
+ /*
+ * Remaining portion of the BIOS region up to a maximum of CONFIG_EXT_BIOS_WIN_SIZE is
+ * mapped at the top of the extended window if the BIOS region is greater than 16MiB.
+ *
+ * If the BIOS region is not greater than 16MiB, then the extended window is not
+ * enabled.
+ */
+ ext_win_size = MIN(CONFIG_EXT_BIOS_WIN_SIZE, bios_size - fixed_win_size);
+
+ if (ext_win_size) {
+ ext_win_host_base = CONFIG_EXT_BIOS_WIN_BASE + CONFIG_EXT_BIOS_WIN_SIZE -
+ ext_win_size;
+ ext_win_flash_base = fixed_win_flash_base - ext_win_size;
+ initialize_window(EXT_BIOS_DECODE_WINDOW, ext_win_host_base,
+ ext_win_flash_base, ext_win_size);
+ win_count++;
+ }
+
+ xlate_region_device_ro_init(&real_dev, win_count, real_dev_windows, CONFIG_ROM_SIZE);
+
+ init_done = true;
+}
+
+const struct region_device *boot_device_ro(void)
+{
+ bios_mmap_init();
+
+ return &real_dev.rdev;
+}
+
+void fast_spi_get_ext_bios_window(uintptr_t *base, size_t *size)
+{
+ const struct region_device *rd = &shadow_devs[EXT_BIOS_DECODE_WINDOW].rdev;
+
+ bios_mmap_init();
+
+ *size = region_device_sz(rd);
+
+ if (*size == 0) {
+ *base = 0;
+ } else {
+ /*
+ * This is a memory region device. So, mmap returns the base address of the
+ * device. Also, as this is a memory region device, unmap is a no-op.
+ */
+ *base = (uintptr_t)rdev_mmap_full(rd);
+ }
+}