1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2018 Linaro Limited
4 * Author: AKASHI Takahiro
14 #include <linux/types.h>
17 #include <sys/types.h>
18 #include <uuid/uuid.h>
20 #include <gnutls/gnutls.h>
21 #include <gnutls/pkcs7.h>
22 #include <gnutls/abstract.h>
24 #include "eficapsule.h"
26 static const char *tool_name
= "mkeficapsule";
28 efi_guid_t efi_guid_fm_capsule
= EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
;
29 efi_guid_t efi_guid_cert_type_pkcs7
= EFI_CERT_TYPE_PKCS7_GUID
;
31 static const char *opts_short
= "g:i:I:v:p:c:m:o:dhARD";
34 CAPSULE_NORMAL_BLOB
= 0,
39 static struct option options
[] = {
40 {"guid", required_argument
, NULL
, 'g'},
41 {"index", required_argument
, NULL
, 'i'},
42 {"instance", required_argument
, NULL
, 'I'},
43 {"fw-version", required_argument
, NULL
, 'v'},
44 {"private-key", required_argument
, NULL
, 'p'},
45 {"certificate", required_argument
, NULL
, 'c'},
46 {"monotonic-count", required_argument
, NULL
, 'm'},
47 {"dump-sig", no_argument
, NULL
, 'd'},
48 {"fw-accept", no_argument
, NULL
, 'A'},
49 {"fw-revert", no_argument
, NULL
, 'R'},
50 {"capoemflag", required_argument
, NULL
, 'o'},
51 {"dump-capsule", no_argument
, NULL
, 'D'},
52 {"help", no_argument
, NULL
, 'h'},
56 static void print_usage(void)
58 fprintf(stderr
, "Usage: %s [options] <image blob> <output file>\n"
61 "\t-g, --guid <guid string> guid for image blob type\n"
62 "\t-i, --index <index> update image index\n"
63 "\t-I, --instance <instance> update hardware instance\n"
64 "\t-v, --fw-version <version> firmware version\n"
65 "\t-p, --private-key <privkey file> private key file\n"
66 "\t-c, --certificate <cert file> signer's certificate file\n"
67 "\t-m, --monotonic-count <count> monotonic count\n"
68 "\t-d, --dump_sig dump signature (*.p7)\n"
69 "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n"
70 "\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n"
71 "\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n"
72 "\t-D, --dump-capsule dump the contents of the capsule headers\n"
73 "\t-h, --help print a help message\n",
78 * auth_context - authentication context
79 * @key_file: Path to a private key file
80 * @cert_file: Path to a certificate file
81 * @image_data: Pointer to firmware data
82 * @image_size: Size of firmware data
83 * @auth: Authentication header
84 * @sig_data: Signature data
85 * @sig_size: Size of signature data
87 * Data structure used in create_auth_data(). @key_file through
88 * @image_size are input parameters. @auth, @sig_data and @sig_size
89 * are filled in by create_auth_data().
96 struct efi_firmware_image_authentication auth
;
104 * read_bin_file - read a firmware binary file
105 * @bin: Path to a firmware binary file
106 * @data: Pointer to pointer of allocated buffer
107 * @bin_size: Size of allocated buffer
109 * Read out a content of binary, @bin, into @data.
110 * A caller should free @data.
116 static int read_bin_file(char *bin
, uint8_t **data
, off_t
*bin_size
)
119 struct stat bin_stat
;
126 fprintf(stderr
, "cannot open %s\n", bin
);
129 if (stat(bin
, &bin_stat
) < 0) {
130 fprintf(stderr
, "cannot determine the size of %s\n", bin
);
134 if (bin_stat
.st_size
> SIZE_MAX
) {
135 fprintf(stderr
, "file size is too large for malloc: %s\n", bin
);
139 buf
= malloc(bin_stat
.st_size
);
141 fprintf(stderr
, "cannot allocate memory: %zx\n",
142 (size_t)bin_stat
.st_size
);
147 size
= fread(buf
, 1, bin_stat
.st_size
, g
);
148 if (size
< bin_stat
.st_size
) {
149 fprintf(stderr
, "read failed (%zx)\n", size
);
155 *bin_size
= bin_stat
.st_size
;
163 * write_capsule_file - write a capsule file
165 * @data: Pointer to data
166 * @bin_size: Size of data
168 * Write out data, @data, with the size @bin_size.
174 static int write_capsule_file(FILE *f
, void *data
, size_t size
, const char *msg
)
178 size_written
= fwrite(data
, 1, size
, f
);
179 if (size_written
< size
) {
180 fprintf(stderr
, "%s: write failed (%zx != %zx)\n", msg
,
189 * create_auth_data - compose authentication data in capsule
190 * @auth_context: Pointer to authentication context
192 * Fill up an authentication header (.auth) and signature data (.sig_data)
193 * in @auth_context, using library functions from openssl.
194 * All the parameters in @auth_context must be filled in by a caller.
200 static int create_auth_data(struct auth_context
*ctx
)
205 gnutls_privkey_t pkey
;
206 gnutls_x509_crt_t x509
;
207 gnutls_pkcs7_t pkcs7
;
209 gnutls_datum_t signature
;
212 ret
= read_bin_file(ctx
->cert_file
, &cert
.data
, &file_size
);
215 if (file_size
> UINT_MAX
)
217 cert
.size
= file_size
;
219 ret
= read_bin_file(ctx
->key_file
, &key
.data
, &file_size
);
222 if (file_size
> UINT_MAX
)
224 key
.size
= file_size
;
228 * gnutls_global_set_time_function(mytime);
229 * gnutls_global_set_log_function(tls_log_func);
230 * gnutls_global_set_log_level(6);
233 ret
= gnutls_privkey_init(&pkey
);
235 fprintf(stderr
, "error in gnutls_privkey_init(): %s\n",
236 gnutls_strerror(ret
));
240 ret
= gnutls_x509_crt_init(&x509
);
242 fprintf(stderr
, "error in gnutls_x509_crt_init(): %s\n",
243 gnutls_strerror(ret
));
247 /* load a private key */
248 ret
= gnutls_privkey_import_x509_raw(pkey
, &key
, GNUTLS_X509_FMT_PEM
,
252 "error in gnutls_privkey_import_x509_raw(): %s\n",
253 gnutls_strerror(ret
));
257 /* load x509 certificate */
258 ret
= gnutls_x509_crt_import(x509
, &cert
, GNUTLS_X509_FMT_PEM
);
260 fprintf(stderr
, "error in gnutls_x509_crt_import(): %s\n",
261 gnutls_strerror(ret
));
265 /* generate a PKCS #7 structure */
266 ret
= gnutls_pkcs7_init(&pkcs7
);
268 fprintf(stderr
, "error in gnutls_pkcs7_init(): %s\n",
269 gnutls_strerror(ret
));
279 * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
281 data
.size
= ctx
->image_size
+ sizeof(ctx
->auth
.monotonic_count
);
282 data
.data
= malloc(data
.size
);
284 fprintf(stderr
, "allocating memory (0x%x) failed\n", data
.size
);
287 memcpy(data
.data
, ctx
->image_data
, ctx
->image_size
);
288 memcpy(data
.data
+ ctx
->image_size
, &ctx
->auth
.monotonic_count
,
289 sizeof(ctx
->auth
.monotonic_count
));
291 ret
= gnutls_pkcs7_sign(pkcs7
, x509
, pkey
, &data
, NULL
, NULL
,
293 /* GNUTLS_PKCS7_EMBED_DATA? */
294 GNUTLS_PKCS7_INCLUDE_CERT
|
295 GNUTLS_PKCS7_INCLUDE_TIME
);
297 fprintf(stderr
, "error in gnutls_pkcs7)sign(): %s\n",
298 gnutls_strerror(ret
));
303 ret
= gnutls_pkcs7_export2(pkcs7
, GNUTLS_X509_FMT_DER
, &signature
);
305 fprintf(stderr
, "error in gnutls_pkcs7_export2: %s\n",
306 gnutls_strerror(ret
));
309 ctx
->sig_data
= signature
.data
;
310 ctx
->sig_size
= signature
.size
;
313 ctx
->auth
.auth_info
.hdr
.dwLength
= sizeof(ctx
->auth
.auth_info
)
315 ctx
->auth
.auth_info
.hdr
.wRevision
= WIN_CERT_REVISION_2_0
;
316 ctx
->auth
.auth_info
.hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
317 memcpy(&ctx
->auth
.auth_info
.cert_type
, &efi_guid_cert_type_pkcs7
,
318 sizeof(efi_guid_cert_type_pkcs7
));
321 * For better clean-ups,
322 * gnutls_pkcs7_deinit(pkcs7);
323 * gnutls_privkey_deinit(pkey);
324 * gnutls_x509_crt_deinit(x509);
328 * gnutls_free(signature.data);
335 * dump_signature - dump out a signature
336 * @path: Path to a capsule file
337 * @signature: Signature data
338 * @sig_size: Size of signature data
340 * Signature data pointed to by @signature will be saved into
341 * a file whose file name is @path with ".p7" suffix.
347 static int dump_signature(const char *path
, uint8_t *signature
, size_t sig_size
)
354 sig_path
= malloc(strlen(path
) + 3 + 1);
358 sprintf(sig_path
, "%s.p7", path
);
359 f
= fopen(sig_path
, "w");
363 size
= fwrite(signature
, 1, sig_size
, f
);
364 if (size
== sig_size
)
374 * free_sig_data - free out signature data
375 * @ctx: Pointer to authentication context
377 * Free signature data allocated in create_auth_data().
379 static void free_sig_data(struct auth_context
*ctx
)
382 gnutls_free(ctx
->sig_data
);
386 * create_fwbin - create an uefi capsule file
387 * @path: Path to a created capsule file
388 * @bin: Path to a firmware binary to encapsulate
389 * @guid: GUID of related FMP driver
390 * @index: Index number in capsule
391 * @instance: Instance number in capsule
392 * @mcount: Monotonic count in authentication information
393 * @private_file: Path to a private key file
394 * @cert_file: Path to a certificate file
395 * @oemflags: Capsule OEM Flags, bits 0-15
397 * This function actually does the job of creating an uefi capsule file.
398 * All the arguments must be supplied.
399 * If either @private_file ror @cert_file is NULL, the capsule file
406 static int create_fwbin(char *path
, char *bin
, efi_guid_t
*guid
,
407 unsigned long index
, unsigned long instance
,
408 struct fmp_payload_header_params
*fmp_ph_params
,
409 uint64_t mcount
, char *privkey_file
, char *cert_file
,
412 struct efi_capsule_header header
;
413 struct efi_firmware_management_capsule_header capsule
;
414 struct efi_firmware_management_capsule_image_header image
;
415 struct auth_context auth_context
;
417 uint8_t *data
, *new_data
, *buf
;
421 struct fmp_payload_header payload_header
;
424 fprintf(stderr
, "For output: %s\n", path
);
425 fprintf(stderr
, "\tbin: %s\n\ttype: %pUl\n", bin
, guid
);
426 fprintf(stderr
, "\tindex: %lu\n\tinstance: %lu\n", index
, instance
);
428 auth_context
.sig_size
= 0;
435 * read a firmware binary
437 if (read_bin_file(bin
, &data
, &bin_size
))
442 /* insert fmp payload header right before the payload */
443 if (fmp_ph_params
->have_header
) {
444 new_data
= malloc(bin_size
+ sizeof(payload_header
));
448 payload_header
.signature
= FMP_PAYLOAD_HDR_SIGNATURE
;
449 payload_header
.header_size
= sizeof(payload_header
);
450 payload_header
.fw_version
= fmp_ph_params
->fw_version
;
451 payload_header
.lowest_supported_version
= 0; /* not used */
452 memcpy(new_data
, &payload_header
, sizeof(payload_header
));
453 memcpy(new_data
+ sizeof(payload_header
), data
, bin_size
);
455 bin_size
+= sizeof(payload_header
);
458 /* first, calculate signature to determine its size */
459 if (privkey_file
&& cert_file
) {
460 auth_context
.key_file
= privkey_file
;
461 auth_context
.cert_file
= cert_file
;
462 auth_context
.auth
.monotonic_count
= mcount
;
463 auth_context
.image_data
= buf
;
464 auth_context
.image_size
= bin_size
;
466 if (create_auth_data(&auth_context
)) {
467 fprintf(stderr
, "Signing firmware image failed\n");
472 dump_signature(path
, auth_context
.sig_data
,
473 auth_context
.sig_size
)) {
474 fprintf(stderr
, "Creating signature file failed\n");
480 * write a capsule file
482 f
= fopen(path
, "w");
484 fprintf(stderr
, "cannot open %s\n", path
);
489 * capsule file header
491 header
.capsule_guid
= efi_guid_fm_capsule
;
492 header
.header_size
= sizeof(header
);
493 /* TODO: The current implementation ignores flags */
494 header
.flags
= CAPSULE_FLAGS_PERSIST_ACROSS_RESET
;
496 header
.flags
|= oemflags
;
497 header
.capsule_image_size
= sizeof(header
)
498 + sizeof(capsule
) + sizeof(uint64_t)
501 if (auth_context
.sig_size
)
502 header
.capsule_image_size
+= sizeof(auth_context
.auth
)
503 + auth_context
.sig_size
;
504 if (write_capsule_file(f
, &header
, sizeof(header
),
509 * firmware capsule header
510 * This capsule has only one firmware capsule image.
512 capsule
.version
= 0x00000001;
513 capsule
.embedded_driver_count
= 0;
514 capsule
.payload_item_count
= 1;
515 if (write_capsule_file(f
, &capsule
, sizeof(capsule
),
516 "Firmware capsule header"))
519 offset
= sizeof(capsule
) + sizeof(uint64_t);
520 if (write_capsule_file(f
, &offset
, sizeof(offset
),
521 "Offset to capsule image"))
525 * firmware capsule image header
527 image
.version
= 0x00000003;
528 memcpy(&image
.update_image_type_id
, guid
, sizeof(*guid
));
529 image
.update_image_index
= index
;
530 image
.reserved
[0] = 0;
531 image
.reserved
[1] = 0;
532 image
.reserved
[2] = 0;
533 image
.update_image_size
= bin_size
;
534 if (auth_context
.sig_size
)
535 image
.update_image_size
+= sizeof(auth_context
.auth
)
536 + auth_context
.sig_size
;
537 image
.update_vendor_code_size
= 0; /* none */
538 image
.update_hardware_instance
= instance
;
539 image
.image_capsule_support
= 0;
540 if (auth_context
.sig_size
)
541 image
.image_capsule_support
|= CAPSULE_SUPPORT_AUTHENTICATION
;
542 if (write_capsule_file(f
, &image
, sizeof(image
),
543 "Firmware capsule image header"))
549 if (auth_context
.sig_size
) {
550 if (write_capsule_file(f
, &auth_context
.auth
,
551 sizeof(auth_context
.auth
),
552 "Authentication header"))
555 if (write_capsule_file(f
, auth_context
.sig_data
,
556 auth_context
.sig_size
, "Signature"))
563 if (write_capsule_file(f
, buf
, bin_size
, "Firmware binary"))
570 free_sig_data(&auth_context
);
578 * convert_uuid_to_guid() - convert UUID to GUID
581 * UUID and GUID have the same data structure, but their binary
582 * formats are different due to the endianness. See lib/uuid.c.
583 * Since uuid_parse() can handle only UUID, this function must
584 * be called to get correct data for GUID when parsing a string.
586 * The correct data will be returned in @buf.
588 void convert_uuid_to_guid(unsigned char *buf
)
608 static int create_empty_capsule(char *path
, efi_guid_t
*guid
, bool fw_accept
)
610 struct efi_capsule_header header
= { 0 };
613 efi_guid_t fw_accept_guid
= FW_ACCEPT_OS_GUID
;
614 efi_guid_t fw_revert_guid
= FW_REVERT_OS_GUID
;
615 efi_guid_t capsule_guid
;
617 f
= fopen(path
, "w");
619 fprintf(stderr
, "cannot open %s\n", path
);
623 capsule_guid
= fw_accept
? fw_accept_guid
: fw_revert_guid
;
625 memcpy(&header
.capsule_guid
, &capsule_guid
, sizeof(efi_guid_t
));
626 header
.header_size
= sizeof(header
);
629 header
.capsule_image_size
= fw_accept
?
630 sizeof(header
) + sizeof(efi_guid_t
) : sizeof(header
);
632 if (write_capsule_file(f
, &header
, sizeof(header
),
637 if (write_capsule_file(f
, guid
, sizeof(*guid
),
638 "FW Accept Capsule Payload"))
651 static void print_guid(void *ptr
)
654 efi_guid_t
*guid
= ptr
;
655 const uint8_t seq
[] = {
656 3, 2, 1, 0, '-', 5, 4, '-', 7, 6,
657 '-', 8, 9, '-', 10, 11, 12, 13, 14, 15 };
659 for (i
= 0; i
< ARRAY_SIZE(seq
); i
++) {
663 printf("%02X", guid
->b
[seq
[i
]]);
669 static uint32_t dump_fmp_payload_header(
670 struct fmp_payload_header
*fmp_payload_hdr
)
672 if (fmp_payload_hdr
->signature
== FMP_PAYLOAD_HDR_SIGNATURE
) {
673 printf("--------\n");
674 printf("FMP_PAYLOAD_HDR.SIGNATURE\t\t\t: %08X\n",
675 FMP_PAYLOAD_HDR_SIGNATURE
);
676 printf("FMP_PAYLOAD_HDR.HEADER_SIZE\t\t\t: %08X\n",
677 fmp_payload_hdr
->header_size
);
678 printf("FMP_PAYLOAD_HDR.FW_VERSION\t\t\t: %08X\n",
679 fmp_payload_hdr
->fw_version
);
680 printf("FMP_PAYLOAD_HDR.LOWEST_SUPPORTED_VERSION\t: %08X\n",
681 fmp_payload_hdr
->lowest_supported_version
);
682 return fmp_payload_hdr
->header_size
;
688 static void dump_capsule_auth_header(
689 struct efi_firmware_image_authentication
*capsule_auth_hdr
)
691 printf("EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT\t\t: %08lX\n",
692 capsule_auth_hdr
->monotonic_count
);
693 printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.dwLENGTH\t: %08X\n",
694 capsule_auth_hdr
->auth_info
.hdr
.dwLength
);
695 printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION\t: %08X\n",
696 capsule_auth_hdr
->auth_info
.hdr
.wRevision
);
697 printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE\t: %08X\n",
698 capsule_auth_hdr
->auth_info
.hdr
.wCertificateType
);
699 printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE\t: ");
700 print_guid(&capsule_auth_hdr
->auth_info
.cert_type
);
703 static void dump_fmp_capsule_image_header(
704 struct efi_firmware_management_capsule_image_header
*image_hdr
)
706 void *capsule_auth_hdr
;
707 void *fmp_payload_hdr
;
708 uint64_t signature_size
= 0;
709 uint32_t payload_size
= 0;
710 uint32_t fmp_payload_hdr_size
= 0;
711 struct efi_firmware_image_authentication
*auth_hdr
;
713 printf("--------\n");
714 printf("FMP_CAPSULE_IMAGE_HDR.VERSION\t\t\t: %08X\n",
716 printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID\t: ");
717 print_guid(&image_hdr
->update_image_type_id
);
718 printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX\t: %08X\n",
719 image_hdr
->update_image_index
);
720 printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_SIZE\t\t: %08X\n",
721 image_hdr
->update_image_size
);
722 printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_VENDOR_CODE_SIZE\t: %08X\n",
723 image_hdr
->update_vendor_code_size
);
724 printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_HARDWARE_INSTANCE\t: %08lX\n",
725 image_hdr
->update_hardware_instance
);
726 printf("FMP_CAPSULE_IMAGE_HDR.IMAGE_CAPSULE_SUPPORT\t: %08lX\n",
727 image_hdr
->image_capsule_support
);
729 printf("--------\n");
730 if (image_hdr
->image_capsule_support
& CAPSULE_SUPPORT_AUTHENTICATION
) {
731 capsule_auth_hdr
= (char *)image_hdr
+ sizeof(*image_hdr
);
732 dump_capsule_auth_header(capsule_auth_hdr
);
734 auth_hdr
= capsule_auth_hdr
;
735 signature_size
= sizeof(auth_hdr
->monotonic_count
) +
736 auth_hdr
->auth_info
.hdr
.dwLength
;
737 fmp_payload_hdr
= (char *)capsule_auth_hdr
+ signature_size
;
739 printf("Capsule Authentication Not Enabled\n");
740 fmp_payload_hdr
= (char *)image_hdr
+ sizeof(*image_hdr
);
743 fmp_payload_hdr_size
= dump_fmp_payload_header(fmp_payload_hdr
);
745 payload_size
= image_hdr
->update_image_size
- signature_size
-
746 fmp_payload_hdr_size
;
747 printf("--------\n");
748 printf("Payload Image Size\t\t\t\t: %08X\n", payload_size
);
751 static void dump_fmp_header(
752 struct efi_firmware_management_capsule_header
*fmp_hdr
)
755 void *capsule_image_hdr
;
757 printf("EFI_FMP_HDR.VERSION\t\t\t\t: %08X\n", fmp_hdr
->version
);
758 printf("EFI_FMP_HDR.EMBEDDED_DRIVER_COUNT\t\t: %08X\n",
759 fmp_hdr
->embedded_driver_count
);
760 printf("EFI_FMP_HDR.PAYLOAD_ITEM_COUNT\t\t\t: %08X\n",
761 fmp_hdr
->payload_item_count
);
764 * We currently don't support Embedded Drivers.
765 * Only worry about the payload items.
767 for (i
= 0; i
< fmp_hdr
->payload_item_count
; i
++) {
768 capsule_image_hdr
= (char *)fmp_hdr
+
769 fmp_hdr
->item_offset_list
[i
];
770 dump_fmp_capsule_image_header(capsule_image_hdr
);
774 static void dump_capsule_header(struct efi_capsule_header
*capsule_hdr
)
776 printf("EFI_CAPSULE_HDR.CAPSULE_GUID\t\t\t: ");
777 print_guid((void *)&capsule_hdr
->capsule_guid
);
778 printf("EFI_CAPSULE_HDR.HEADER_SIZE\t\t\t: %08X\n",
779 capsule_hdr
->header_size
);
780 printf("EFI_CAPSULE_HDR.FLAGS\t\t\t\t: %08X\n", capsule_hdr
->flags
);
781 printf("EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE\t\t: %08X\n",
782 capsule_hdr
->capsule_image_size
);
785 static void normal_capsule_dump(void *capsule_buf
)
788 struct efi_capsule_header
*hdr
= capsule_buf
;
790 dump_capsule_header(hdr
);
791 printf("--------\n");
793 fmp_hdr
= (char *)capsule_buf
+ sizeof(*hdr
);
794 dump_fmp_header(fmp_hdr
);
797 static void empty_capsule_dump(void *capsule_buf
)
799 efi_guid_t
*accept_image_guid
;
800 struct efi_capsule_header
*hdr
= capsule_buf
;
801 efi_guid_t efi_empty_accept_capsule
= FW_ACCEPT_OS_GUID
;
803 dump_capsule_header(hdr
);
805 if (!memcmp(&efi_empty_accept_capsule
, &hdr
->capsule_guid
,
806 sizeof(efi_guid_t
))) {
807 accept_image_guid
= (void *)(char *)capsule_buf
+
808 sizeof(struct efi_capsule_header
);
809 printf("--------\n");
810 printf("ACCEPT_IMAGE_GUID\t\t\t\t: ");
811 print_guid(accept_image_guid
);
815 static void dump_capsule_contents(char *capsule_file
)
819 efi_guid_t efi_fmp_guid
= EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID
;
820 efi_guid_t efi_empty_accept_capsule
= FW_ACCEPT_OS_GUID
;
821 efi_guid_t efi_empty_revert_capsule
= FW_REVERT_OS_GUID
;
825 fprintf(stderr
, "No capsule file provided\n");
829 if ((fd
= open(capsule_file
, O_RDONLY
)) < 0) {
830 fprintf(stderr
, "Error opening capsule file: %s\n",
835 if (fstat(fd
, &sbuf
) < 0) {
836 fprintf(stderr
, "Can't stat capsule file: %s\n", capsule_file
);
840 if ((ptr
= mmap(0, sbuf
.st_size
, PROT_READ
, MAP_SHARED
, fd
, 0))
842 fprintf(stderr
, "Can't mmap capsule file: %s\n", capsule_file
);
846 if (!memcmp(&efi_fmp_guid
, ptr
, sizeof(efi_guid_t
))) {
847 normal_capsule_dump(ptr
);
848 } else if (!memcmp(&efi_empty_accept_capsule
, ptr
,
849 sizeof(efi_guid_t
)) ||
850 !memcmp(&efi_empty_revert_capsule
, ptr
,
851 sizeof(efi_guid_t
))) {
852 empty_capsule_dump(ptr
);
854 fprintf(stderr
, "Unable to decode the capsule file: %s\n",
861 * main - main entry function of mkeficapsule
862 * @argc: Number of arguments
863 * @argv: Array of pointers to arguments
865 * Create an uefi capsule file, optionally signing it.
866 * Parse all the arguments and pass them on to create_fwbin().
872 int main(int argc
, char **argv
)
875 unsigned char uuid_buf
[16];
876 unsigned long index
, instance
;
878 unsigned long oemflags
;
880 char *privkey_file
, *cert_file
;
882 struct fmp_payload_header_params fmp_ph_params
= { 0 };
890 capsule_dump
= false;
892 capsule_type
= CAPSULE_NORMAL_BLOB
;
895 c
= getopt_long(argc
, argv
, opts_short
, options
, &idx
);
903 "Image type already specified\n");
906 if (uuid_parse(optarg
, uuid_buf
)) {
907 fprintf(stderr
, "Wrong guid format\n");
910 convert_uuid_to_guid(uuid_buf
);
911 guid
= (efi_guid_t
*)uuid_buf
;
914 index
= strtoul(optarg
, NULL
, 0);
917 instance
= strtoul(optarg
, NULL
, 0);
920 fmp_ph_params
.fw_version
= strtoul(optarg
, NULL
, 0);
921 fmp_ph_params
.have_header
= true;
926 "Private Key already specified\n");
929 privkey_file
= optarg
;
934 "Certificate file already specified\n");
940 mcount
= strtoul(optarg
, NULL
, 0);
948 "Select either of Accept or Revert capsule generation\n");
951 capsule_type
= CAPSULE_ACCEPT
;
956 "Select either of Accept or Revert capsule generation\n");
959 capsule_type
= CAPSULE_REVERT
;
962 oemflags
= strtoul(optarg
, NULL
, 0);
963 if (oemflags
> 0xffff) {
965 "oemflags must be between 0x0 and 0xffff\n");
979 if (argc
!= optind
+ 1) {
980 fprintf(stderr
, "Must provide the capsule file to parse\n");
983 dump_capsule_contents(argv
[argc
- 1]);
987 /* check necessary parameters */
988 if ((capsule_type
== CAPSULE_NORMAL_BLOB
&&
989 ((argc
!= optind
+ 2) || !guid
||
990 ((privkey_file
&& !cert_file
) ||
991 (!privkey_file
&& cert_file
)))) ||
992 (capsule_type
!= CAPSULE_NORMAL_BLOB
&&
993 ((argc
!= optind
+ 1) ||
994 ((capsule_type
== CAPSULE_ACCEPT
) && !guid
) ||
995 ((capsule_type
== CAPSULE_REVERT
) && guid
)))) {
1000 if (capsule_type
!= CAPSULE_NORMAL_BLOB
) {
1001 if (create_empty_capsule(argv
[argc
- 1], guid
,
1002 capsule_type
== CAPSULE_ACCEPT
) < 0) {
1003 fprintf(stderr
, "Creating empty capsule failed\n");
1006 } else if (create_fwbin(argv
[argc
- 1], argv
[argc
- 2], guid
,
1007 index
, instance
, &fmp_ph_params
, mcount
, privkey_file
,
1008 cert_file
, (uint16_t)oemflags
) < 0) {
1009 fprintf(stderr
, "Creating firmware capsule failed\n");