summaryrefslogtreecommitdiff
path: root/util/cbfstool
diff options
context:
space:
mode:
Diffstat (limited to 'util/cbfstool')
-rw-r--r--util/cbfstool/cbfstool.c101
1 files changed, 93 insertions, 8 deletions
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index eca9bcc2bf..57c9e5117f 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -94,6 +94,18 @@ static struct param {
char *initrd;
char *cmdline;
int force;
+ /*
+ * Base and size of extended window for decoding SPI flash greater than 16MiB in host
+ * address space on x86 platforms. 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.
+ */
+ uint32_t ext_win_base;
+ uint32_t ext_win_size;
} param = {
/* All variables not listed are initialized as zero. */
.arch = CBFS_ARCHITECTURE_UNKNOWN,
@@ -125,6 +137,8 @@ struct mmap_window {
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,
};
@@ -145,25 +159,72 @@ static void add_mmap_window(enum mmap_window_type idx, size_t flash_offset, size
mmap_window_table[idx].host_space.size = window_size;
}
-static void create_mmap_windows(void)
+#define DEFAULT_DECODE_WINDOW_TOP (4ULL * GiB)
+#define DEFAULT_DECODE_WINDOW_MAX_SIZE (16 * MiB)
+
+static bool create_mmap_windows(void)
{
static bool done;
if (done)
- return;
+ return done;
const size_t image_size = partitioned_file_total_size(param.image_file);
- const size_t window_size = MIN(16 * MiB, 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, image_size - window_size,
- 4ULL * GiB - window_size, window_size);
+ 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.
+ */
+ 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;
+ }
+ }
done = true;
+ return done;
}
static unsigned int convert_address(const struct region *to, const struct region *from,
@@ -250,7 +311,7 @@ static unsigned int convert_addr_space(const struct buffer *region, unsigned int
{
assert(region);
- create_mmap_windows();
+ assert(create_mmap_windows());
if (IS_HOST_SPACE_ADDRESS(addr))
return convert_host_to_flash(region, addr);
@@ -1431,6 +1492,8 @@ enum {
/* begin after ASCII characters */
LONGOPT_START = 256,
LONGOPT_IBB = LONGOPT_START,
+ LONGOPT_EXT_WIN_BASE,
+ LONGOPT_EXT_WIN_SIZE,
LONGOPT_END,
};
@@ -1474,6 +1537,8 @@ 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 },
{NULL, 0, 0, 0 }
};
@@ -1576,11 +1641,16 @@ static void usage(char *name)
" -U Unprocessed; don't decompress or make ELF\n"
" -v Provide verbose output\n"
" -h Display this help message\n\n"
+ " --ext-win-base Base of extended decode window in host address\n"
+ " space(x86 only)\n"
+ " --ext-win-size Size of extended decode window in host address\n"
+ " space(x86 only)\n"
"COMMANDs:\n"
" add [-r image,regions] -f FILE -n NAME -t TYPE [-A hash] \\\n"
" [-c compression] [-b base-address | -a alignment] \\\n"
" [-p padding size] [-y|--xip if TYPE is FSP] \\\n"
- " [-j topswap-size] (Intel CPUs only) [--ibb] "
+ " [-j topswap-size] (Intel CPUs only) [--ibb] \\\n"
+ " [--ext-win-base win-base --ext-win-size win-size] "
"Add a component\n"
" "
" -j valid size: 0x10000 0x20000 0x40000 0x80000 0x100000 \n"
@@ -1591,7 +1661,8 @@ static void usage(char *name)
" add-stage [-r image,regions] -f FILE -n NAME [-A hash] \\\n"
" [-c compression] [-b base] [-S section-to-ignore] \\\n"
" [-a alignment] [-P page-size] [-Q|--pow2page] \\\n"
- " [-y|--xip] [--ibb] "
+ " [-y|--xip] [--ibb] \\\n"
+ " [--ext-win-base win-base --ext-win-size win-size] "
"Add a stage to the ROM\n"
" add-flat-binary [-r image,regions] -f FILE -n NAME \\\n"
" [-A hash] -l load-address -e entry-point \\\n"
@@ -1920,6 +1991,20 @@ 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);
+ return 1;
+ }
+ break;
case 'h':
case '?':
usage(argv[0]);