On Fri, May 19, 2023 at 07:32:12PM +0900, Masahisa Kojima wrote:
> Current mkeficapsule tool does not provide firmware
> version management. EDK II reference implementation inserts
> the FMP Payload Header right before the payload.
> It coutains the fw_version and lowest supported version.
>
> This commit adds a new parameters required to generate
> the FMP Payload Header for mkeficapsule tool.
>  '-v' indicates the firmware version.
>
> When mkeficapsule tool is invoked without '-v' option,
> FMP Payload Header is not inserted, the behavior is same as
> current implementation.
>
> The lowest supported version included in the FMP Payload Header
> is not used, the value stored in the device tree is used instead.
>
> Signed-off-by: Masahisa Kojima <masahisa.koj...@linaro.org>
> ---
> No update since v5
>
> Changes in v5:
> - remove --lsv since we use the lowest_supported_version in the dtb
>
> Changes in v3:
> - remove '-f' option
> - move some definitions into tools/eficapsule.h
> - add dependency check of fw_version and lowest_supported_version
> - remove unexpected modification of existing fprintf() call
> - add documentation
>
> Newly created in v2
>
>  doc/mkeficapsule.1   | 10 ++++++++++
>  tools/eficapsule.h   | 30 ++++++++++++++++++++++++++++++
>  tools/mkeficapsule.c | 37 +++++++++++++++++++++++++++++++++----
>  3 files changed, 73 insertions(+), 4 deletions(-)
>
> diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> index 1ca245a10f..c4c2057d5c 100644
> --- a/doc/mkeficapsule.1
> +++ b/doc/mkeficapsule.1
> @@ -61,6 +61,16 @@ Specify an image index
>  .BI "-I\fR,\fB --instance " instance
>  Specify a hardware instance
>
> +.PP
> +FMP Payload Header is inserted right before the payload if
> +.BR --fw-version
> +is specified
> +
> +
> +.TP
> +.BI "-v\fR,\fB --fw-version " firmware-version
> +Specify a firmware version, 0 if omitted
> +
>  .PP
>  For generation of firmware accept empty capsule
>  .BR --guid
> diff --git a/tools/eficapsule.h b/tools/eficapsule.h
> index 072a4b5598..753fb73313 100644
> --- a/tools/eficapsule.h
> +++ b/tools/eficapsule.h
> @@ -113,4 +113,34 @@ struct efi_firmware_image_authentication {
>       struct win_certificate_uefi_guid auth_info;
>  } __packed;
>
> +/* fmp payload header */
> +#define SIGNATURE_16(A, B)   ((A) | ((B) << 8))
> +#define SIGNATURE_32(A, B, C, D)     \
> +     (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16))
> +
> +#define FMP_PAYLOAD_HDR_SIGNATURE    SIGNATURE_32('M', 'S', 'S', '1')
> +
> +/**
> + * struct fmp_payload_header - EDK2 header for the FMP payload
> + *
> + * This structure describes the header which is preprended to the
> + * FMP payload by the edk2 capsule generation scripts.
> + *
> + * @signature:                       Header signature used to identify the 
> header
> + * @header_size:             Size of the structure
> + * @fw_version:                      Firmware versions used
> + * @lowest_supported_version:        Lowest supported version (not used)
> + */
> +struct fmp_payload_header {
> +     uint32_t signature;
> +     uint32_t header_size;
> +     uint32_t fw_version;
> +     uint32_t lowest_supported_version;
> +};
> +
> +struct fmp_payload_header_params {
> +     bool have_header;
> +     uint32_t fw_version;
> +};
> +
>  #endif /* _EFI_CAPSULE_H */
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index b71537beee..52be1f122e 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -41,6 +41,7 @@ static struct option options[] = {
>       {"guid", required_argument, NULL, 'g'},
>       {"index", required_argument, NULL, 'i'},
>       {"instance", required_argument, NULL, 'I'},
> +     {"fw-version", required_argument, NULL, 'v'},
>       {"private-key", required_argument, NULL, 'p'},
>       {"certificate", required_argument, NULL, 'c'},
>       {"monotonic-count", required_argument, NULL, 'm'},
> @@ -60,6 +61,7 @@ static void print_usage(void)
>               "\t-g, --guid <guid string>    guid for image blob type\n"
>               "\t-i, --index <index>         update image index\n"
>               "\t-I, --instance <instance>   update hardware instance\n"
> +             "\t-v, --fw-version <version>  firmware version\n"
>               "\t-p, --private-key <privkey file>  private key file\n"
>               "\t-c, --certificate <cert file>     signer's certificate 
> file\n"
>               "\t-m, --monotonic-count <count>     monotonic count\n"
> @@ -402,6 +404,7 @@ static void free_sig_data(struct auth_context *ctx)
>   */
>  static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>                       unsigned long index, unsigned long instance,
> +                     struct fmp_payload_header_params *fmp_ph_params,
>                       uint64_t mcount, char *privkey_file, char *cert_file,
>                       uint16_t oemflags)
>  {
> @@ -410,10 +413,11 @@ static int create_fwbin(char *path, char *bin, 
> efi_guid_t *guid,
>       struct efi_firmware_management_capsule_image_header image;
>       struct auth_context auth_context;
>       FILE *f;
> -     uint8_t *data;
> +     uint8_t *data, *new_data, *buf;
>       off_t bin_size;
>       uint64_t offset;
>       int ret;
> +     struct fmp_payload_header payload_header;
>
>  #ifdef DEBUG
>       fprintf(stderr, "For output: %s\n", path);
> @@ -423,6 +427,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t 
> *guid,
>       auth_context.sig_size = 0;
>       f = NULL;
>       data = NULL;
> +     new_data = NULL;
>       ret = -1;
>
>       /*
> @@ -431,12 +436,30 @@ static int create_fwbin(char *path, char *bin, 
> efi_guid_t *guid,
>       if (read_bin_file(bin, &data, &bin_size))
>               goto err;
>
> +     buf = data;
> +
> +     /* insert fmp payload header right before the payload */
> +     if (fmp_ph_params->have_header) {
> +             new_data = malloc(bin_size + sizeof(payload_header));
> +             if (!new_data)
> +                     goto err;
> +
> +             payload_header.signature = FMP_PAYLOAD_HDR_SIGNATURE;
> +             payload_header.header_size = sizeof(payload_header);
> +             payload_header.fw_version = fmp_ph_params->fw_version;
> +             payload_header.lowest_supported_version = 0; /* not used */
> +             memcpy(new_data, &payload_header, sizeof(payload_header));
> +             memcpy(new_data + sizeof(payload_header), data, bin_size);
> +             buf = new_data;
> +             bin_size += sizeof(payload_header);
> +     }
> +
>       /* first, calculate signature to determine its size */
>       if (privkey_file && cert_file) {
>               auth_context.key_file = privkey_file;
>               auth_context.cert_file = cert_file;
>               auth_context.auth.monotonic_count = mcount;
> -             auth_context.image_data = data;
> +             auth_context.image_data = buf;
>               auth_context.image_size = bin_size;
>
>               if (create_auth_data(&auth_context)) {
> @@ -536,7 +559,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t 
> *guid,
>       /*
>        * firmware binary
>        */
> -     if (write_capsule_file(f, data, bin_size, "Firmware binary"))
> +     if (write_capsule_file(f, buf, bin_size, "Firmware binary"))
>               goto err;
>
>       ret = 0;
> @@ -545,6 +568,7 @@ err:
>               fclose(f);
>       free_sig_data(&auth_context);
>       free(data);
> +     free(new_data);
>
>       return ret;
>  }
> @@ -644,6 +668,7 @@ int main(int argc, char **argv)
>       unsigned long oemflags;
>       char *privkey_file, *cert_file;
>       int c, idx;
> +     struct fmp_payload_header_params fmp_ph_params = { 0 };
>
>       guid = NULL;
>       index = 0;
> @@ -679,6 +704,10 @@ int main(int argc, char **argv)
>               case 'I':
>                       instance = strtoul(optarg, NULL, 0);
>                       break;
> +             case 'v':
> +                     fmp_ph_params.fw_version = strtoul(optarg, NULL, 0);
> +                     fmp_ph_params.have_header = true;
> +                     break;
>               case 'p':
>                       if (privkey_file) {
>                               fprintf(stderr,
> @@ -751,7 +780,7 @@ int main(int argc, char **argv)
>                       exit(EXIT_FAILURE);
>               }
>       } else  if (create_fwbin(argv[argc - 1], argv[argc - 2], guid,
> -                              index, instance, mcount, privkey_file,
> +                              index, instance, &fmp_ph_params, mcount, 
> privkey_file,
>                                cert_file, (uint16_t)oemflags) < 0) {
>               fprintf(stderr, "Creating firmware capsule failed\n");
>               exit(EXIT_FAILURE);
> --
> 2.17.1
>

Acked-by: Ilias Apalodimas <ilias.apalodi...@linaro.org>

Reply via email to