util/ifittool: Add an option to set the FIT pointer a CBFS file
The purpose of this is to eventually move the FIT table out of the bootblock, generate it separately as a cbfs file and then have the FIT pointer point to that cbfs file. TESTED: extracted a FIT table using dd, added it as a cbfs file and see that the FIT pointer correctly points to it. Also test that trying to add a non valid FIT cbfs file results in an error. Change-Id: I6e38b7df31e6b30f75b0ae57a5332f386e00f16b Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Reviewed-on: https://review.coreboot.org/c/coreboot/+/50925 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com> Reviewed-by: Christian Walter <christian.walter@9elements.com>
This commit is contained in:
parent
6ca3375c08
commit
e9e4e54e27
|
@ -519,6 +519,40 @@ int fit_add_microcode_file(struct fit_table *fit,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t *get_fit_ptr(struct buffer *bootblock, fit_offset_converter_t offset_fn,
|
||||||
|
uint32_t topswap_size)
|
||||||
|
{
|
||||||
|
return rom_buffer_pointer(bootblock,
|
||||||
|
ptr_to_offset(offset_fn, bootblock,
|
||||||
|
FIT_POINTER_LOCATION - topswap_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the FIT pointer to a FIT table. */
|
||||||
|
int set_fit_pointer(struct buffer *bootblock,
|
||||||
|
const uint32_t fit_address,
|
||||||
|
fit_offset_converter_t offset_fn,
|
||||||
|
uint32_t topswap_size)
|
||||||
|
{
|
||||||
|
struct fit_table *fit;
|
||||||
|
uint32_t *fit_pointer = get_fit_ptr(bootblock, offset_fn, topswap_size);
|
||||||
|
|
||||||
|
fit = rom_buffer_pointer(bootblock, ptr_to_offset(offset_fn, bootblock, fit_address));
|
||||||
|
|
||||||
|
if (fit_address < FIT_TABLE_LOWEST_ADDRESS) {
|
||||||
|
ERROR("FIT must be reside in the top 16MiB.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fit_table_verified(fit)) {
|
||||||
|
ERROR("FIT not found at address.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fit_pointer[0] = fit_address;
|
||||||
|
fit_pointer[1] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a pointer to the active FIT.
|
* Return a pointer to the active FIT.
|
||||||
*/
|
*/
|
||||||
|
@ -527,11 +561,7 @@ struct fit_table *fit_get_table(struct buffer *bootblock,
|
||||||
uint32_t topswap_size)
|
uint32_t topswap_size)
|
||||||
{
|
{
|
||||||
struct fit_table *fit;
|
struct fit_table *fit;
|
||||||
uint32_t *fit_pointer;
|
uint32_t *fit_pointer = get_fit_ptr(bootblock, offset_fn, 0);
|
||||||
|
|
||||||
fit_pointer = rom_buffer_pointer(bootblock,
|
|
||||||
ptr_to_offset(offset_fn, bootblock,
|
|
||||||
FIT_POINTER_LOCATION));
|
|
||||||
|
|
||||||
/* Ensure pointer is below 4GiB and within 16MiB of 4GiB */
|
/* Ensure pointer is below 4GiB and within 16MiB of 4GiB */
|
||||||
if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) {
|
if (fit_pointer[1] != 0 || fit_pointer[0] < FIT_TABLE_LOWEST_ADDRESS) {
|
||||||
|
|
|
@ -57,5 +57,6 @@ int fit_add_microcode_file(struct fit_table *fit,
|
||||||
const char *blob_name,
|
const char *blob_name,
|
||||||
fit_offset_converter_t offset_helper,
|
fit_offset_converter_t offset_helper,
|
||||||
const size_t max_fit_entries);
|
const size_t max_fit_entries);
|
||||||
|
int set_fit_pointer(struct buffer *bootblock, const uint32_t offset,
|
||||||
|
fit_offset_converter_t offset_fn, uint32_t topswap_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,23 +15,24 @@
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
partitioned_file_t *image_file;
|
partitioned_file_t *image_file;
|
||||||
|
|
||||||
static const char *optstring = "H:j:f:r:d:t:n:s:cAaDvh?";
|
static const char *optstring = "H:j:f:r:d:t:n:s:cAaDvhF?";
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"file", required_argument, 0, 'f' },
|
{"file", required_argument, 0, 'f' },
|
||||||
{"region", required_argument, 0, 'r' },
|
{"region", required_argument, 0, 'r' },
|
||||||
{"add-cbfs-entry", no_argument, 0, 'a' },
|
{"add-cbfs-entry", no_argument, 0, 'a' },
|
||||||
{"add-region", no_argument, 0, 'A' },
|
{"add-region", no_argument, 0, 'A' },
|
||||||
{"del-entry", required_argument, 0, 'd' },
|
{"del-entry", required_argument, 0, 'd' },
|
||||||
{"clear-table", no_argument, 0, 'c' },
|
{"clear-table", no_argument, 0, 'c' },
|
||||||
{"fit-type", required_argument, 0, 't' },
|
{"set-fit-pointer", no_argument, 0, 'F' },
|
||||||
{"cbfs-filename", required_argument, 0, 'n' },
|
{"fit-type", required_argument, 0, 't' },
|
||||||
{"max-table-size", required_argument, 0, 's' },
|
{"cbfs-filename", required_argument, 0, 'n' },
|
||||||
{"topswap-size", required_argument, 0, 'j' },
|
{"max-table-size", required_argument, 0, 's' },
|
||||||
{"dump", no_argument, 0, 'D' },
|
{"topswap-size", required_argument, 0, 'j' },
|
||||||
{"verbose", no_argument, 0, 'v' },
|
{"dump", no_argument, 0, 'D' },
|
||||||
{"help", no_argument, 0, 'h' },
|
{"verbose", no_argument, 0, 'v' },
|
||||||
{"header-offset", required_argument, 0, 'H' },
|
{"help", no_argument, 0, 'h' },
|
||||||
{NULL, 0, 0, 0 }
|
{"header-offset", required_argument, 0, 'H' },
|
||||||
|
{NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
|
@ -43,6 +44,7 @@ static void usage(const char *name)
|
||||||
"\t\t-a|--add-entry : Add a CBFS file as new entry to FIT\n"
|
"\t\t-a|--add-entry : Add a CBFS file as new entry to FIT\n"
|
||||||
"\t\t-A|--add-region : Add region as new entry to FIT (for microcodes)\n"
|
"\t\t-A|--add-region : Add region as new entry to FIT (for microcodes)\n"
|
||||||
"\t\t-d|--del-entry number : Delete existing <number> entry\n"
|
"\t\t-d|--del-entry number : Delete existing <number> entry\n"
|
||||||
|
"\t\t-F|--set-fit-pointer : Set the FIT pointer to a CBFS file\n"
|
||||||
"\t\t-t|--fit-type : Type of new entry\n"
|
"\t\t-t|--fit-type : Type of new entry\n"
|
||||||
"\t\t-n|--name : The CBFS filename or region to add to table\n"
|
"\t\t-n|--name : The CBFS filename or region to add to table\n"
|
||||||
"\tOPTIONAL ARGUMENTS:\n"
|
"\tOPTIONAL ARGUMENTS:\n"
|
||||||
|
@ -127,7 +129,8 @@ enum fit_operation {
|
||||||
NO_OP = 0,
|
NO_OP = 0,
|
||||||
ADD_CBFS_OP,
|
ADD_CBFS_OP,
|
||||||
ADD_REGI_OP,
|
ADD_REGI_OP,
|
||||||
DEL_OP
|
DEL_OP,
|
||||||
|
SET_FIT_PTR_OP
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -199,6 +202,14 @@ int main(int argc, char *argv[])
|
||||||
case 'f':
|
case 'f':
|
||||||
input_file = optarg;
|
input_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'F':
|
||||||
|
if (op != NO_OP) {
|
||||||
|
ERROR("specified multiple actions at once\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
op = SET_FIT_PTR_OP;
|
||||||
|
break;
|
||||||
case 'H':
|
case 'H':
|
||||||
headeroffset = strtoul(optarg, &suffix, 0);
|
headeroffset = strtoul(optarg, &suffix, 0);
|
||||||
if (!*optarg || (suffix && *suffix)) {
|
if (!*optarg || (suffix && *suffix)) {
|
||||||
|
@ -253,6 +264,14 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op == SET_FIT_PTR_OP) {
|
||||||
|
if (name == NULL) {
|
||||||
|
ERROR("Adding FIT entry, but no name set\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!region_name) {
|
if (!region_name) {
|
||||||
ERROR("Region not given\n");
|
ERROR("Region not given\n");
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
@ -281,13 +300,14 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fit_table *fit = fit_get_table(&bootblock,
|
struct fit_table *fit = NULL;
|
||||||
convert_to_from_top_aligned,
|
if (op != SET_FIT_PTR_OP) {
|
||||||
topswap_size);
|
fit = fit_get_table(&bootblock, convert_to_from_top_aligned, topswap_size);
|
||||||
if (!fit) {
|
if (!fit) {
|
||||||
partitioned_file_close(image_file);
|
partitioned_file_close(image_file);
|
||||||
ERROR("FIT not found.\n");
|
ERROR("FIT not found.\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clear_table) {
|
if (clear_table) {
|
||||||
|
@ -352,6 +372,30 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SET_FIT_PTR_OP:
|
||||||
|
{
|
||||||
|
uint32_t fit_address;
|
||||||
|
struct cbfs_file *cbfs_file = cbfs_get_entry(&image, name);
|
||||||
|
if (!cbfs_file) {
|
||||||
|
partitioned_file_close(image_file);
|
||||||
|
ERROR("%s not found in CBFS.\n", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fit_address = offset_to_ptr(convert_to_from_top_aligned, &image.buffer,
|
||||||
|
cbfs_get_entry_addr(&image, cbfs_file)
|
||||||
|
+ ntohl(cbfs_file->offset));
|
||||||
|
|
||||||
|
|
||||||
|
if (set_fit_pointer(&bootblock, fit_address, convert_to_from_top_aligned,
|
||||||
|
topswap_size)) {
|
||||||
|
partitioned_file_close(image_file);
|
||||||
|
ERROR("%s is not a FIT table\n", name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fit = fit_get_table(&bootblock, convert_to_from_top_aligned, topswap_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DEL_OP:
|
case DEL_OP:
|
||||||
{
|
{
|
||||||
if (fit_delete_entry(fit, table_entry)) {
|
if (fit_delete_entry(fit, table_entry)) {
|
||||||
|
|
Loading…
Reference in New Issue