From: Takahiro Akashi <takahiro.akashi@linaro.org>
To: Masahisa Kojima <masahisa.kojima@linaro.org>
Cc: u-boot@lists.denx.de, Heinrich Schuchardt <xypron.glpk@gmx.de>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>
Subject: Re: [PATCH v2 4/4] mkeficapsule: add FMP Payload Header
Date: Thu, 2 Mar 2023 14:29:49 +0900 [thread overview]
Message-ID: <20230302052949.GC44192@laputa> (raw)
In-Reply-To: <20230301091523.18384-5-masahisa.kojima@linaro.org>
On Wed, Mar 01, 2023 at 06:15:22PM +0900, Masahisa Kojima wrote:
> Current mkeficapsule tool does not provide firmware
> version management. EDK2 reference implementation inserts
> the FMP Payload Header right before the payload.
> It coutains the fw_version and lowest supported version.
>
> This commit adds three new parameters required to generate
> the FMP Payload Header for mkeficapsule tool.
> '-f' indicates whether FMP Payload Header is inserted.
> '-v' indicates the firmware version.
> '-l' indicates the lowest supported version.
from user's point of view, '-f' looks redundant since '-v' or '-l'
implicitly means '-f'.
> When mkeficapsule tool is invoked without '-f' option,
> FMP Payload Header is not inserted, the behavior is same as
> current implementation.
>
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
> Newly created in v2
>
> tools/mkeficapsule.c | 81 ++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 75 insertions(+), 6 deletions(-)
>
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index b71537beee..e0a6948df8 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
> efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
> efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>
> -static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
> +static const char *opts_short = "g:i:I:v:l:p:c:m:o:dfhAR";
>
> enum {
> CAPSULE_NORMAL_BLOB = 0,
> @@ -41,6 +41,9 @@ static struct option options[] = {
> {"guid", required_argument, NULL, 'g'},
> {"index", required_argument, NULL, 'i'},
> {"instance", required_argument, NULL, 'I'},
> + {"fmp-payload-header", no_argument, NULL, 'f'},
> + {"fw-version", required_argument, NULL, 'v'},
> + {"lsv", required_argument, NULL, 'l'},
> {"private-key", required_argument, NULL, 'p'},
> {"certificate", required_argument, NULL, 'c'},
> {"monotonic-count", required_argument, NULL, 'm'},
> @@ -60,6 +63,9 @@ 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-f, --fmp-payload-header insert fmp payload header\n"
> + "\t-v, --fw-version <version> firmware version\n"
> + "\t-l, --lsv <version> lowest supported 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"
> @@ -71,6 +77,30 @@ static void print_usage(void)
> tool_name);
> }
>
> +#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
> + */
> +struct fmp_payload_header {
> + uint32_t signature;
> + uint32_t header_size;
> + uint32_t fw_version;
> + uint32_t lowest_supported_version;
> +};
> +
> /**
> * auth_context - authentication context
> * @key_file: Path to a private key file
> @@ -95,6 +125,12 @@ struct auth_context {
> size_t sig_size;
> };
>
> +struct fmp_payload_header_params {
> + bool have_header;
> + uint32_t fw_version;
> + uint32_t lowest_supported_version;
> +};
> +
You may put those definitions in tools/eficapsule.h.
> static int dump_sig;
>
> /**
> @@ -402,6 +438,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 +447,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 +461,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 +470,31 @@ 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 =
> + fmp_ph_params->lowest_supported_version;
> + 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 +594,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 +603,7 @@ err:
> fclose(f);
> free_sig_data(&auth_context);
> free(data);
> + free(new_data);
>
> return ret;
> }
> @@ -644,6 +703,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 +739,15 @@ int main(int argc, char **argv)
> case 'I':
> instance = strtoul(optarg, NULL, 0);
> break;
> + case 'f':
> + fmp_ph_params.have_header = true;
> + break;
> + case 'v':
> + fmp_ph_params.fw_version = strtoul(optarg, NULL, 0);
> + break;
> + case 'l':
> + fmp_ph_params.lowest_supported_version = strtoul(optarg, NULL, 0);
> + break;
Should we check dependencies between two options?
Let's say, '-v' is required if '-l' is provided, and
'fw_version' must be greater than 'lowest_supported_version'.
-Takahiro Akashi
> case 'p':
> if (privkey_file) {
> fprintf(stderr,
> @@ -747,11 +816,11 @@ int main(int argc, char **argv)
> if (capsule_type != CAPSULE_NORMAL_BLOB) {
> if (create_empty_capsule(argv[argc - 1], guid,
> capsule_type == CAPSULE_ACCEPT) < 0) {
> - fprintf(stderr, "Creating empty capsule failed\n");
> + fprintf(stderr, "Creating empty capsulefailed\n");
> 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
>
next prev parent reply other threads:[~2023-03-02 5:30 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-01 9:15 [PATCH v2 0/4] FMP versioning support Masahisa Kojima
2023-03-01 9:15 ` [PATCH v2 1/4] efi_loader: store firmware version into FmpState variable Masahisa Kojima
2023-03-02 5:09 ` Takahiro Akashi
2023-03-02 9:50 ` Masahisa Kojima
2023-03-03 0:17 ` Takahiro Akashi
2023-03-03 4:16 ` Masahisa Kojima
2023-03-01 9:15 ` [PATCH v2 2/4] efi_loader: versioning support in GetImageInfo Masahisa Kojima
2023-03-02 5:16 ` Takahiro Akashi
2023-03-02 10:05 ` Masahisa Kojima
2023-03-03 0:10 ` Takahiro Akashi
2023-03-03 4:15 ` Masahisa Kojima
2023-03-01 9:15 ` [PATCH v2 3/4] efi_loader: check lowest supported version in capsule update Masahisa Kojima
2023-03-01 9:15 ` [PATCH v2 4/4] mkeficapsule: add FMP Payload Header Masahisa Kojima
2023-03-02 5:29 ` Takahiro Akashi [this message]
2023-03-02 10:15 ` Masahisa Kojima
2023-03-04 1:28 ` [PATCH v2 0/4] FMP versioning support Takahiro Akashi
2023-03-06 6:08 ` Masahisa Kojima
2023-03-06 6:32 ` Takahiro Akashi
2023-03-06 7:26 ` Masahisa Kojima
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230302052949.GC44192@laputa \
--to=takahiro.akashi@linaro.org \
--cc=ilias.apalodimas@linaro.org \
--cc=masahisa.kojima@linaro.org \
--cc=u-boot@lists.denx.de \
--cc=xypron.glpk@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.