From d99127a69ebf65cd35c33896ea6f4b45b77b8c82 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:15 +0530 Subject: tools: mkfwumdata: fix the size parameter to the fwrite call The fwrite call returns the number of bytes transferred as part of the write only when the size parameter is 1. Pass the size parameter to the library call as 1 so that the correct number of bytes transferred are returned. Fixes: fdd56bfd3ad ("tools: Add mkfwumdata tool for FWU metadata image") Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- tools/mkfwumdata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index 9732a8ddc5a..b2d90ca7c94 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -259,7 +259,7 @@ fwu_make_mdata(size_t images, size_t banks, char *uuids[], char *output) goto done_make; } - ret = fwrite(mobj->mdata, mobj->size, 1, file); + ret = fwrite(mobj->mdata, 1, mobj->size, file); if (ret != mobj->size) ret = -errno; else -- cgit v1.2.3 From df42d684961fbb9a79e6ae81234d97799d3efbbb Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:28 +0530 Subject: 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 Tested-by: Michal Simek --- tools/mkfwumdata.c | 148 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 29 deletions(-) (limited to 'tools') diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index b2d90ca7c94..634453d421e 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -10,28 +10,35 @@ #include #include #include -#include #include +#include +#include #include -/* 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 int16_t s16; typedef uint16_t u16; typedef uint32_t u32; 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 /* 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[] = { {"banks", required_argument, NULL, 'b'}, @@ -39,6 +46,7 @@ static struct option options[] = { {"guid", required_argument, NULL, 'g'}, {"active-bank", required_argument, NULL, 'a'}, {"previous-bank", required_argument, NULL, 'p'}, + {"version", required_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -49,6 +57,7 @@ static void print_usage(void) fprintf(stderr, "Options:\n" "\t-i, --images Number of images (mandatory)\n" "\t-b, --banks Number of banks (mandatory)\n" + "\t-v, --version Metadata version (mandatory)\n" "\t-a, --active-bank Active bank (default=0)\n" "\t-p, --previous-bank Previous active bank (default=active_bank - 1)\n" "\t-g, --guid Use GUID instead of UUID\n" @@ -70,13 +79,26 @@ struct fwu_mdata_object { size_t images; size_t banks; size_t size; + u8 version; struct fwu_mdata *mdata; }; static int previous_bank, active_bank; 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; @@ -84,11 +106,20 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks) if (!mobj) return NULL; - mobj->size = sizeof(struct fwu_mdata) + - (sizeof(struct fwu_image_entry) + - sizeof(struct fwu_image_bank_info) * banks) * images; + if (version == 1) { + mobj->size = sizeof(struct fwu_mdata) + + (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->banks = banks; + mobj->version = version; mobj->mdata = calloc(1, mobj->size); if (!mobj->mdata) { @@ -104,9 +135,18 @@ fwu_get_image(struct fwu_mdata_object *mobj, size_t idx) { size_t offset; - offset = sizeof(struct fwu_mdata) + - (sizeof(struct fwu_image_entry) + - sizeof(struct fwu_image_bank_info) * mobj->banks) * idx; + if (mobj->version == 1) { + offset = sizeof(struct fwu_mdata) + + (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); } @@ -116,11 +156,20 @@ fwu_get_bank(struct fwu_mdata_object *mobj, size_t img_idx, size_t bnk_idx) { size_t offset; - offset = sizeof(struct fwu_mdata) + - (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; + if (mobj->version == 1) { + offset = sizeof(struct fwu_mdata) + + (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; + } 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); } @@ -188,7 +237,7 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, return -EINVAL; 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; /* Image type UUID */ @@ -196,7 +245,7 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, if (!uuid) 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; /* Fill bank image-UUID */ @@ -210,22 +259,52 @@ fwu_parse_fill_image_uuid(struct fwu_mdata_object *mobj, return -EINVAL; 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 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. */ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) { struct fwu_mdata *mdata = mobj->mdata; int i, ret; - mdata->version = FWU_MDATA_VERSION; + mdata->version = mobj->version; mdata->active_index = active_bank; mdata->previous_active_index = previous_bank; + fwu_fill_version_specific_mdata(mobj); + for (i = 0; i < mobj->images; i++) { ret = fwu_parse_fill_image_uuid(mobj, i, uuids[i]); if (ret < 0) @@ -239,13 +318,14 @@ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) } 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; FILE *file; int ret; - mobj = fwu_alloc_mdata(images, banks); + mobj = fwu_alloc_mdata(images, banks, version); if (!mobj) return -ENOMEM; @@ -276,7 +356,7 @@ done_make: int main(int argc, char *argv[]) { - unsigned long banks = 0, images = 0; + unsigned long banks = 0, images = 0, version = 0; int c, ret; /* Explicitly initialize defaults */ @@ -305,6 +385,9 @@ int main(int argc, char *argv[]) case 'a': active_bank = strtoul(optarg, NULL, 0); break; + case 'v': + version = strtoul(optarg, NULL, 0); + break; } } while (c != -1); @@ -313,6 +396,12 @@ int main(int argc, char *argv[]) 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. */ if (optind + images + 1 != argc) { 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; } - 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) fprintf(stderr, "Error: Failed to parse and write image: %s\n", strerror(-ret)); -- cgit v1.2.3 From cb9ae40a16f0e9adae594526435de976afeedaf2 Mon Sep 17 00:00:00 2001 From: Sughosh Ganu Date: Fri, 22 Mar 2024 16:27:29 +0530 Subject: tools: mkfwumdata: add logic to append vendor data to the FWU metadata The version 2 of the FWU metadata allows for appending opaque vendor specific data to the metadata structure. Add support for appending this data to the metadata. The vendor specific data needs to be provided through a file, passed through a command-line parameter. Make corresponding changes to the tool's manpage. Signed-off-by: Sughosh Ganu Tested-by: Michal Simek --- tools/mkfwumdata.c | 99 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index 634453d421e..fbc2067bc12 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -36,9 +38,7 @@ typedef uint64_t u64; #include -/* TODO: Endianness conversion may be required for some arch. */ - -static const char *opts_short = "b:i:a:p:v:gh"; +static const char *opts_short = "b:i:a:p:v:V:gh"; static struct option options[] = { {"banks", required_argument, NULL, 'b'}, @@ -47,6 +47,7 @@ static struct option options[] = { {"active-bank", required_argument, NULL, 'a'}, {"previous-bank", required_argument, NULL, 'p'}, {"version", required_argument, NULL, 'v'}, + {"vendor-file", required_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -61,6 +62,7 @@ static void print_usage(void) "\t-a, --active-bank Active bank (default=0)\n" "\t-p, --previous-bank Previous active bank (default=active_bank - 1)\n" "\t-g, --guid Use GUID instead of UUID\n" + "\t-V, --vendor-file Vendor data file to append to the metadata\n" "\t-h, --help print a help message\n" ); fprintf(stderr, " UUIDs list syntax:\n" @@ -80,6 +82,8 @@ struct fwu_mdata_object { size_t banks; size_t size; u8 version; + size_t vsize; + void *vbuf; struct fwu_mdata *mdata; }; @@ -98,7 +102,7 @@ static bool supported_mdata_version(unsigned long version) } static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, - u8 version) + u8 version, size_t vendor_size) { struct fwu_mdata_object *mobj; @@ -115,6 +119,9 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, sizeof(struct fwu_fw_store_desc) + (sizeof(struct fwu_image_entry) + sizeof(struct fwu_image_bank_info) * banks) * images; + + mobj->size += vendor_size; + mobj->vsize = vendor_size; } mobj->images = images; @@ -122,12 +129,21 @@ static struct fwu_mdata_object *fwu_alloc_mdata(size_t images, size_t banks, mobj->version = version; mobj->mdata = calloc(1, mobj->size); - if (!mobj->mdata) { - free(mobj); - return NULL; + if (!mobj->mdata) + goto alloc_err; + + if (vendor_size) { + mobj->vbuf = calloc(1, mobj->vsize); + if (!mobj->vbuf) + goto alloc_err; } return mobj; + +alloc_err: + free(mobj->mdata); + free(mobj); + return NULL; } static struct fwu_image_entry * @@ -297,6 +313,7 @@ static void fwu_fill_version_specific_mdata(struct fwu_mdata_object *mobj) static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) { struct fwu_mdata *mdata = mobj->mdata; + char *vdata; int i, ret; mdata->version = mobj->version; @@ -311,24 +328,65 @@ static int fwu_parse_fill_uuids(struct fwu_mdata_object *mobj, char *uuids[]) return ret; } + if (mobj->vsize) { + vdata = (char *)mobj->mdata + (mobj->size - mobj->vsize); + memcpy(vdata, mobj->vbuf, mobj->vsize); + } + mdata->crc32 = crc32(0, (const unsigned char *)&mdata->version, mobj->size - sizeof(uint32_t)); return 0; } -static int -fwu_make_mdata(size_t images, size_t banks, u8 version, char *uuids[], - char *output) +static int fwu_read_vendor_data(struct fwu_mdata_object *mobj, + const char *vendor_file) +{ + int ret = 0; + FILE *vfile = NULL; + + vfile = fopen(vendor_file, "r"); + if (!vfile) { + ret = -1; + goto out; + } + + if (fread(mobj->vbuf, 1, mobj->vsize, vfile) != mobj->vsize) + ret = -1; + +out: + fclose(vfile); + return ret; +} + +static int fwu_make_mdata(size_t images, size_t banks, u8 version, + const char *vendor_file, char *uuids[], + char *output) { - struct fwu_mdata_object *mobj; - FILE *file; int ret; + FILE *file; + struct stat sbuf; + size_t vendor_size = 0; + struct fwu_mdata_object *mobj; - mobj = fwu_alloc_mdata(images, banks, version); + if (vendor_file) { + ret = stat(vendor_file, &sbuf); + if (ret) + return -errno; + + vendor_size = sbuf.st_size; + } + + mobj = fwu_alloc_mdata(images, banks, version, vendor_size); if (!mobj) return -ENOMEM; + if (vendor_file) { + ret = fwu_read_vendor_data(mobj, vendor_file); + if (ret) + goto done_make; + } + ret = fwu_parse_fill_uuids(mobj, uuids); if (ret < 0) goto done_make; @@ -349,6 +407,7 @@ fwu_make_mdata(size_t images, size_t banks, u8 version, char *uuids[], done_make: free(mobj->mdata); + free(mobj->vbuf); free(mobj); return ret; @@ -358,11 +417,13 @@ int main(int argc, char *argv[]) { unsigned long banks = 0, images = 0, version = 0; int c, ret; + const char *vendor_file; /* Explicitly initialize defaults */ active_bank = 0; __use_guid = false; previous_bank = INT_MAX; + vendor_file = NULL; do { c = getopt_long(argc, argv, opts_short, options, NULL); @@ -388,6 +449,9 @@ int main(int argc, char *argv[]) case 'v': version = strtoul(optarg, NULL, 0); break; + case 'V': + vendor_file = optarg; + break; } } while (c != -1); @@ -402,6 +466,11 @@ int main(int argc, char *argv[]) return -EINVAL; } + if (version == 1 && vendor_file) { + fprintf(stderr, "Error: Vendor Data can only be appended in version 2 of FWU Metadata.\n"); + return -EINVAL; + } + /* This command takes UUIDs * images and output file. */ if (optind + images + 1 != argc) { fprintf(stderr, "Error: UUID list or output file is not specified or too much.\n"); @@ -414,8 +483,8 @@ int main(int argc, char *argv[]) previous_bank = active_bank > 0 ? active_bank - 1 : banks - 1; } - ret = fwu_make_mdata(images, banks, (u8)version, argv + optind, - argv[argc - 1]); + ret = fwu_make_mdata(images, banks, (u8)version, vendor_file, + argv + optind, argv[argc - 1]); if (ret < 0) fprintf(stderr, "Error: Failed to parse and write image: %s\n", strerror(-ret)); -- cgit v1.2.3