diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/mkfwumdata.c | 148 |
1 files changed, 119 insertions, 29 deletions
diff --git a/tools/mkfwumdata.c b/tools/mkfwumdata.c index b2d90ca..634453d 100644 --- a/tools/mkfwumdata.c +++ b/tools/mkfwumdata.c @@ -10,28 +10,35 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> -#include <u-boot/crc.h> #include <unistd.h> +#include <generated/autoconf.h> +#include <u-boot/crc.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 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 <fwu_mdata.h> /* 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 <num> Number of images (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-p, --previous-bank <num> 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)); |