]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
mkeficapsule: add FMP Payload Header
authorMasahisa Kojima <masahisa.kojima@linaro.org>
Wed, 7 Jun 2023 05:41:56 +0000 (14:41 +0900)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Thu, 8 Jun 2023 07:20:36 +0000 (09:20 +0200)
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.kojima@linaro.org>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
doc/mkeficapsule.1
tools/eficapsule.h
tools/mkeficapsule.c

index 1ca245a10f833b581bf36dcc3076bd2ff7d8e26a..c4c2057d5c7affc3a5c25c77d3bf512a2f956aa1 100644 (file)
@@ -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
index 072a4b5598b5cf93432d9dde51a8e905c3741c8d..753fb73313bce559b2ce9e0d25a54788db3e27a2 100644 (file)
@@ -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 */
index b71537beee05ea402eb23d6ad469436eb7cfc8e6..52be1f122eecd41f24ed11d2755a612da5dd6fb6 100644 (file)
@@ -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);