]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - tools/mkfwumdata.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2023, Linaro Limited
13 #include <u-boot/crc.h>
15 #include <uuid/uuid.h>
17 /* This will dynamically allocate the fwu_mdata */
18 #define CONFIG_FWU_NUM_BANKS 0
19 #define CONFIG_FWU_NUM_IMAGES_PER_BANK 0
21 /* Since we can not include fwu.h, redefine version here. */
22 #define FWU_MDATA_VERSION 1
30 #include <fwu_mdata.h>
32 /* TODO: Endianness conversion may be required for some arch. */
34 static const char *opts_short
= "b:i:a:p:gh";
36 static struct option options
[] = {
37 {"banks", required_argument
, NULL
, 'b'},
38 {"images", required_argument
, NULL
, 'i'},
39 {"guid", required_argument
, NULL
, 'g'},
40 {"active-bank", required_argument
, NULL
, 'a'},
41 {"previous-bank", required_argument
, NULL
, 'p'},
42 {"help", no_argument
, NULL
, 'h'},
46 static void print_usage(void)
48 fprintf(stderr
, "Usage: mkfwumdata [options] <UUIDs list> <output file>\n");
49 fprintf(stderr
, "Options:\n"
50 "\t-i, --images <num> Number of images (mandatory)\n"
51 "\t-b, --banks <num> Number of banks (mandatory)\n"
52 "\t-a, --active-bank <num> Active bank (default=0)\n"
53 "\t-p, --previous-bank <num> Previous active bank (default=active_bank - 1)\n"
54 "\t-g, --guid Use GUID instead of UUID\n"
55 "\t-h, --help print a help message\n"
57 fprintf(stderr
, " UUIDs list syntax:\n"
58 "\t <location uuid>,<image type uuid>,<images uuid list>\n"
59 "\t images uuid list syntax:\n"
60 "\t img_uuid_00,img_uuid_01...img_uuid_0b,\n"
61 "\t img_uuid_10,img_uuid_11...img_uuid_1b,\n"
63 "\t img_uuid_i0,img_uuid_i1...img_uuid_ib,\n"
64 "\t where 'b' and 'i' are number of banks and number\n"
65 "\t of images in a bank respectively.\n"
69 struct fwu_mdata_object
{
73 struct fwu_mdata
*mdata
;
76 static int previous_bank
, active_bank
;
77 static bool __use_guid
;
79 static struct fwu_mdata_object
*fwu_alloc_mdata(size_t images
, size_t banks
)
81 struct fwu_mdata_object
*mobj
;
83 mobj
= calloc(1, sizeof(*mobj
));
87 mobj
->size
= sizeof(struct fwu_mdata
) +
88 (sizeof(struct fwu_image_entry
) +
89 sizeof(struct fwu_image_bank_info
) * banks
) * images
;
90 mobj
->images
= images
;
93 mobj
->mdata
= calloc(1, mobj
->size
);
102 static struct fwu_image_entry
*
103 fwu_get_image(struct fwu_mdata_object
*mobj
, size_t idx
)
107 offset
= sizeof(struct fwu_mdata
) +
108 (sizeof(struct fwu_image_entry
) +
109 sizeof(struct fwu_image_bank_info
) * mobj
->banks
) * idx
;
111 return (struct fwu_image_entry
*)((char *)mobj
->mdata
+ offset
);
114 static struct fwu_image_bank_info
*
115 fwu_get_bank(struct fwu_mdata_object
*mobj
, size_t img_idx
, size_t bnk_idx
)
119 offset
= sizeof(struct fwu_mdata
) +
120 (sizeof(struct fwu_image_entry
) +
121 sizeof(struct fwu_image_bank_info
) * mobj
->banks
) * img_idx
+
122 sizeof(struct fwu_image_entry
) +
123 sizeof(struct fwu_image_bank_info
) * bnk_idx
;
125 return (struct fwu_image_bank_info
*)((char *)mobj
->mdata
+ offset
);
129 * convert_uuid_to_guid() - convert UUID to GUID
132 * UUID and GUID have the same data structure, but their binary
133 * formats are different due to the endianness. See lib/uuid.c.
134 * Since uuid_parse() can handle only UUID, this function must
135 * be called to get correct data for GUID when parsing a string.
137 * The correct data will be returned in @buf.
139 static void convert_uuid_to_guid(unsigned char *buf
)
159 static int uuid_guid_parse(char *uuidstr
, unsigned char *uuid
)
163 ret
= uuid_parse(uuidstr
, uuid
);
168 convert_uuid_to_guid(uuid
);
174 fwu_parse_fill_image_uuid(struct fwu_mdata_object
*mobj
,
175 size_t idx
, char *uuids
)
177 struct fwu_image_entry
*image
= fwu_get_image(mobj
, idx
);
178 struct fwu_image_bank_info
*bank
;
179 char *p
= uuids
, *uuid
;
185 /* Image location UUID */
186 uuid
= strsep(&p
, ",");
190 if (strcmp(uuid
, "0") &&
191 uuid_guid_parse(uuid
, (unsigned char *)&image
->location_uuid
) < 0)
194 /* Image type UUID */
195 uuid
= strsep(&p
, ",");
199 if (uuid_guid_parse(uuid
, (unsigned char *)&image
->image_type_uuid
) < 0)
202 /* Fill bank image-UUID */
203 for (i
= 0; i
< mobj
->banks
; i
++) {
204 bank
= fwu_get_bank(mobj
, idx
, i
);
208 uuid
= strsep(&p
, ",");
212 if (strcmp(uuid
, "0") &&
213 uuid_guid_parse(uuid
, (unsigned char *)&bank
->image_uuid
) < 0)
219 /* Caller must ensure that @uuids[] has @mobj->images entries. */
220 static int fwu_parse_fill_uuids(struct fwu_mdata_object
*mobj
, char *uuids
[])
222 struct fwu_mdata
*mdata
= mobj
->mdata
;
225 mdata
->version
= FWU_MDATA_VERSION
;
226 mdata
->active_index
= active_bank
;
227 mdata
->previous_active_index
= previous_bank
;
229 for (i
= 0; i
< mobj
->images
; i
++) {
230 ret
= fwu_parse_fill_image_uuid(mobj
, i
, uuids
[i
]);
235 mdata
->crc32
= crc32(0, (const unsigned char *)&mdata
->version
,
236 mobj
->size
- sizeof(uint32_t));
242 fwu_make_mdata(size_t images
, size_t banks
, char *uuids
[], char *output
)
244 struct fwu_mdata_object
*mobj
;
248 mobj
= fwu_alloc_mdata(images
, banks
);
252 ret
= fwu_parse_fill_uuids(mobj
, uuids
);
256 file
= fopen(output
, "w");
262 ret
= fwrite(mobj
->mdata
, mobj
->size
, 1, file
);
263 if (ret
!= mobj
->size
)
277 int main(int argc
, char *argv
[])
279 unsigned long banks
= 0, images
= 0;
282 /* Explicitly initialize defaults */
285 previous_bank
= INT_MAX
;
288 c
= getopt_long(argc
, argv
, opts_short
, options
, NULL
);
294 banks
= strtoul(optarg
, NULL
, 0);
297 images
= strtoul(optarg
, NULL
, 0);
303 previous_bank
= strtoul(optarg
, NULL
, 0);
306 active_bank
= strtoul(optarg
, NULL
, 0);
311 if (!banks
|| !images
) {
312 fprintf(stderr
, "Error: The number of banks and images must not be 0.\n");
316 /* This command takes UUIDs * images and output file. */
317 if (optind
+ images
+ 1 != argc
) {
318 fprintf(stderr
, "Error: UUID list or output file is not specified or too much.\n");
323 if (previous_bank
== INT_MAX
) {
324 /* set to the earlier bank in round-robin scheme */
325 previous_bank
= active_bank
> 0 ? active_bank
- 1 : banks
- 1;
328 ret
= fwu_make_mdata(images
, banks
, argv
+ optind
, argv
[argc
- 1]);
330 fprintf(stderr
, "Error: Failed to parse and write image: %s\n",