From 1dc188fad0c6c209a0185bae6b53d5798e7cf043 Mon Sep 17 00:00:00 2001 From: Rizwan Qureshi Date: Tue, 29 May 2018 14:48:14 +0530 Subject: cbfstool: add an option for creating a topswap bootblock Add an option '-j' which takes the size of topswap boundary. This option serves both as a bool and a size for creating a second bootblock to be used with topswap feature in Intel CPUs. '-j' is also used in conjunction with add-master-header to update the location of cbfs master header in the second bootblock. BUG=None BRANHC=None TEST=add bootblock entry to the image with -j option specifying different topswap sizes and also use the -j option for add-master-header. Change-Id: I3e455dc8b7f54e55f2229491695cf4218d9cfef8 Signed-off-by: Rizwan Qureshi Signed-off-by: Aamir Bohra Reviewed-on: https://review.coreboot.org/22537 Reviewed-by: Subrata Banik Reviewed-by: Aaron Durbin Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- util/cbfstool/cbfstool.c | 138 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 128 insertions(+), 10 deletions(-) (limited to 'util/cbfstool/cbfstool.c') diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 9b654b11b2..0544e8f2f4 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -32,6 +32,7 @@ #include "partitioned_file.h" #include #include +#include #define SECTION_WITH_FIT_TABLE "BOOTBLOCK" @@ -73,6 +74,7 @@ static struct param { uint32_t cbfsoffset_assigned; uint32_t arch; uint32_t padding; + uint32_t topswap_size; bool u64val_assigned; bool fill_partial_upward; bool fill_partial_downward; @@ -261,6 +263,56 @@ done: return ret; } +static int is_valid_topswap(void) +{ + switch (param.topswap_size) { + case (64 * KiB): + case (128 * KiB): + case (256 * KiB): + case (512 * KiB): + case (1 * MiB): + break; + default: + ERROR("Invalid topswap_size %d, topswap can be 64K|128K|256K|512K|1M\n", + param.topswap_size); + return 0; + } + return 1; +} + +static void fill_header_offset(void *location, uint32_t offset) +{ + // TODO: when we have a BE target, we'll need to store this as BE + write_le32(location, offset); +} + +static int update_master_header_loc_topswap(struct cbfs_image *image, + void *h_loc, uint32_t header_offset) +{ + struct cbfs_file *entry; + void *ts_h_loc = h_loc; + + entry = cbfs_get_entry(image, "bootblock"); + if (entry == NULL) { + ERROR("Bootblock not in ROM image?!?\n"); + return 1; + } + + /* + * Check if the existing topswap boundary matches with + * the one provided. + */ + if (param.topswap_size != ntohl(entry->len)/2) { + ERROR("Top swap boundary does not match\n"); + return 1; + } + + ts_h_loc -= param.topswap_size; + fill_header_offset(ts_h_loc, header_offset); + + return 0; +} + static int cbfs_add_master_header(void) { const char * const name = "cbfs master header"; @@ -270,6 +322,7 @@ static int cbfs_add_master_header(void) int ret = 1; size_t offset; size_t size; + void *h_loc; if (cbfs_image_from_buffer(&image, param.image_region, param.headeroffset)) { @@ -326,10 +379,18 @@ static int cbfs_add_master_header(void) buffer_get(&image.buffer); header_offset = -(buffer_size(&image.buffer) - header_offset); - // TODO: when we have a BE target, we'll need to store this as BE - *(uint32_t *)(buffer_get(&image.buffer) + - buffer_size(&image.buffer) - 4) = - swab32(htonl(header_offset)); + h_loc = (void *)(buffer_get(&image.buffer) + + buffer_size(&image.buffer) - 4); + fill_header_offset(h_loc, header_offset); + /* + * if top swap present, update the header + * location in secondary bootblock + */ + if (param.topswap_size) { + if (update_master_header_loc_topswap(&image, h_loc, + header_offset)) + return 1; + } ret = 0; @@ -339,6 +400,47 @@ done: return ret; } +static int add_topswap_bootblock(struct buffer *buffer, uint32_t *offset) +{ + size_t bb_buf_size = buffer_size(buffer); + + if (bb_buf_size > param.topswap_size) { + ERROR("Bootblock bigger than the topswap boundary\n"); + ERROR("size = %zd, ts = %d\n", bb_buf_size, + param.topswap_size); + return 1; + } + + /* + * allocate topswap_size*2 bytes for bootblock to + * accommodate the second bootblock. + */ + struct buffer new_bootblock, bb1, bb2; + if (buffer_create(&new_bootblock, 2 * param.topswap_size, + buffer->name)) + return 1; + + buffer_splice(&bb1, &new_bootblock, param.topswap_size - bb_buf_size, + bb_buf_size); + buffer_splice(&bb2, &new_bootblock, + buffer_size(&new_bootblock) - bb_buf_size, + bb_buf_size); + + /* copy to first bootblock */ + memcpy(buffer_get(&bb1), buffer_get(buffer), bb_buf_size); + /* copy to second bootblock */ + memcpy(buffer_get(&bb2), buffer_get(buffer), bb_buf_size); + + buffer_delete(buffer); + buffer_clone(buffer, &new_bootblock); + + /* update the location (offset) of bootblock in the region */ + *offset = convert_to_from_top_aligned(param.image_region, + buffer_size(buffer)); + + return 0; +} + static int cbfs_add_component(const char *filename, const char *name, uint32_t type, @@ -376,6 +478,14 @@ static int cbfs_add_component(const char *filename, return 1; } + /* + * Check if Intel CPU topswap is specified this will require a + * second bootblock to be added. + */ + if (type == CBFS_COMPONENT_BOOTBLOCK && param.topswap_size) + if (add_topswap_bootblock(&buffer, &offset)) + return 1; + struct cbfs_file *header = cbfs_create_file_header(type, buffer.size, name); @@ -444,7 +554,6 @@ static int cbfs_add_component(const char *filename, if (IS_TOP_ALIGNED_ADDRESS(offset)) offset = convert_to_from_top_aligned(param.image_region, -offset); - if (cbfs_add_entry(&image, &buffer, offset, header) != 0) { ERROR("Failed to add '%s' into ROM image.\n", filename); free(header); @@ -1174,7 +1283,7 @@ static int cbfs_truncate(void) } static const struct command commands[] = { - {"add", "H:r:f:n:t:c:b:a:p:yvA:gh?", cbfs_add, true, true}, + {"add", "H:r:f:n:t:c:b:a:p:yvA:j:gh?", cbfs_add, true, true}, {"add-flat-binary", "H:r:f:n:l:e:c:b:p:vA:gh?", cbfs_add_flat_binary, true, true}, {"add-payload", "H:r:f:n:c:b:C:I:p:vA:gh?", cbfs_add_payload, @@ -1182,7 +1291,7 @@ static const struct command commands[] = { {"add-stage", "a:H:r:f:n:t:c:b:P:S:p:yvA:gh?", cbfs_add_stage, true, true}, {"add-int", "H:r:i:n:b:vgh?", cbfs_add_integer, true, true}, - {"add-master-header", "H:r:vh?", cbfs_add_master_header, true, true}, + {"add-master-header", "H:r:vh?j:", cbfs_add_master_header, true, true}, {"compact", "r:h?", cbfs_compact, true, true}, {"copy", "r:R:h?", cbfs_copy, true, true}, {"create", "M:r:s:B:b:H:o:m:vh?", cbfs_create, true, true}, @@ -1203,6 +1312,7 @@ static struct option long_options[] = { {"bootblock", required_argument, 0, 'B' }, {"cmdline", required_argument, 0, 'C' }, {"compression", required_argument, 0, 'c' }, + {"topswap-size", required_argument, 0, 'j' }, {"empty-fits", required_argument, 0, 'x' }, {"entry-point", required_argument, 0, 'e' }, {"file", required_argument, 0, 'f' }, @@ -1303,8 +1413,11 @@ static void usage(char *name) "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] " + " [-p padding size] [-y|--xip if TYPE is FSP] \\\n" + " [-j topswap-size] (Intel CPUs only) " "Add a component\n" + " " + " -j valid size: 0x10000 0x20000 0x40000 0x80000 0x100000 \n" " add-payload [-r image,regions] -f FILE -n NAME [-A hash] \\\n" " [-c compression] [-b base-address] \\\n" " (linux specific: [-C cmdline] [-I initrd]) " @@ -1319,7 +1432,8 @@ static void usage(char *name) "Add a 32bit flat mode binary\n" " add-int [-r image,regions] -i INTEGER -n NAME [-b base] " "Add a raw 64-bit integer value\n" - " add-master-header [-r image,regions] " + " add-master-header [-r image,regions] \\ \n" + " [-j topswap-size] (Intel CPUs only) " "Add a legacy CBFS master header\n" " remove [-r image,regions] -n NAME " "Remove a component\n" @@ -1364,7 +1478,6 @@ static void usage(char *name) printf("TYPEs:\n"); print_supported_filetypes(); - printf( "\n* Note that these actions and switches are only valid when\n" " working with legacy images whose structure is described\n" @@ -1600,6 +1713,11 @@ int main(int argc, char **argv) return 1; } break; + case 'j': + param.topswap_size = strtol(optarg, NULL, 0); + if (!is_valid_topswap()) + return 1; + break; case 'v': verbose++; break; -- cgit v1.2.3