diff options
-rw-r--r-- | src/soc/intel/common/block/fast_spi/Makefile.inc | 34 | ||||
-rw-r--r-- | util/cbfstool/cbfstool.c | 170 |
2 files changed, 126 insertions, 78 deletions
diff --git a/src/soc/intel/common/block/fast_spi/Makefile.inc b/src/soc/intel/common/block/fast_spi/Makefile.inc index 1237000af0..cc65e1f23e 100644 --- a/src/soc/intel/common/block/fast_spi/Makefile.inc +++ b/src/soc/intel/common/block/fast_spi/Makefile.inc @@ -67,6 +67,38 @@ $(call add_intermediate, check-fmap-16mib-crossing, $(obj)/fmap_config.h) done; \ exit $$fail -CBFSTOOL_ADD_CMD_OPTIONS += --ext-win-base $(CONFIG_EXT_BIOS_WIN_BASE) --ext-win-size $(CONFIG_EXT_BIOS_WIN_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. +# + +ifeq ($(call int-gt, $(CONFIG_ROM_SIZE) 0x1000000), 1) +DEFAULT_WINDOW_SIZE=0x1000000 +DEFAULT_WINDOW_FLASH_BASE=$(call int-subtract, $(CONFIG_ROM_SIZE) $(DEFAULT_WINDOW_SIZE)) +DEFAULT_WINDOW_MMIO_BASE=0xff000000 +EXT_WINDOW_FLASH_BASE=0 +EXT_WINDOW_SIZE=$(DEFAULT_WINDOW_FLASH_BASE) +EXT_WINDOW_MMIO_BASE=$(call int-subtract, $(call int-add, $(CONFIG_EXT_BIOS_WIN_BASE) $(CONFIG_EXT_BIOS_WIN_SIZE)) \ + $(EXT_WINDOW_SIZE)) +CBFSTOOL_ADD_CMD_OPTIONS += --mmap $(DEFAULT_WINDOW_FLASH_BASE):$(DEFAULT_WINDOW_MMIO_BASE):$(DEFAULT_WINDOW_SIZE) +CBFSTOOL_ADD_CMD_OPTIONS += --mmap $(EXT_WINDOW_FLASH_BASE):$(EXT_WINDOW_MMIO_BASE):$(EXT_WINDOW_SIZE) +endif + endif # CONFIG_FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW 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 '?': |