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 <rizwan.qureshi@intel.com>
Signed-off-by: Aamir Bohra <aamir.bohra@intel.com>
Reviewed-on: https://review.coreboot.org/22537
Reviewed-by: Subrata Banik <subrata.banik@intel.com>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Rizwan Qureshi 2018-05-29 14:48:14 +05:30 committed by Subrata Banik
parent 4f16049f17
commit 1dc188fad0
1 changed files with 128 additions and 10 deletions

View File

@ -32,6 +32,7 @@
#include "partitioned_file.h"
#include <commonlib/fsp.h>
#include <commonlib/endian.h>
#include <commonlib/helpers.h>
#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;