From 9e63786e2b4b35587da2050c180111e9bd1e3a23 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 18 Jan 2022 13:39:45 +0900 Subject: [PATCH] tools: mkeficapsule: rework the code a little bit Abstract common routines to make the code easily understandable. No functional change. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass --- tools/mkeficapsule.c | 239 ++++++++++++++++++++++++++++++------------- 1 file changed, 167 insertions(+), 72 deletions(-) diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index b22b61a9a5..243fd6e483 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -51,33 +52,36 @@ static struct option options[] = { static void print_usage(void) { printf("Usage: %s [options] \n" - "Options:\n" - - "\t-f, --fit new FIT image file\n" - "\t-r, --raw new raw image file\n" - "\t-i, --index update image index\n" - "\t-I, --instance update hardware instance\n" - "\t-h, --help print a help message\n", - tool_name); + "Options:\n" + + "\t-f, --fit new FIT image file\n" + "\t-r, --raw new raw image file\n" + "\t-i, --index update image index\n" + "\t-I, --instance update hardware instance\n" + "\t-h, --help print a help message\n", + tool_name); } -static int create_fwbin(char *path, char *bin, efi_guid_t *guid, - unsigned long index, unsigned long instance) +/** + * read_bin_file - read a firmware binary file + * @bin: Path to a firmware binary file + * @data: Pointer to pointer of allocated buffer + * @bin_size: Size of allocated buffer + * + * Read out a content of binary, @bin, into @data. + * A caller should free @data. + * + * Return: + * * 0 - on success + * * -1 - on failure + */ +static int read_bin_file(char *bin, void **data, off_t *bin_size) { - struct efi_capsule_header header; - struct efi_firmware_management_capsule_header capsule; - struct efi_firmware_management_capsule_image_header image; - FILE *f, *g; + FILE *g; struct stat bin_stat; - u8 *data; + void *buf; size_t size; - u64 offset; - -#ifdef DEBUG - printf("For output: %s\n", path); - printf("\tbin: %s\n\ttype: %pUl\n", bin, guid); - printf("\tindex: %ld\n\tinstance: %ld\n", index, instance); -#endif + int ret = 0; g = fopen(bin, "r"); if (!g) { @@ -86,19 +90,123 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, } if (stat(bin, &bin_stat) < 0) { fprintf(stderr, "cannot determine the size of %s\n", bin); - goto err_1; + ret = -1; + goto err; + } + if (bin_stat.st_size > SIZE_MAX) { + fprintf(stderr, "file size is too large for malloc: %s\n", bin); + ret = -1; + goto err; } - data = malloc(bin_stat.st_size); - if (!data) { + buf = malloc(bin_stat.st_size); + if (!buf) { fprintf(stderr, "cannot allocate memory: %zx\n", (size_t)bin_stat.st_size); - goto err_1; + ret = -1; + goto err; + } + + size = fread(buf, 1, bin_stat.st_size, g); + if (size < bin_stat.st_size) { + fprintf(stderr, "read failed (%zx)\n", size); + ret = -1; + goto err; } + + *data = buf; + *bin_size = bin_stat.st_size; +err: + fclose(g); + + return ret; +} + +/** + * write_capsule_file - write a capsule file + * @bin: FILE stream + * @data: Pointer to data + * @bin_size: Size of data + * + * Write out data, @data, with the size @bin_size. + * + * Return: + * * 0 - on success + * * -1 - on failure + */ +static int write_capsule_file(FILE *f, void *data, size_t size, const char *msg) +{ + size_t size_written; + + size_written = fwrite(data, 1, size, f); + if (size_written < size) { + fprintf(stderr, "%s: write failed (%zx != %zx)\n", msg, + size_written, size); + return -1; + } + + return 0; +} + +/** + * create_fwbin - create an uefi capsule file + * @path: Path to a created capsule file + * @bin: Path to a firmware binary to encapsulate + * @guid: GUID of related FMP driver + * @index: Index number in capsule + * @instance: Instance number in capsule + * @mcount: Monotonic count in authentication information + * @private_file: Path to a private key file + * @cert_file: Path to a certificate file + * + * This function actually does the job of creating an uefi capsule file. + * All the arguments must be supplied. + * If either @private_file ror @cert_file is NULL, the capsule file + * won't be signed. + * + * Return: + * * 0 - on success + * * -1 - on failure + */ +static int create_fwbin(char *path, char *bin, efi_guid_t *guid, + unsigned long index, unsigned long instance) +{ + struct efi_capsule_header header; + struct efi_firmware_management_capsule_header capsule; + struct efi_firmware_management_capsule_image_header image; + FILE *f; + void *data; + off_t bin_size; + u64 offset; + int ret; + +#ifdef DEBUG + printf("For output: %s\n", path); + printf("\tbin: %s\n\ttype: %pUl\n", bin, guid); + printf("\tindex: %ld\n\tinstance: %ld\n", index, instance); +#endif + + f = NULL; + data = NULL; + ret = -1; + + /* + * read a firmware binary + */ + if (read_bin_file(bin, &data, &bin_size)) + goto err; + + /* + * write a capsule file + */ f = fopen(path, "w"); if (!f) { fprintf(stderr, "cannot open %s\n", path); - goto err_2; + goto err; } + + /* + * capsule file header + */ header.capsule_guid = efi_guid_fm_capsule; header.header_size = sizeof(header); /* TODO: The current implementation ignores flags */ @@ -106,70 +214,57 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, header.capsule_image_size = sizeof(header) + sizeof(capsule) + sizeof(u64) + sizeof(image) - + bin_stat.st_size; - - size = fwrite(&header, 1, sizeof(header), f); - if (size < sizeof(header)) { - fprintf(stderr, "write failed (%zx)\n", size); - goto err_3; - } + + bin_size; + if (write_capsule_file(f, &header, sizeof(header), + "Capsule header")) + goto err; + /* + * firmware capsule header + * This capsule has only one firmware capsule image. + */ capsule.version = 0x00000001; capsule.embedded_driver_count = 0; capsule.payload_item_count = 1; - size = fwrite(&capsule, 1, sizeof(capsule), f); - if (size < (sizeof(capsule))) { - fprintf(stderr, "write failed (%zx)\n", size); - goto err_3; - } + if (write_capsule_file(f, &capsule, sizeof(capsule), + "Firmware capsule header")) + goto err; + offset = sizeof(capsule) + sizeof(u64); - size = fwrite(&offset, 1, sizeof(offset), f); - if (size < sizeof(offset)) { - fprintf(stderr, "write failed (%zx)\n", size); - goto err_3; - } + if (write_capsule_file(f, &offset, sizeof(offset), + "Offset to capsule image")) + goto err; + /* + * firmware capsule image header + */ image.version = 0x00000003; memcpy(&image.update_image_type_id, guid, sizeof(*guid)); image.update_image_index = index; image.reserved[0] = 0; image.reserved[1] = 0; image.reserved[2] = 0; - image.update_image_size = bin_stat.st_size; + image.update_image_size = bin_size; image.update_vendor_code_size = 0; /* none */ image.update_hardware_instance = instance; image.image_capsule_support = 0; + if (write_capsule_file(f, &image, sizeof(image), + "Firmware capsule image header")) + goto err; - size = fwrite(&image, 1, sizeof(image), f); - if (size < sizeof(image)) { - fprintf(stderr, "write failed (%zx)\n", size); - goto err_3; - } - size = fread(data, 1, bin_stat.st_size, g); - if (size < bin_stat.st_size) { - fprintf(stderr, "read failed (%zx)\n", size); - goto err_3; - } - size = fwrite(data, 1, bin_stat.st_size, f); - if (size < bin_stat.st_size) { - fprintf(stderr, "write failed (%zx)\n", size); - goto err_3; - } - - fclose(f); - fclose(g); - free(data); - - return 0; + /* + * firmware binary + */ + if (write_capsule_file(f, data, bin_size, "Firmware binary")) + goto err; -err_3: - fclose(f); -err_2: + ret = 0; +err: + if (f) + fclose(f); free(data); -err_1: - fclose(g); - return -1; + return ret; } /* -- 2.39.5