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");