board: starfive: support Milk-V Mars board
[pandora-u-boot.git] / tools / mkeficapsule.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2018 Linaro Limited
4  *              Author: AKASHI Takahiro
5  */
6
7 #include <getopt.h>
8 #include <pe.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <linux/types.h>
15
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <uuid/uuid.h>
19
20 #include <gnutls/gnutls.h>
21 #include <gnutls/pkcs7.h>
22 #include <gnutls/abstract.h>
23
24 #include "eficapsule.h"
25
26 static const char *tool_name = "mkeficapsule";
27
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;
30
31 static const char *opts_short = "g:i:I:v:p:c:m:o:dhARD";
32
33 enum {
34         CAPSULE_NORMAL_BLOB = 0,
35         CAPSULE_ACCEPT,
36         CAPSULE_REVERT,
37 } capsule_type;
38
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'},
53         {NULL, 0, NULL, 0},
54 };
55
56 static void print_usage(void)
57 {
58         fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n"
59                 "Options:\n"
60
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",
74                 tool_name);
75 }
76
77 /**
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
86  *
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().
90  */
91 struct auth_context {
92         char *key_file;
93         char *cert_file;
94         uint8_t *image_data;
95         size_t image_size;
96         struct efi_firmware_image_authentication auth;
97         uint8_t *sig_data;
98         size_t sig_size;
99 };
100
101 static int dump_sig;
102
103 /**
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
108  *
109  * Read out a content of binary, @bin, into @data.
110  * A caller should free @data.
111  *
112  * Return:
113  * * 0  - on success
114  * * -1 - on failure
115  */
116 static int read_bin_file(char *bin, uint8_t **data, off_t *bin_size)
117 {
118         FILE *g;
119         struct stat bin_stat;
120         void *buf;
121         size_t size;
122         int ret = 0;
123
124         g = fopen(bin, "r");
125         if (!g) {
126                 fprintf(stderr, "cannot open %s\n", bin);
127                 return -1;
128         }
129         if (stat(bin, &bin_stat) < 0) {
130                 fprintf(stderr, "cannot determine the size of %s\n", bin);
131                 ret = -1;
132                 goto err;
133         }
134         if (bin_stat.st_size > SIZE_MAX) {
135                 fprintf(stderr, "file size is too large for malloc: %s\n", bin);
136                 ret = -1;
137                 goto err;
138         }
139         buf = malloc(bin_stat.st_size);
140         if (!buf) {
141                 fprintf(stderr, "cannot allocate memory: %zx\n",
142                         (size_t)bin_stat.st_size);
143                 ret = -1;
144                 goto err;
145         }
146
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);
150                 ret = -1;
151                 goto err;
152         }
153
154         *data = buf;
155         *bin_size = bin_stat.st_size;
156 err:
157         fclose(g);
158
159         return ret;
160 }
161
162 /**
163  * write_capsule_file - write a capsule file
164  * @bin:        FILE stream
165  * @data:       Pointer to data
166  * @bin_size:   Size of data
167  *
168  * Write out data, @data, with the size @bin_size.
169  *
170  * Return:
171  * * 0  - on success
172  * * -1 - on failure
173  */
174 static int write_capsule_file(FILE *f, void *data, size_t size, const char *msg)
175 {
176         size_t size_written;
177
178         size_written = fwrite(data, 1, size, f);
179         if (size_written < size) {
180                 fprintf(stderr, "%s: write failed (%zx != %zx)\n", msg,
181                         size_written, size);
182                 return -1;
183         }
184
185         return 0;
186 }
187
188 /**
189  * create_auth_data - compose authentication data in capsule
190  * @auth_context:       Pointer to authentication context
191  *
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.
195  *
196  * Return:
197  * * 0  - on success
198  * * -1 - on failure
199  */
200 static int create_auth_data(struct auth_context *ctx)
201 {
202         gnutls_datum_t cert;
203         gnutls_datum_t key;
204         off_t file_size;
205         gnutls_privkey_t pkey;
206         gnutls_x509_crt_t x509;
207         gnutls_pkcs7_t pkcs7;
208         gnutls_datum_t data;
209         gnutls_datum_t signature;
210         int ret;
211
212         ret = read_bin_file(ctx->cert_file, &cert.data, &file_size);
213         if (ret < 0)
214                 return -1;
215         if (file_size > UINT_MAX)
216                 return -1;
217         cert.size = file_size;
218
219         ret = read_bin_file(ctx->key_file, &key.data, &file_size);
220         if (ret < 0)
221                 return -1;
222         if (file_size > UINT_MAX)
223                 return -1;
224         key.size = file_size;
225
226         /*
227          * For debugging,
228          * gnutls_global_set_time_function(mytime);
229          * gnutls_global_set_log_function(tls_log_func);
230          * gnutls_global_set_log_level(6);
231          */
232
233         ret = gnutls_privkey_init(&pkey);
234         if (ret < 0) {
235                 fprintf(stderr, "error in gnutls_privkey_init(): %s\n",
236                         gnutls_strerror(ret));
237                 return -1;
238         }
239
240         ret = gnutls_x509_crt_init(&x509);
241         if (ret < 0) {
242                 fprintf(stderr, "error in gnutls_x509_crt_init(): %s\n",
243                         gnutls_strerror(ret));
244                 return -1;
245         }
246
247         /* load a private key */
248         ret = gnutls_privkey_import_x509_raw(pkey, &key, GNUTLS_X509_FMT_PEM,
249                                              0, 0);
250         if (ret < 0) {
251                 fprintf(stderr,
252                         "error in gnutls_privkey_import_x509_raw(): %s\n",
253                         gnutls_strerror(ret));
254                 return -1;
255         }
256
257         /* load x509 certificate */
258         ret = gnutls_x509_crt_import(x509, &cert, GNUTLS_X509_FMT_PEM);
259         if (ret < 0) {
260                 fprintf(stderr, "error in gnutls_x509_crt_import(): %s\n",
261                         gnutls_strerror(ret));
262                 return -1;
263         }
264
265         /* generate a PKCS #7 structure */
266         ret = gnutls_pkcs7_init(&pkcs7);
267         if (ret < 0) {
268                 fprintf(stderr, "error in gnutls_pkcs7_init(): %s\n",
269                         gnutls_strerror(ret));
270                 return -1;
271         }
272
273         /* sign */
274         /*
275          * Data should have
276          *  * firmware image
277          *  * monotonic count
278          * in this order!
279          * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
280          */
281         data.size = ctx->image_size + sizeof(ctx->auth.monotonic_count);
282         data.data = malloc(data.size);
283         if (!data.data) {
284                 fprintf(stderr, "allocating memory (0x%x) failed\n", data.size);
285                 return -1;
286         }
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));
290
291         ret = gnutls_pkcs7_sign(pkcs7, x509, pkey, &data, NULL, NULL,
292                                 GNUTLS_DIG_SHA256,
293                                 /* GNUTLS_PKCS7_EMBED_DATA? */
294                                 GNUTLS_PKCS7_INCLUDE_CERT |
295                                 GNUTLS_PKCS7_INCLUDE_TIME);
296         if (ret < 0) {
297                 fprintf(stderr, "error in gnutls_pkcs7)sign(): %s\n",
298                         gnutls_strerror(ret));
299                 return -1;
300         }
301
302         /* export */
303         ret = gnutls_pkcs7_export2(pkcs7, GNUTLS_X509_FMT_DER, &signature);
304         if (ret < 0) {
305                 fprintf(stderr, "error in gnutls_pkcs7_export2: %s\n",
306                         gnutls_strerror(ret));
307                 return -1;
308         }
309         ctx->sig_data = signature.data;
310         ctx->sig_size = signature.size;
311
312         /* fill auth_info */
313         ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
314                                                 + ctx->sig_size;
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));
319
320         /*
321          * For better clean-ups,
322          * gnutls_pkcs7_deinit(pkcs7);
323          * gnutls_privkey_deinit(pkey);
324          * gnutls_x509_crt_deinit(x509);
325          * free(cert.data);
326          * free(key.data);
327          * if error
328          *   gnutls_free(signature.data);
329          */
330
331         return 0;
332 }
333
334 /**
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
339  *
340  * Signature data pointed to by @signature will be saved into
341  * a file whose file name is @path with ".p7" suffix.
342  *
343  * Return:
344  * * 0  - on success
345  * * -1 - on failure
346  */
347 static int dump_signature(const char *path, uint8_t *signature, size_t sig_size)
348 {
349         char *sig_path;
350         FILE *f;
351         size_t size;
352         int ret = -1;
353
354         sig_path = malloc(strlen(path) + 3 + 1);
355         if (!sig_path)
356                 return ret;
357
358         sprintf(sig_path, "%s.p7", path);
359         f = fopen(sig_path, "w");
360         if (!f)
361                 goto err;
362
363         size = fwrite(signature, 1, sig_size, f);
364         if (size == sig_size)
365                 ret = 0;
366
367         fclose(f);
368 err:
369         free(sig_path);
370         return ret;
371 }
372
373 /**
374  * free_sig_data - free out signature data
375  * @ctx:        Pointer to authentication context
376  *
377  * Free signature data allocated in create_auth_data().
378  */
379 static void free_sig_data(struct auth_context *ctx)
380 {
381         if (ctx->sig_size)
382                 gnutls_free(ctx->sig_data);
383 }
384
385 /**
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
396  *
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
400  * won't be signed.
401  *
402  * Return:
403  * * 0  - on success
404  * * -1 - on failure
405  */
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,
410                         uint16_t oemflags)
411 {
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;
416         FILE *f;
417         uint8_t *data, *new_data, *buf;
418         off_t bin_size;
419         uint64_t offset;
420         int ret;
421         struct fmp_payload_header payload_header;
422
423 #ifdef DEBUG
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);
427 #endif
428         auth_context.sig_size = 0;
429         f = NULL;
430         data = NULL;
431         new_data = NULL;
432         ret = -1;
433
434         /*
435          * read a firmware binary
436          */
437         if (read_bin_file(bin, &data, &bin_size))
438                 goto err;
439
440         buf = data;
441
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));
445                 if (!new_data)
446                         goto err;
447
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);
454                 buf = new_data;
455                 bin_size += sizeof(payload_header);
456         }
457
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;
465
466                 if (create_auth_data(&auth_context)) {
467                         fprintf(stderr, "Signing firmware image failed\n");
468                         goto err;
469                 }
470
471                 if (dump_sig &&
472                     dump_signature(path, auth_context.sig_data,
473                                    auth_context.sig_size)) {
474                         fprintf(stderr, "Creating signature file failed\n");
475                         goto err;
476                 }
477         }
478
479         /*
480          * write a capsule file
481          */
482         f = fopen(path, "w");
483         if (!f) {
484                 fprintf(stderr, "cannot open %s\n", path);
485                 goto err;
486         }
487
488         /*
489          * capsule file header
490          */
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;
495         if (oemflags)
496                 header.flags |= oemflags;
497         header.capsule_image_size = sizeof(header)
498                                         + sizeof(capsule) + sizeof(uint64_t)
499                                         + sizeof(image)
500                                         + bin_size;
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),
505                                "Capsule header"))
506                 goto err;
507
508         /*
509          * firmware capsule header
510          * This capsule has only one firmware capsule image.
511          */
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"))
517                 goto err;
518
519         offset = sizeof(capsule) + sizeof(uint64_t);
520         if (write_capsule_file(f, &offset, sizeof(offset),
521                                "Offset to capsule image"))
522                 goto err;
523
524         /*
525          * firmware capsule image header
526          */
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"))
544                 goto err;
545
546         /*
547          * signature
548          */
549         if (auth_context.sig_size) {
550                 if (write_capsule_file(f, &auth_context.auth,
551                                        sizeof(auth_context.auth),
552                                        "Authentication header"))
553                         goto err;
554
555                 if (write_capsule_file(f, auth_context.sig_data,
556                                        auth_context.sig_size, "Signature"))
557                         goto err;
558         }
559
560         /*
561          * firmware binary
562          */
563         if (write_capsule_file(f, buf, bin_size, "Firmware binary"))
564                 goto err;
565
566         ret = 0;
567 err:
568         if (f)
569                 fclose(f);
570         free_sig_data(&auth_context);
571         free(data);
572         free(new_data);
573
574         return ret;
575 }
576
577 /**
578  * convert_uuid_to_guid() - convert UUID to GUID
579  * @buf:        UUID binary
580  *
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.
585  *
586  * The correct data will be returned in @buf.
587  */
588 void convert_uuid_to_guid(unsigned char *buf)
589 {
590         unsigned char c;
591
592         c = buf[0];
593         buf[0] = buf[3];
594         buf[3] = c;
595         c = buf[1];
596         buf[1] = buf[2];
597         buf[2] = c;
598
599         c = buf[4];
600         buf[4] = buf[5];
601         buf[5] = c;
602
603         c = buf[6];
604         buf[6] = buf[7];
605         buf[7] = c;
606 }
607
608 static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept)
609 {
610         struct efi_capsule_header header = { 0 };
611         FILE *f = NULL;
612         int ret = -1;
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;
616
617         f = fopen(path, "w");
618         if (!f) {
619                 fprintf(stderr, "cannot open %s\n", path);
620                 goto err;
621         }
622
623         capsule_guid = fw_accept ? fw_accept_guid : fw_revert_guid;
624
625         memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
626         header.header_size = sizeof(header);
627         header.flags = 0;
628
629         header.capsule_image_size = fw_accept ?
630                 sizeof(header) + sizeof(efi_guid_t) : sizeof(header);
631
632         if (write_capsule_file(f, &header, sizeof(header),
633                                "Capsule header"))
634                 goto err;
635
636         if (fw_accept) {
637                 if (write_capsule_file(f, guid, sizeof(*guid),
638                                        "FW Accept Capsule Payload"))
639                         goto err;
640         }
641
642         ret = 0;
643
644 err:
645         if (f)
646                 fclose(f);
647
648         return ret;
649 }
650
651 static void print_guid(void *ptr)
652 {
653         int i;
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 };
658
659         for (i = 0; i < ARRAY_SIZE(seq); i++) {
660                 if (seq[i] == '-')
661                         putchar(seq[i]);
662                 else
663                         printf("%02X", guid->b[seq[i]]);
664         }
665
666         printf("\n");
667 }
668
669 static uint32_t dump_fmp_payload_header(
670         struct fmp_payload_header *fmp_payload_hdr)
671 {
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;
683         }
684
685         return 0;
686 }
687
688 static void dump_capsule_auth_header(
689         struct efi_firmware_image_authentication *capsule_auth_hdr)
690 {
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);
701 }
702
703 static void dump_fmp_capsule_image_header(
704         struct efi_firmware_management_capsule_image_header *image_hdr)
705 {
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;
712
713         printf("--------\n");
714         printf("FMP_CAPSULE_IMAGE_HDR.VERSION\t\t\t: %08X\n",
715                image_hdr->version);
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);
728
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);
733
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;
738         } else {
739                 printf("Capsule Authentication Not Enabled\n");
740                 fmp_payload_hdr = (char *)image_hdr + sizeof(*image_hdr);
741         }
742
743         fmp_payload_hdr_size = dump_fmp_payload_header(fmp_payload_hdr);
744
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);
749 }
750
751 static void dump_fmp_header(
752         struct efi_firmware_management_capsule_header *fmp_hdr)
753 {
754         int i;
755         void *capsule_image_hdr;
756
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);
762
763         /*
764          * We currently don't support Embedded Drivers.
765          * Only worry about the payload items.
766          */
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);
771         }
772 }
773
774 static void dump_capsule_header(struct efi_capsule_header *capsule_hdr)
775 {
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);
783 }
784
785 static void normal_capsule_dump(void *capsule_buf)
786 {
787         void *fmp_hdr;
788         struct efi_capsule_header *hdr = capsule_buf;
789
790         dump_capsule_header(hdr);
791         printf("--------\n");
792
793         fmp_hdr = (char *)capsule_buf + sizeof(*hdr);
794         dump_fmp_header(fmp_hdr);
795 }
796
797 static void empty_capsule_dump(void *capsule_buf)
798 {
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;
802
803         dump_capsule_header(hdr);
804
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);
812         }
813 }
814
815 static void dump_capsule_contents(char *capsule_file)
816 {
817         int fd;
818         char *ptr;
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;
822         struct stat sbuf;
823
824         if (!capsule_file) {
825                 fprintf(stderr, "No capsule file provided\n");
826                 exit(EXIT_FAILURE);
827         }
828
829         if ((fd = open(capsule_file, O_RDONLY)) < 0) {
830                 fprintf(stderr, "Error opening capsule file: %s\n",
831                         capsule_file);
832                 exit(EXIT_FAILURE);
833         }
834
835         if (fstat(fd, &sbuf) < 0) {
836                 fprintf(stderr, "Can't stat capsule file: %s\n", capsule_file);
837                 exit(EXIT_FAILURE);
838         }
839
840         if ((ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0))
841             == MAP_FAILED) {
842                 fprintf(stderr, "Can't mmap capsule file: %s\n", capsule_file);
843                 exit(EXIT_FAILURE);
844         }
845
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);
853         } else {
854                 fprintf(stderr, "Unable to decode the capsule file: %s\n",
855                         capsule_file);
856                 exit(EXIT_FAILURE);
857         }
858 }
859
860 /**
861  * main - main entry function of mkeficapsule
862  * @argc:       Number of arguments
863  * @argv:       Array of pointers to arguments
864  *
865  * Create an uefi capsule file, optionally signing it.
866  * Parse all the arguments and pass them on to create_fwbin().
867  *
868  * Return:
869  * * 0  - on success
870  * * -1 - on failure
871  */
872 int main(int argc, char **argv)
873 {
874         efi_guid_t *guid;
875         unsigned char uuid_buf[16];
876         unsigned long index, instance;
877         uint64_t mcount;
878         unsigned long oemflags;
879         bool capsule_dump;
880         char *privkey_file, *cert_file;
881         int c, idx;
882         struct fmp_payload_header_params fmp_ph_params = { 0 };
883
884         guid = NULL;
885         index = 0;
886         instance = 0;
887         mcount = 0;
888         privkey_file = NULL;
889         cert_file = NULL;
890         capsule_dump = false;
891         dump_sig = 0;
892         capsule_type = CAPSULE_NORMAL_BLOB;
893         oemflags = 0;
894         for (;;) {
895                 c = getopt_long(argc, argv, opts_short, options, &idx);
896                 if (c == -1)
897                         break;
898
899                 switch (c) {
900                 case 'g':
901                         if (guid) {
902                                 fprintf(stderr,
903                                         "Image type already specified\n");
904                                 exit(EXIT_FAILURE);
905                         }
906                         if (uuid_parse(optarg, uuid_buf)) {
907                                 fprintf(stderr, "Wrong guid format\n");
908                                 exit(EXIT_FAILURE);
909                         }
910                         convert_uuid_to_guid(uuid_buf);
911                         guid = (efi_guid_t *)uuid_buf;
912                         break;
913                 case 'i':
914                         index = strtoul(optarg, NULL, 0);
915                         break;
916                 case 'I':
917                         instance = strtoul(optarg, NULL, 0);
918                         break;
919                 case 'v':
920                         fmp_ph_params.fw_version = strtoul(optarg, NULL, 0);
921                         fmp_ph_params.have_header = true;
922                         break;
923                 case 'p':
924                         if (privkey_file) {
925                                 fprintf(stderr,
926                                         "Private Key already specified\n");
927                                 exit(EXIT_FAILURE);
928                         }
929                         privkey_file = optarg;
930                         break;
931                 case 'c':
932                         if (cert_file) {
933                                 fprintf(stderr,
934                                         "Certificate file already specified\n");
935                                 exit(EXIT_FAILURE);
936                         }
937                         cert_file = optarg;
938                         break;
939                 case 'm':
940                         mcount = strtoul(optarg, NULL, 0);
941                         break;
942                 case 'd':
943                         dump_sig = 1;
944                         break;
945                 case 'A':
946                         if (capsule_type) {
947                                 fprintf(stderr,
948                                         "Select either of Accept or Revert capsule generation\n");
949                                 exit(1);
950                         }
951                         capsule_type = CAPSULE_ACCEPT;
952                         break;
953                 case 'R':
954                         if (capsule_type) {
955                                 fprintf(stderr,
956                                         "Select either of Accept or Revert capsule generation\n");
957                                 exit(1);
958                         }
959                         capsule_type = CAPSULE_REVERT;
960                         break;
961                 case 'o':
962                         oemflags = strtoul(optarg, NULL, 0);
963                         if (oemflags > 0xffff) {
964                                 fprintf(stderr,
965                                         "oemflags must be between 0x0 and 0xffff\n");
966                                 exit(1);
967                         }
968                         break;
969                 case 'D':
970                         capsule_dump = true;
971                         break;
972                 default:
973                         print_usage();
974                         exit(EXIT_SUCCESS);
975                 }
976         }
977
978         if (capsule_dump) {
979                 if (argc != optind + 1) {
980                         fprintf(stderr, "Must provide the capsule file to parse\n");
981                         exit(EXIT_FAILURE);
982                 }
983                 dump_capsule_contents(argv[argc - 1]);
984                 exit(EXIT_SUCCESS);
985         }
986
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)))) {
996                 print_usage();
997                 exit(EXIT_FAILURE);
998         }
999
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");
1004                         exit(EXIT_FAILURE);
1005                 }
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");
1010                 exit(EXIT_FAILURE);
1011         }
1012
1013         exit(EXIT_SUCCESS);
1014 }