tools: mkfwumdata: add support for metadata version 2

Add support for generating the FWU metadata version 2. The tool now
requires the version to be provided as a command-line option. Make
corresponding changes to the tool's manpage.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Tested-by: Michal Simek <michal.simek@amd.com>
This commit is contained in:
Sughosh Ganu 2024-03-22 16:27:28 +05:30 committed by Tom Rini
parent 7cfe0d8a48
commit df42d68496
2 changed files with 127 additions and 30 deletions

View file

@ -6,6 +6,7 @@ mkfwumdata \- create FWU metadata image
. .
.SH SYNOPSIS .SH SYNOPSIS
.SY mkfwumdata .SY mkfwumdata
.OP \-v version
.OP \-a activeidx .OP \-a activeidx
.OP \-p previousidx .OP \-p previousidx
.OP \-g .OP \-g
@ -28,6 +29,12 @@ creates metadata info to be used with FWU.
Print usage information and exit. Print usage information and exit.
. .
.TP .TP
.B \-v
Set
.IR version
as the metadata version to generate. Valid values 1 or 2.
.
.TP
.B \-a .B \-a
Set Set
.IR activeidx .IR activeidx
@ -81,7 +88,7 @@ Create a metadata image with 2 banks and 1 image/bank, BankAct=0, BankPrev=1:
.EX .EX
.in +4 .in +4
$ \c $ \c
.B mkfwumdata \-a 0 \-p 1 \-b 2 \-i 1 \\\\\& .B mkfwumdata \-v 2 \-a 0 \-p 1 \-b 2 \-i 1 \\\\\&
.in +6 .in +6
.B 17e86d77-41f9-4fd7-87ec-a55df9842de5,\\\\\& .B 17e86d77-41f9-4fd7-87ec-a55df9842de5,\\\\\&
.B 10c36d7d-ca52-b843-b7b9-f9d6c501d108,\\\\\& .B 10c36d7d-ca52-b843-b7b9-f9d6c501d108,\\\\\&

View file

@ -10,28 +10,35 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <u-boot/crc.h>
#include <unistd.h> #include <unistd.h>
#include <generated/autoconf.h>
#include <u-boot/crc.h>
#include <uuid/uuid.h> #include <uuid/uuid.h>
/* This will dynamically allocate the fwu_mdata */
#define CONFIG_FWU_NUM_BANKS 0
#define CONFIG_FWU_NUM_IMAGES_PER_BANK 0
/* Since we can not include fwu.h, redefine version here. */
#define FWU_MDATA_VERSION 1
typedef uint8_t u8; typedef uint8_t u8;
typedef int16_t s16; typedef int16_t s16;
typedef uint16_t u16; typedef uint16_t u16;
typedef uint32_t u32; typedef uint32_t u32;
typedef uint64_t u64; typedef uint64_t u64;
#undef CONFIG_FWU_NUM_BANKS
#undef CONFIG_FWU_NUM_IMAGES_PER_BANK
/* This will dynamically allocate the fwu_mdata */
#define CONFIG_FWU_NUM_BANKS 0
#define CONFIG_FWU_NUM_IMAGES_PER_BANK 0
/* version 2 supports maximum of 4 banks */
#define MAX_BANKS_V2 4
#define BANK_INVALID (u8)0xFF
#define BANK_ACCEPTED (u8)0xFC
#include <fwu_mdata.h> #include <fwu_mdata.h>
/* TODO: Endianness conversion may be required for some arch. */ /* TODO: Endianness conversion may be required for some arch. */
static const char *opts_short = "b:i:a:p:gh"; static const char *opts_short = "b:i:a:p:v:gh";
static struct option options[] = { static struct option options[] = {
{"banks", required_argument, NULL, 'b'}, {"banks", required_argument, NULL, 'b'},
@ -39,6 +46,7 @@ static struct option options[] = {
{"guid", required_argument, NULL, 'g'}, {"guid", required_argument, NULL, 'g'},
{"active-bank", required_argument, NULL, 'a'}, {"active-bank", required_argument, NULL, 'a'},
{"previous-bank", required_argument, NULL, 'p'}, {"previous-bank", required_argument, NULL, 'p'},
{"version", required_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0},
}; };
@ -49,6 +57,7 @@ static void print_usage(void)
fprintf(stderr, "Options:\n" fprintf(stderr, "Options:\n"
"\t-i, --images <num> Number of images (mandatory)\n" "\t-i, --images <num> Number of images (mandatory)\n"
"\t-b, --banks <num> Number of banks (mandatory)\n" "\t-b, --banks <num> Number of banks (mandatory)\n"
"\t-v, --version Metadata version (mandatory)\n"
"\t-a, --active-bank <num> Active bank (default=0)\n" "\t-a, --active-bank <num> Active bank (default=0)\n"
"\t-p, --previous-bank <num> Previous active bank (default=active_bank - 1)\n" "\t-p, --previous-bank <num> Previous active bank (default=active_bank - 1)\n"
"\t-g, --guid Use GUID instead of UUID\n" "\t-g, --guid Use GUID instead of UUID\n"
@ -70,13 +79,26 @@ struct fwu_mdata_object {
size_t images; size_t images;
size_t banks; size_t banks;
size_t size; size_t size;
u8 version;
struct fwu_mdata *mdata; struct fwu_mdata *mdata;
}; };
static int previous_bank, active_bank; static int previous_bank, active_bank;
static bool __use_guid; static bool __use_guid;
static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) static bool supported_mdata_version(unsigned long version)
{
switch (version) {
case 1:
case 2:
return true;
default:
return false;
}
}
static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks,
u8 version)
{ {
struct fwu_mdata_object *mobj; struct fwu_mdata_object *mobj;
@ -84,11 +106,20 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks)
if (!mobj) if (!mobj)
return NULL; return NULL;
mobj->size = sizeof(struct fwu_mdata) + if (version == 1) {
(sizeof(struct fwu_image_entry) + mobj->size = sizeof(struct fwu_mdata) +
sizeof(struct fwu_image_bank_info) * banks) * images; (sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * banks) * images;
} else {
mobj->size = sizeof(struct fwu_mdata) +
sizeof(struct fwu_fw_store_desc) +
(sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * banks) * images;
}
mobj->images = images; mobj->images = images;
mobj->banks = banks; mobj->banks = banks;
mobj->version = version;
mobj->mdata = calloc(1, mobj->size); mobj->mdata = calloc(1, mobj->size);
if (!mobj->mdata) { if (!mobj->mdata) {
@ -104,9 +135,18 @@ fwu_get_image(struct fwu_mdata_object *mobj, size_t idx)
{ {
size_t offset; size_t offset;
offset = sizeof(struct fwu_mdata) + if (mobj->version == 1) {
(sizeof(struct fwu_image_entry) + offset = sizeof(struct fwu_mdata) +
sizeof(struct fwu_image_bank_info) * mobj->banks) * idx; (sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * mobj->banks) *
idx;
} else {
offset = sizeof(struct fwu_mdata) +
sizeof(struct fwu_fw_store_desc) +
(sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * mobj->banks) *
idx;
}
return (struct fwu_image_entry *)((char *)mobj->mdata + offset); return (struct fwu_image_entry *)((char *)mobj->mdata + offset);
} }
@ -116,11 +156,20 @@ fwu_get_bank(struct fwu_mdata_object *mobj, size_t img_idx, size_t bnk_idx)
{ {
size_t offset; size_t offset;
offset = sizeof(struct fwu_mdata) + if (mobj->version == 1) {
(sizeof(struct fwu_image_entry) + offset = sizeof(struct fwu_mdata) +
sizeof(struct fwu_image_bank_info) * mobj->banks) * img_idx + (sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_entry) + sizeof(struct fwu_image_bank_info) * mobj->banks) *
sizeof(struct fwu_image_bank_info) * bnk_idx; img_idx + sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * bnk_idx;
} else {
offset = sizeof(struct fwu_mdata) +
sizeof(struct fwu_fw_store_desc) +
(sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * mobj->banks) *
img_idx + sizeof(struct fwu_image_entry) +
sizeof(struct fwu_image_bank_info) * bnk_idx;
}
return (struct fwu_image_bank_info *)((char *)mobj->mdata + offset); return (struct fwu_image_bank_info *)((char *)mobj->mdata + offset);
} }
@ -188,7 +237,7 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj,
return -EINVAL; return -EINVAL;
if (strcmp(uuid, "0") && if (strcmp(uuid, "0") &&
uuid_guid_parse(uuid, (unsigned char *)&image->location_uuid) < 0) uuid_guid_parse(uuid, (unsigned char *)&image->location_guid) < 0)
return -EINVAL; return -EINVAL;
/* Image type UUID */ /* Image type UUID */
@ -196,7 +245,7 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj,
if (!uuid) if (!uuid)
return -EINVAL; return -EINVAL;
if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_uuid) < 0) if (uuid_guid_parse(uuid, (unsigned char *)&image->image_type_guid) < 0)
return -EINVAL; return -EINVAL;
/* Fill bank image-UUID */ /* Fill bank image-UUID */
@ -210,22 +259,52 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj,
return -EINVAL; return -EINVAL;
if (strcmp(uuid, "0") && if (strcmp(uuid, "0") &&
uuid_guid_parse(uuid, (unsigned char *)&bank->image_uuid) < 0) uuid_guid_parse(uuid, (unsigned char *)&bank->image_guid) < 0)
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
} }
#if defined(CONFIG_FWU_MDATA_V1)
static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj)
{
}
#else
static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj)
{
int i;
struct fwu_fw_store_desc *fw_desc;
struct fwu_mdata *mdata = mobj->mdata;
mdata->metadata_size = mobj->size;
mdata->desc_offset = sizeof(struct fwu_mdata);
for (i = 0; i < MAX_BANKS_V2; i++)
mdata->bank_state[i] = i < mobj->banks ?
BANK_ACCEPTED : BANK_INVALID;
fw_desc = (struct fwu_fw_store_desc *)((u8 *)mdata + sizeof(*mdata));
fw_desc->num_banks = mobj->banks;
fw_desc->num_images = mobj->images;
fw_desc->img_entry_size = sizeof(struct fwu_image_entry) +
(sizeof(struct fwu_image_bank_info) * mobj->banks);
fw_desc->bank_info_entry_size =
sizeof(struct fwu_image_bank_info);
}
#endif /* CONFIG_FWU_MDATA_V1 */
/* Caller must ensure that @uuids[] has @mobj->images entries. */ /* Caller must ensure that @uuids[] has @mobj->images entries. */
static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[])
{ {
struct fwu_mdata *mdata = mobj->mdata; struct fwu_mdata *mdata = mobj->mdata;
int i, ret; int i, ret;
mdata->version = FWU_MDATA_VERSION; mdata->version = mobj->version;
mdata->active_index = active_bank; mdata->active_index = active_bank;
mdata->previous_active_index = previous_bank; mdata->previous_active_index = previous_bank;
fwu_fill_version_specific_mdata(mobj);
for (i = 0; i < mobj->images; i++) { for (i = 0; i < mobj->images; i++) {
ret = fwu_parse_fill_image_uuid(mobj, i, uuids[i]); ret = fwu_parse_fill_image_uuid(mobj, i, uuids[i]);
if (ret < 0) if (ret < 0)
@ -239,13 +318,14 @@ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[])
} }
static int static int
fwu_make_mdata(size_t images, size_t banks, char *uuids[], char *output) fwu_make_mdata(size_t images, size_t banks, u8 version, char *uuids[],
char *output)
{ {
struct fwu_mdata_object *mobj; struct fwu_mdata_object *mobj;
FILE *file; FILE *file;
int ret; int ret;
mobj = fwu_alloc_mdata(images, banks); mobj = fwu_alloc_mdata(images, banks, version);
if (!mobj) if (!mobj)
return -ENOMEM; return -ENOMEM;
@ -276,7 +356,7 @@ done_make:
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
unsigned long banks = 0, images = 0; unsigned long banks = 0, images = 0, version = 0;
int c, ret; int c, ret;
/* Explicitly initialize defaults */ /* Explicitly initialize defaults */
@ -305,6 +385,9 @@ int main(int argc, char *argv[])
case 'a': case 'a':
active_bank = strtoul(optarg, NULL, 0); active_bank = strtoul(optarg, NULL, 0);
break; break;
case 'v':
version = strtoul(optarg, NULL, 0);
break;
} }
} while (c != -1); } while (c != -1);
@ -313,6 +396,12 @@ int main(int argc, char *argv[])
return -EINVAL; return -EINVAL;
} }
if (!version || !supported_mdata_version(version)) {
fprintf(stderr, "Error: Version value can only be either 1 or 2, not %ld.\n",
version);
return -EINVAL;
}
/* This command takes UUIDs * images and output file. */ /* This command takes UUIDs * images and output file. */
if (optind + images + 1 != argc) { if (optind + images + 1 != argc) {
fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n"); fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n");
@ -325,7 +414,8 @@ int main(int argc, char *argv[])
previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1; previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1;
} }
ret = fwu_make_mdata(images, banks, argv + optind, argv[argc - 1]); ret = fwu_make_mdata(images, banks, (u8)version, argv + optind,
argv[argc - 1]);
if (ret < 0) if (ret < 0)
fprintf(stderr, "Error: Failed to parse and write image: %s\n", fprintf(stderr, "Error: Failed to parse and write image: %s\n",
strerror(-ret)); strerror(-ret));