From 34a7e66faa46ec3ddf3d2346b00c91e3c0547012 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Thu, 6 Oct 2022 09:42:15 +0200 Subject: util/cbfstool: Add a new mechanism to provide a memory map This replaces the mechanism with --ext-win-base --ext-win-size with a more generic mechanism where cbfstool can be provided with an arbitrary memory map. This will be useful for AMD platforms with flash sizes larger than 16M where only the lower 16M half gets memory mapped below 4G. Also on Intel system the IFD allows for a memory map where the "top of flash" != "below 4G". This is for instance the case by default on Intel APL. TEST: google/brya build for chromeos which used --ext-win-base remains the same after this change with BUILD_TIMELESS=1. Change-Id: I38ab4c369704497f711e14ecda3ff3a8cdc0d089 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/c/coreboot/+/68160 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- util/cbfstool/cbfstool.c | 170 ++++++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 77 deletions(-) (limited to 'util/cbfstool') diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index d26c418612..2dcc9d1cb6 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -317,28 +317,68 @@ struct mmap_window { struct region host_space; }; -enum mmap_window_type { - X86_DEFAULT_DECODE_WINDOW, /* Decode window just below 4G boundary */ - X86_EXTENDED_DECODE_WINDOW, /* Extended decode window for mapping greater than 16MiB - flash */ - MMAP_MAX_WINDOWS, -}; +/* Should be enough for now */ +#define MMAP_MAX_WINDOWS 3 /* Table of all the decode windows supported by the platform. */ +static int mmap_window_table_size; 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, +static void add_mmap_window(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); + if (mmap_window_table_size >= MMAP_MAX_WINDOWS) { + ERROR("Too many memory map windows\n"); 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; + mmap_window_table[mmap_window_table_size].flash_space.offset = flash_offset; + mmap_window_table[mmap_window_table_size].host_space.offset = host_offset; + mmap_window_table[mmap_window_table_size].flash_space.size = window_size; + mmap_window_table[mmap_window_table_size].host_space.size = window_size; + mmap_window_table_size++; +} + + +static int decode_mmap_arg(char *optarg) +{ + if (optarg == NULL) + return 1; + + union { + unsigned long int array[3]; + struct { + unsigned long int flash_base; + unsigned long int mmap_base; + unsigned long int mmap_size; + }; + } mmap_args; + char *suffix = NULL; + char *substring = strtok(optarg, ":"); + for (size_t i = 0; i < ARRAY_SIZE(mmap_args.array); i++) { + if (!substring) { + ERROR("Invalid mmap arguments '%s'.\n", + optarg); + return 1; + } + mmap_args.array[i] = strtol(substring, &suffix, 0); + if (suffix && *suffix) { + ERROR("Invalid mmap arguments '%s'.\n", + optarg); + return 1; + } + substring = strtok(NULL, ":"); + } + + if (substring != NULL) { + ERROR("Invalid argument, too many substrings '%s'.\n", + optarg); + + return 1; + } + + add_mmap_window(mmap_args.flash_base, mmap_args.mmap_base, mmap_args.mmap_size); + return 0; } #define DEFAULT_DECODE_WINDOW_TOP (4ULL * GiB) @@ -351,57 +391,45 @@ static bool create_mmap_windows(void) if (done) return done; - const size_t image_size = partitioned_file_total_size(param.image_file); - const size_t std_window_size = MIN(DEFAULT_DECODE_WINDOW_MAX_SIZE, image_size); - const size_t std_window_flash_offset = image_size - std_window_size; + // No memory map provided, use a default one + if (mmap_window_table_size == 0) { + const size_t image_size = partitioned_file_total_size(param.image_file); + printf("Image SIZE %lu\n", image_size); + const size_t std_window_size = MIN(DEFAULT_DECODE_WINDOW_MAX_SIZE, image_size); + const size_t std_window_flash_offset = image_size - std_window_size; - /* - * Default decode window lives just below 4G boundary in host space and maps up to a - * maximum of 16MiB. If the window is smaller than 16MiB, the SPI flash window is mapped - * at the top of the host window just below 4G. - */ - add_mmap_window(X86_DEFAULT_DECODE_WINDOW, std_window_flash_offset, - DEFAULT_DECODE_WINDOW_TOP - std_window_size, std_window_size); - - if (param.ext_win_size && (image_size > DEFAULT_DECODE_WINDOW_MAX_SIZE)) { /* - * If the platform supports extended window and the SPI flash size is greater - * than 16MiB, then create a mapping for the extended window as well. - * The assumptions here are: - * 1. Top 16MiB is still decoded in the fixed decode window just below 4G - * boundary. - * 2. Rest of the SPI flash below the top 16MiB is mapped at the top of extended - * window. Even though the platform might support a larger extended window, the - * SPI flash part used by the mainboard might not be large enough to be mapped - * in the entire window. In such cases, the mapping is assumed to be in the top - * part of the extended window with the bottom part remaining unused. - * - * Example: - * ext_win_base = 0xF8000000 - * ext_win_size = 32 * MiB - * ext_win_limit = ext_win_base + ext_win_size - 1 = 0xF9FFFFFF - * - * If SPI flash is 32MiB, then top 16MiB is mapped from 0xFF000000 - 0xFFFFFFFF - * whereas the bottom 16MiB is mapped from 0xF9000000 - 0xF9FFFFFF. The extended - * window 0xF8000000 - 0xF8FFFFFF remains unused. + * Default decode window lives just below 4G boundary in host space and maps up to a + * maximum of 16MiB. If the window is smaller than 16MiB, the SPI flash window is mapped + * at the top of the host window just below 4G. */ - const size_t ext_window_mapped_size = MIN(param.ext_win_size, - image_size - std_window_size); - const size_t ext_window_top = param.ext_win_base + param.ext_win_size; - add_mmap_window(X86_EXTENDED_DECODE_WINDOW, - std_window_flash_offset - ext_window_mapped_size, - ext_window_top - ext_window_mapped_size, - ext_window_mapped_size); - - if (region_overlap(&mmap_window_table[X86_EXTENDED_DECODE_WINDOW].host_space, - &mmap_window_table[X86_DEFAULT_DECODE_WINDOW].host_space)) { - const struct region *ext_region; - - ext_region = &mmap_window_table[X86_EXTENDED_DECODE_WINDOW].host_space; - ERROR("Extended window(base=0x%zx, limit=0x%zx) overlaps with default window!\n", - region_offset(ext_region), region_end(ext_region)); - - return false; + add_mmap_window(std_window_flash_offset, DEFAULT_DECODE_WINDOW_TOP - std_window_size, std_window_size); + } else { + /* + * Check provided memory map + */ + for (int i = 0; i < mmap_window_table_size; i++) { + for (int j = i + 1; j < mmap_window_table_size; j++) { + if (region_overlap(&mmap_window_table[i].flash_space, + &mmap_window_table[j].flash_space)) { + ERROR("Flash space windows (base=0x%zx, limit=0x%zx) and (base=0x%zx, limit=0x%zx) overlap!\n", + region_offset(&mmap_window_table[i].flash_space), + region_end(&mmap_window_table[i].flash_space), + region_offset(&mmap_window_table[j].flash_space), + region_end(&mmap_window_table[j].flash_space)); + return false; + } + + if (region_overlap(&mmap_window_table[i].host_space, + &mmap_window_table[j].host_space)) { + ERROR("Host space windows (base=0x%zx, limit=0x%zx) and (base=0x%zx, limit=0x%zx) overlap!\n", + region_offset(&mmap_window_table[i].flash_space), + region_end(&mmap_window_table[i].flash_space), + region_offset(&mmap_window_table[j].flash_space), + region_end(&mmap_window_table[j].flash_space)); + return false; + } + } } } @@ -1777,8 +1805,7 @@ enum { /* begin after ASCII characters */ LONGOPT_START = 256, LONGOPT_IBB = LONGOPT_START, - LONGOPT_EXT_WIN_BASE, - LONGOPT_EXT_WIN_SIZE, + LONGOPT_MMAP, LONGOPT_END, }; @@ -1820,8 +1847,7 @@ static struct option long_options[] = { {"mach-parseable",no_argument, 0, 'k' }, {"unprocessed", no_argument, 0, 'U' }, {"ibb", no_argument, 0, LONGOPT_IBB }, - {"ext-win-base", required_argument, 0, LONGOPT_EXT_WIN_BASE }, - {"ext-win-size", required_argument, 0, LONGOPT_EXT_WIN_SIZE }, + {"mmap", required_argument, 0, LONGOPT_MMAP }, {NULL, 0, 0, 0 } }; @@ -2262,19 +2288,9 @@ int main(int argc, char **argv) case LONGOPT_IBB: param.ibb = true; break; - case LONGOPT_EXT_WIN_BASE: - param.ext_win_base = strtoul(optarg, &suffix, 0); - if (!*optarg || (suffix && *suffix)) { - ERROR("Invalid ext window base '%s'.\n", optarg); - return 1; - } - break; - case LONGOPT_EXT_WIN_SIZE: - param.ext_win_size = strtoul(optarg, &suffix, 0); - if (!*optarg || (suffix && *suffix)) { - ERROR("Invalid ext window size '%s'.\n", optarg); + case LONGOPT_MMAP: + if (decode_mmap_arg(optarg)) return 1; - } break; case 'h': case '?': -- cgit v1.2.3