/* SPDX-License-Identifier: GPL-2.0-or-later */ #include <boot_device.h> #include <commonlib/region.h> #include <console/console.h> #include <fmap.h> #include <intelblocks/fast_spi.h> #include <spi_flash.h> /* * BIOS region on the flash is mapped right below 4GiB in the address * space. However, 256KiB right below 4GiB is decoded by read-only SRAM and not * boot media. * * +-----------+ 0 * | | * | | * | | * | | * | | * | | * | | * | | * +--------+ | | * | IFD | | | * bios_start +---> +--------+------------------> +-----------+ 4GiB - bios_size * ^ | | ^ | | * | | | | | | * | | | bios_mapped_size | BIOS | * | | BIOS | | | | * bios_size | | | | | * | | | v | | * | | +------------------> +-----------+ 4GiB - 256KiB * | | | | Read only | * v | | | SRAM | * bios_end +---> +--------+ +-----------+ 4GiB * | Device | * | ext | * +--------+ * */ static size_t bios_size; static struct region_device shadow_dev; static struct xlate_region_device real_dev; static struct xlate_window real_dev_window; static void bios_mmap_init(void) { size_t size, start, bios_mapped_size; uintptr_t base; size = bios_size; /* If bios_size is initialized, then bail out. */ if (size != 0) return; start = fast_spi_get_bios_region(&size); /* BIOS region is mapped right below 4G. */ base = 4ULL * GiB - size; /* * The 256 KiB right below 4G are decoded by readonly SRAM, * not boot media. */ bios_mapped_size = size - 256 * KiB; rdev_chain_mem(&shadow_dev, (void *)base, bios_mapped_size); xlate_window_init(&real_dev_window, &shadow_dev, start, bios_mapped_size); xlate_region_device_ro_init(&real_dev, 1, &real_dev_window, CONFIG_ROM_SIZE); bios_size = size; /* Check that the CBFS lies within the memory mapped area. It's too easy to forget the SRAM mapping when crafting an FMAP file. */ struct region cbfs_region; if (!fmap_locate_area("COREBOOT", &cbfs_region) && !region_is_subregion(&real_dev_window.sub_region, &cbfs_region)) printk(BIOS_CRIT, "ERROR: CBFS @ %zx size %zx exceeds mem-mapped area @ %zx size %zx\n", region_offset(&cbfs_region), region_sz(&cbfs_region), start, bios_mapped_size); } const struct region_device *boot_device_ro(void) { bios_mmap_init(); return &real_dev.rdev; } uint32_t spi_flash_get_mmap_windows(struct flash_mmap_window *table) { bios_mmap_init(); table->flash_base = region_offset(&real_dev_window.sub_region); table->host_base = (uintptr_t)rdev_mmap_full(&shadow_dev); table->size = region_sz(&real_dev_window.sub_region); return 1; }