util/cbfstool: Add support for mapping extended window for x86 platforms

All x86 platforms until now have memory mapped up to a maximum of
16MiB of SPI flash just below 4G boundary in host address space. For
newer platforms, cbfstool needs to be able to accommodate additional
windows in the host address space for mapping SPI flash size greater
than 16MiB.

This change adds two input parameters to cbfstool ext-win-base and
ext-win-size which a platform can use to provide the details of the
extended window in host address space. The extended window does not
necessarily have to be contiguous with the standard decode window
below 4G. But, it is left upto the platform to ensure that the fmap
sections are defined such that they do not cross the window boundary.

create_mmap_windows() uses the input parameters from the platform for
the extended window and the flash size to determine if extended mmap
window is used. If the entire window in host address space is not
covered by the SPI flash region below the top 16MiB, then mapping is
assumed to be done at the top of the extended window in host space.

BUG=b:171534504

Change-Id: Ie8f95993e9c690e34b0e8e792f9881c81459c6b6
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/47882
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Furquan Shaikh 2020-11-21 10:35:10 -08:00
parent 0dcc0662f3
commit 0ae389cb23
1 changed files with 93 additions and 8 deletions

View File

@ -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]);