Furquan Shaikh has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/47831 )
Change subject: util/cbfstool: Introduce concept of mmap_window ......................................................................
util/cbfstool: Introduce concept of mmap_window
This change adds the concept of mmap_window to describe how the SPI flash address space is mapped to host address space. It gets rid of the assumption that the SPI flash address space is mapped only below the 4G boundary in host space. This is required in follow up changes to be able to add more decode windows for the SPI flash into the host address space.
Currently, a single mmap window is added i.e. the default x86 decode window of maximum 16MiB size living just below the 4G boundary.
Change-Id: I8dd3d1c922cc834c1e67f279ffce8fa438d8209c Signed-off-by: Furquan Shaikh furquan@google.com --- M util/cbfstool/cbfstool.c 1 file changed, 125 insertions(+), 15 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/31/47831/1
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 061ff82..08d3cd0 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -17,6 +17,7 @@ #include <commonlib/fsp.h> #include <commonlib/endian.h> #include <commonlib/helpers.h> +#include <commonlib/region.h>
#define SECTION_WITH_FIT_TABLE "BOOTBLOCK"
@@ -107,18 +108,130 @@ CBFS_FILE_MAGIC, strlen(CBFS_FILE_MAGIC)); }
-/* - * Converts between offsets from the start of the specified image region and - * "top-aligned" offsets from the top of the entire boot media. - */ -static unsigned convert_to_from_absolute_top_aligned( - const struct buffer *region, unsigned offset) +/* This describes a window from the SPI flash address space into the host address space. */ +struct mmap_window { + struct region flash_space; + struct region host_space; +}; + +enum mmap_window_type { + X86_DEFAULT_DECODE_WINDOW, /* Decode window just below 4G boundary */ + MMAP_MAX_WINDOWS, +}; + +/* Table of all the decode windows supported by the platform. */ +static struct mmap_window mmap_window_table[MMAP_MAX_WINDOWS]; + +static void add_mmap_window(enum mmap_window_type idx, size_t flash_offset, size_t host_offset, + size_t window_size) +{ + if (idx >= MMAP_MAX_WINDOWS) { + ERROR("Incorrect mmap window index(%d)\n", idx); + return; + } + + mmap_window_table[idx].flash_space.offset = flash_offset; + mmap_window_table[idx].host_space.offset = host_offset; + mmap_window_table[idx].flash_space.size = window_size; + mmap_window_table[idx].host_space.size = window_size; +} + +static void create_mmap_windows(void) +{ + static bool done; + + if (done) + return; + + const size_t image_size = partitioned_file_total_size(param.image_file); + const size_t window_size = MIN(16 * MiB, image_size); + + /* + * Default decode window lives just below 4G boundary in host space and maps upto a + * maximum of 16MiB. + */ + add_mmap_window(X86_DEFAULT_DECODE_WINDOW, image_size - window_size, + 4ULL * GiB - window_size, window_size); + + done = true; +} + +static unsigned convert_address(const struct region *to, const struct region *from, + unsigned addr) +{ + /* + * Calculate the offset in the "from" region and use that offset to calculate + * corresponding address in the "to" region. + */ + size_t offset = addr - region_offset(from); + return region_offset(to) + offset; +} + +static int find_mmap_window(size_t struct_offset, unsigned addr) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(mmap_window_table); i++) { + const struct region *reg; + reg = (struct region *)((char *)&mmap_window_table[i] + struct_offset); + if (region_offset(reg) <= addr && region_end(reg) >= addr) + return i; + } + + return -1; +} + +static unsigned convert_host_to_flash(const struct buffer *region, unsigned addr) +{ + int idx; + const struct region *to, *from; + + idx = find_mmap_window(offsetof(struct mmap_window, host_space), addr); + if (idx == -1) { + ERROR("Host address(%x) not in any mmap window!\n", addr); + return 0; + } + + to = &mmap_window_table[idx].flash_space; + from = &mmap_window_table[idx].host_space; + + /* region->offset is subtracted because caller expects offset in the given region. */ + return convert_address(to, from, addr) - region->offset; +} + +static unsigned convert_flash_to_host(const struct buffer *region, unsigned addr) +{ + int idx; + const struct region *to, *from; + + /* + * region->offset is added because caller provides offset in the given region. This is + * converted to an absolute address in the SPI flash space. + */ + addr += region->offset; + idx = find_mmap_window(offsetof(struct mmap_window, flash_space), addr); + + if (idx == -1) { + ERROR("SPI flash address(%x) not in any mmap window!\n", addr); + return 0; + } + + to = &mmap_window_table[idx].host_space; + from = &mmap_window_table[idx].flash_space; + + return convert_address(to, from, addr); +} + +static unsigned convert_addr_space(const struct buffer *region, unsigned addr) { assert(region);
- size_t image_size = partitioned_file_total_size(param.image_file); + create_mmap_windows();
- return image_size - region->offset - offset; + if (IS_HOST_SPACE_ADDRESS(addr)) + return convert_host_to_flash(region, addr); + else + return convert_flash_to_host(region, addr); }
/* @@ -564,8 +677,8 @@ }
if (IS_HOST_SPACE_ADDRESS(offset)) - offset = convert_to_from_absolute_top_aligned(param.image_region, - -offset); + offset = convert_addr_space(param.image_region, offset); + if (cbfs_add_entry(&image, &buffer, offset, header, len_align) != 0) { ERROR("Failed to add '%s' into ROM image.\n", filename); free(header); @@ -647,8 +760,7 @@ */ if (param.stage_xip) { if (!IS_HOST_SPACE_ADDRESS(address)) - address = -convert_to_from_absolute_top_aligned( - param.image_region, address); + address = convert_addr_space(param.image_region, address); } else { if (param.baseaddress_assigned == 0) { INFO("Honoring pre-linked FSP module.\n"); @@ -721,9 +833,7 @@ * x86 semantics about the boot media being directly mapped * below 4GiB in the CPU address space. **/ - address = -convert_to_from_absolute_top_aligned( - param.image_region, address); - *offset = address; + *offset = convert_addr_space(param.image_region, address);
ret = parse_elf_to_xip_stage(buffer, &output, offset, param.ignore_section);