binman: doc: Remove incomplete sentence
[platform/kernel/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 #include <linux/kconfig.h>
20
21 #include <gnutls/gnutls.h>
22 #include <gnutls/pkcs7.h>
23 #include <gnutls/abstract.h>
24
25 #include "eficapsule.h"
26
27 static const char *tool_name = "mkeficapsule";
28
29 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
30 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
31
32 static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
33
34 enum {
35         CAPSULE_NORMAL_BLOB = 0,
36         CAPSULE_ACCEPT,
37         CAPSULE_REVERT,
38 } capsule_type;
39
40 static struct option options[] = {
41         {"guid", required_argument, NULL, 'g'},
42         {"index", required_argument, NULL, 'i'},
43         {"instance", required_argument, NULL, 'I'},
44         {"fw-version", required_argument, NULL, 'v'},
45         {"private-key", required_argument, NULL, 'p'},
46         {"certificate", required_argument, NULL, 'c'},
47         {"monotonic-count", required_argument, NULL, 'm'},
48         {"dump-sig", no_argument, NULL, 'd'},
49         {"fw-accept", no_argument, NULL, 'A'},
50         {"fw-revert", no_argument, NULL, 'R'},
51         {"capoemflag", required_argument, NULL, 'o'},
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-h, --help                  print a help message\n",
73                 tool_name);
74 }
75
76 /**
77  * auth_context - authentication context
78  * @key_file:   Path to a private key file
79  * @cert_file:  Path to a certificate file
80  * @image_data: Pointer to firmware data
81  * @image_size: Size of firmware data
82  * @auth:       Authentication header
83  * @sig_data:   Signature data
84  * @sig_size:   Size of signature data
85  *
86  * Data structure used in create_auth_data(). @key_file through
87  * @image_size are input parameters. @auth, @sig_data and @sig_size
88  * are filled in by create_auth_data().
89  */
90 struct auth_context {
91         char *key_file;
92         char *cert_file;
93         uint8_t *image_data;
94         size_t image_size;
95         struct efi_firmware_image_authentication auth;
96         uint8_t *sig_data;
97         size_t sig_size;
98 };
99
100 static int dump_sig;
101
102 /**
103  * read_bin_file - read a firmware binary file
104  * @bin:        Path to a firmware binary file
105  * @data:       Pointer to pointer of allocated buffer
106  * @bin_size:   Size of allocated buffer
107  *
108  * Read out a content of binary, @bin, into @data.
109  * A caller should free @data.
110  *
111  * Return:
112  * * 0  - on success
113  * * -1 - on failure
114  */
115 static int read_bin_file(char *bin, uint8_t **data, off_t *bin_size)
116 {
117         FILE *g;
118         struct stat bin_stat;
119         void *buf;
120         size_t size;
121         int ret = 0;
122
123         g = fopen(bin, "r");
124         if (!g) {
125                 fprintf(stderr, "cannot open %s\n", bin);
126                 return -1;
127         }
128         if (stat(bin, &bin_stat) < 0) {
129                 fprintf(stderr, "cannot determine the size of %s\n", bin);
130                 ret = -1;
131                 goto err;
132         }
133         if (bin_stat.st_size > SIZE_MAX) {
134                 fprintf(stderr, "file size is too large for malloc: %s\n", bin);
135                 ret = -1;
136                 goto err;
137         }
138         buf = malloc(bin_stat.st_size);
139         if (!buf) {
140                 fprintf(stderr, "cannot allocate memory: %zx\n",
141                         (size_t)bin_stat.st_size);
142                 ret = -1;
143                 goto err;
144         }
145
146         size = fread(buf, 1, bin_stat.st_size, g);
147         if (size < bin_stat.st_size) {
148                 fprintf(stderr, "read failed (%zx)\n", size);
149                 ret = -1;
150                 goto err;
151         }
152
153         *data = buf;
154         *bin_size = bin_stat.st_size;
155 err:
156         fclose(g);
157
158         return ret;
159 }
160
161 /**
162  * write_capsule_file - write a capsule file
163  * @bin:        FILE stream
164  * @data:       Pointer to data
165  * @bin_size:   Size of data
166  *
167  * Write out data, @data, with the size @bin_size.
168  *
169  * Return:
170  * * 0  - on success
171  * * -1 - on failure
172  */
173 static int write_capsule_file(FILE *f, void *data, size_t size, const char *msg)
174 {
175         size_t size_written;
176
177         size_written = fwrite(data, 1, size, f);
178         if (size_written < size) {
179                 fprintf(stderr, "%s: write failed (%zx != %zx)\n", msg,
180                         size_written, size);
181                 return -1;
182         }
183
184         return 0;
185 }
186
187 /**
188  * create_auth_data - compose authentication data in capsule
189  * @auth_context:       Pointer to authentication context
190  *
191  * Fill up an authentication header (.auth) and signature data (.sig_data)
192  * in @auth_context, using library functions from openssl.
193  * All the parameters in @auth_context must be filled in by a caller.
194  *
195  * Return:
196  * * 0  - on success
197  * * -1 - on failure
198  */
199 static int create_auth_data(struct auth_context *ctx)
200 {
201         gnutls_datum_t cert;
202         gnutls_datum_t key;
203         off_t file_size;
204         gnutls_privkey_t pkey;
205         gnutls_x509_crt_t x509;
206         gnutls_pkcs7_t pkcs7;
207         gnutls_datum_t data;
208         gnutls_datum_t signature;
209         int ret;
210
211         ret = read_bin_file(ctx->cert_file, &cert.data, &file_size);
212         if (ret < 0)
213                 return -1;
214         if (file_size > UINT_MAX)
215                 return -1;
216         cert.size = file_size;
217
218         ret = read_bin_file(ctx->key_file, &key.data, &file_size);
219         if (ret < 0)
220                 return -1;
221         if (file_size > UINT_MAX)
222                 return -1;
223         key.size = file_size;
224
225         /*
226          * For debugging,
227          * gnutls_global_set_time_function(mytime);
228          * gnutls_global_set_log_function(tls_log_func);
229          * gnutls_global_set_log_level(6);
230          */
231
232         ret = gnutls_privkey_init(&pkey);
233         if (ret < 0) {
234                 fprintf(stderr, "error in gnutls_privkey_init(): %s\n",
235                         gnutls_strerror(ret));
236                 return -1;
237         }
238
239         ret = gnutls_x509_crt_init(&x509);
240         if (ret < 0) {
241                 fprintf(stderr, "error in gnutls_x509_crt_init(): %s\n",
242                         gnutls_strerror(ret));
243                 return -1;
244         }
245
246         /* load a private key */
247         ret = gnutls_privkey_import_x509_raw(pkey, &key, GNUTLS_X509_FMT_PEM,
248                                              0, 0);
249         if (ret < 0) {
250                 fprintf(stderr,
251                         "error in gnutls_privkey_import_x509_raw(): %s\n",
252                         gnutls_strerror(ret));
253                 return -1;
254         }
255
256         /* load x509 certificate */
257         ret = gnutls_x509_crt_import(x509, &cert, GNUTLS_X509_FMT_PEM);
258         if (ret < 0) {
259                 fprintf(stderr, "error in gnutls_x509_crt_import(): %s\n",
260                         gnutls_strerror(ret));
261                 return -1;
262         }
263
264         /* generate a PKCS #7 structure */
265         ret = gnutls_pkcs7_init(&pkcs7);
266         if (ret < 0) {
267                 fprintf(stderr, "error in gnutls_pkcs7_init(): %s\n",
268                         gnutls_strerror(ret));
269                 return -1;
270         }
271
272         /* sign */
273         /*
274          * Data should have
275          *  * firmware image
276          *  * monotonic count
277          * in this order!
278          * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
279          */
280         data.size = ctx->image_size + sizeof(ctx->auth.monotonic_count);
281         data.data = malloc(data.size);
282         if (!data.data) {
283                 fprintf(stderr, "allocating memory (0x%x) failed\n", data.size);
284                 return -1;
285         }
286         memcpy(data.data, ctx->image_data, ctx->image_size);
287         memcpy(data.data + ctx->image_size, &ctx->auth.monotonic_count,
288                sizeof(ctx->auth.monotonic_count));
289
290         ret = gnutls_pkcs7_sign(pkcs7, x509, pkey, &data, NULL, NULL,
291                                 GNUTLS_DIG_SHA256,
292                                 /* GNUTLS_PKCS7_EMBED_DATA? */
293                                 GNUTLS_PKCS7_INCLUDE_CERT |
294                                 GNUTLS_PKCS7_INCLUDE_TIME);
295         if (ret < 0) {
296                 fprintf(stderr, "error in gnutls_pkcs7)sign(): %s\n",
297                         gnutls_strerror(ret));
298                 return -1;
299         }
300
301         /* export */
302         ret = gnutls_pkcs7_export2(pkcs7, GNUTLS_X509_FMT_DER, &signature);
303         if (ret < 0) {
304                 fprintf(stderr, "error in gnutls_pkcs7_export2: %s\n",
305                         gnutls_strerror(ret));
306                 return -1;
307         }
308         ctx->sig_data = signature.data;
309         ctx->sig_size = signature.size;
310
311         /* fill auth_info */
312         ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
313                                                 + ctx->sig_size;
314         ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
315         ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
316         memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
317                sizeof(efi_guid_cert_type_pkcs7));
318
319         /*
320          * For better clean-ups,
321          * gnutls_pkcs7_deinit(pkcs7);
322          * gnutls_privkey_deinit(pkey);
323          * gnutls_x509_crt_deinit(x509);
324          * free(cert.data);
325          * free(key.data);
326          * if error
327          *   gnutls_free(signature.data);
328          */
329
330         return 0;
331 }
332
333 /**
334  * dump_signature - dump out a signature
335  * @path:       Path to a capsule file
336  * @signature:  Signature data
337  * @sig_size:   Size of signature data
338  *
339  * Signature data pointed to by @signature will be saved into
340  * a file whose file name is @path with ".p7" suffix.
341  *
342  * Return:
343  * * 0  - on success
344  * * -1 - on failure
345  */
346 static int dump_signature(const char *path, uint8_t *signature, size_t sig_size)
347 {
348         char *sig_path;
349         FILE *f;
350         size_t size;
351         int ret = -1;
352
353         sig_path = malloc(strlen(path) + 3 + 1);
354         if (!sig_path)
355                 return ret;
356
357         sprintf(sig_path, "%s.p7", path);
358         f = fopen(sig_path, "w");
359         if (!f)
360                 goto err;
361
362         size = fwrite(signature, 1, sig_size, f);
363         if (size == sig_size)
364                 ret = 0;
365
366         fclose(f);
367 err:
368         free(sig_path);
369         return ret;
370 }
371
372 /**
373  * free_sig_data - free out signature data
374  * @ctx:        Pointer to authentication context
375  *
376  * Free signature data allocated in create_auth_data().
377  */
378 static void free_sig_data(struct auth_context *ctx)
379 {
380         if (ctx->sig_size)
381                 gnutls_free(ctx->sig_data);
382 }
383
384 /**
385  * create_fwbin - create an uefi capsule file
386  * @path:       Path to a created capsule file
387  * @bin:        Path to a firmware binary to encapsulate
388  * @guid:       GUID of related FMP driver
389  * @index:      Index number in capsule
390  * @instance:   Instance number in capsule
391  * @mcount:     Monotonic count in authentication information
392  * @private_file:       Path to a private key file
393  * @cert_file:  Path to a certificate file
394  * @oemflags:  Capsule OEM Flags, bits 0-15
395  *
396  * This function actually does the job of creating an uefi capsule file.
397  * All the arguments must be supplied.
398  * If either @private_file ror @cert_file is NULL, the capsule file
399  * won't be signed.
400  *
401  * Return:
402  * * 0  - on success
403  * * -1 - on failure
404  */
405 static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
406                         unsigned long index, unsigned long instance,
407                         struct fmp_payload_header_params *fmp_ph_params,
408                         uint64_t mcount, char *privkey_file, char *cert_file,
409                         uint16_t oemflags)
410 {
411         struct efi_capsule_header header;
412         struct efi_firmware_management_capsule_header capsule;
413         struct efi_firmware_management_capsule_image_header image;
414         struct auth_context auth_context;
415         FILE *f;
416         uint8_t *data, *new_data, *buf;
417         off_t bin_size;
418         uint64_t offset;
419         int ret;
420         struct fmp_payload_header payload_header;
421
422 #ifdef DEBUG
423         fprintf(stderr, "For output: %s\n", path);
424         fprintf(stderr, "\tbin: %s\n\ttype: %pUl\n", bin, guid);
425         fprintf(stderr, "\tindex: %lu\n\tinstance: %lu\n", index, instance);
426 #endif
427         auth_context.sig_size = 0;
428         f = NULL;
429         data = NULL;
430         new_data = NULL;
431         ret = -1;
432
433         /*
434          * read a firmware binary
435          */
436         if (read_bin_file(bin, &data, &bin_size))
437                 goto err;
438
439         buf = data;
440
441         /* insert fmp payload header right before the payload */
442         if (fmp_ph_params->have_header) {
443                 new_data = malloc(bin_size + sizeof(payload_header));
444                 if (!new_data)
445                         goto err;
446
447                 payload_header.signature = FMP_PAYLOAD_HDR_SIGNATURE;
448                 payload_header.header_size = sizeof(payload_header);
449                 payload_header.fw_version = fmp_ph_params->fw_version;
450                 payload_header.lowest_supported_version = 0; /* not used */
451                 memcpy(new_data, &payload_header, sizeof(payload_header));
452                 memcpy(new_data + sizeof(payload_header), data, bin_size);
453                 buf = new_data;
454                 bin_size += sizeof(payload_header);
455         }
456
457         /* first, calculate signature to determine its size */
458         if (privkey_file && cert_file) {
459                 auth_context.key_file = privkey_file;
460                 auth_context.cert_file = cert_file;
461                 auth_context.auth.monotonic_count = mcount;
462                 auth_context.image_data = buf;
463                 auth_context.image_size = bin_size;
464
465                 if (create_auth_data(&auth_context)) {
466                         fprintf(stderr, "Signing firmware image failed\n");
467                         goto err;
468                 }
469
470                 if (dump_sig &&
471                     dump_signature(path, auth_context.sig_data,
472                                    auth_context.sig_size)) {
473                         fprintf(stderr, "Creating signature file failed\n");
474                         goto err;
475                 }
476         }
477
478         /*
479          * write a capsule file
480          */
481         f = fopen(path, "w");
482         if (!f) {
483                 fprintf(stderr, "cannot open %s\n", path);
484                 goto err;
485         }
486
487         /*
488          * capsule file header
489          */
490         header.capsule_guid = efi_guid_fm_capsule;
491         header.header_size = sizeof(header);
492         /* TODO: The current implementation ignores flags */
493         header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
494         if (oemflags)
495                 header.flags |= oemflags;
496         header.capsule_image_size = sizeof(header)
497                                         + sizeof(capsule) + sizeof(uint64_t)
498                                         + sizeof(image)
499                                         + bin_size;
500         if (auth_context.sig_size)
501                 header.capsule_image_size += sizeof(auth_context.auth)
502                                 + auth_context.sig_size;
503         if (write_capsule_file(f, &header, sizeof(header),
504                                "Capsule header"))
505                 goto err;
506
507         /*
508          * firmware capsule header
509          * This capsule has only one firmware capsule image.
510          */
511         capsule.version = 0x00000001;
512         capsule.embedded_driver_count = 0;
513         capsule.payload_item_count = 1;
514         if (write_capsule_file(f, &capsule, sizeof(capsule),
515                                "Firmware capsule header"))
516                 goto err;
517
518         offset = sizeof(capsule) + sizeof(uint64_t);
519         if (write_capsule_file(f, &offset, sizeof(offset),
520                                "Offset to capsule image"))
521                 goto err;
522
523         /*
524          * firmware capsule image header
525          */
526         image.version = 0x00000003;
527         memcpy(&image.update_image_type_id, guid, sizeof(*guid));
528         image.update_image_index = index;
529         image.reserved[0] = 0;
530         image.reserved[1] = 0;
531         image.reserved[2] = 0;
532         image.update_image_size = bin_size;
533         if (auth_context.sig_size)
534                 image.update_image_size += sizeof(auth_context.auth)
535                                 + auth_context.sig_size;
536         image.update_vendor_code_size = 0; /* none */
537         image.update_hardware_instance = instance;
538         image.image_capsule_support = 0;
539         if (auth_context.sig_size)
540                 image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
541         if (write_capsule_file(f, &image, sizeof(image),
542                                "Firmware capsule image header"))
543                 goto err;
544
545         /*
546          * signature
547          */
548         if (auth_context.sig_size) {
549                 if (write_capsule_file(f, &auth_context.auth,
550                                        sizeof(auth_context.auth),
551                                        "Authentication header"))
552                         goto err;
553
554                 if (write_capsule_file(f, auth_context.sig_data,
555                                        auth_context.sig_size, "Signature"))
556                         goto err;
557         }
558
559         /*
560          * firmware binary
561          */
562         if (write_capsule_file(f, buf, bin_size, "Firmware binary"))
563                 goto err;
564
565         ret = 0;
566 err:
567         if (f)
568                 fclose(f);
569         free_sig_data(&auth_context);
570         free(data);
571         free(new_data);
572
573         return ret;
574 }
575
576 /**
577  * convert_uuid_to_guid() - convert UUID to GUID
578  * @buf:        UUID binary
579  *
580  * UUID and GUID have the same data structure, but their binary
581  * formats are different due to the endianness. See lib/uuid.c.
582  * Since uuid_parse() can handle only UUID, this function must
583  * be called to get correct data for GUID when parsing a string.
584  *
585  * The correct data will be returned in @buf.
586  */
587 void convert_uuid_to_guid(unsigned char *buf)
588 {
589         unsigned char c;
590
591         c = buf[0];
592         buf[0] = buf[3];
593         buf[3] = c;
594         c = buf[1];
595         buf[1] = buf[2];
596         buf[2] = c;
597
598         c = buf[4];
599         buf[4] = buf[5];
600         buf[5] = c;
601
602         c = buf[6];
603         buf[6] = buf[7];
604         buf[7] = c;
605 }
606
607 static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept)
608 {
609         struct efi_capsule_header header = { 0 };
610         FILE *f = NULL;
611         int ret = -1;
612         efi_guid_t fw_accept_guid = FW_ACCEPT_OS_GUID;
613         efi_guid_t fw_revert_guid = FW_REVERT_OS_GUID;
614         efi_guid_t capsule_guid;
615
616         f = fopen(path, "w");
617         if (!f) {
618                 fprintf(stderr, "cannot open %s\n", path);
619                 goto err;
620         }
621
622         capsule_guid = fw_accept ? fw_accept_guid : fw_revert_guid;
623
624         memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
625         header.header_size = sizeof(header);
626         header.flags = 0;
627
628         header.capsule_image_size = fw_accept ?
629                 sizeof(header) + sizeof(efi_guid_t) : sizeof(header);
630
631         if (write_capsule_file(f, &header, sizeof(header),
632                                "Capsule header"))
633                 goto err;
634
635         if (fw_accept) {
636                 if (write_capsule_file(f, guid, sizeof(*guid),
637                                        "FW Accept Capsule Payload"))
638                         goto err;
639         }
640
641         ret = 0;
642
643 err:
644         if (f)
645                 fclose(f);
646
647         return ret;
648 }
649
650 /**
651  * main - main entry function of mkeficapsule
652  * @argc:       Number of arguments
653  * @argv:       Array of pointers to arguments
654  *
655  * Create an uefi capsule file, optionally signing it.
656  * Parse all the arguments and pass them on to create_fwbin().
657  *
658  * Return:
659  * * 0  - on success
660  * * -1 - on failure
661  */
662 int main(int argc, char **argv)
663 {
664         efi_guid_t *guid;
665         unsigned char uuid_buf[16];
666         unsigned long index, instance;
667         uint64_t mcount;
668         unsigned long oemflags;
669         char *privkey_file, *cert_file;
670         int c, idx;
671         struct fmp_payload_header_params fmp_ph_params = { 0 };
672
673         guid = NULL;
674         index = 0;
675         instance = 0;
676         mcount = 0;
677         privkey_file = NULL;
678         cert_file = NULL;
679         dump_sig = 0;
680         capsule_type = CAPSULE_NORMAL_BLOB;
681         oemflags = 0;
682         for (;;) {
683                 c = getopt_long(argc, argv, opts_short, options, &idx);
684                 if (c == -1)
685                         break;
686
687                 switch (c) {
688                 case 'g':
689                         if (guid) {
690                                 fprintf(stderr,
691                                         "Image type already specified\n");
692                                 exit(EXIT_FAILURE);
693                         }
694                         if (uuid_parse(optarg, uuid_buf)) {
695                                 fprintf(stderr, "Wrong guid format\n");
696                                 exit(EXIT_FAILURE);
697                         }
698                         convert_uuid_to_guid(uuid_buf);
699                         guid = (efi_guid_t *)uuid_buf;
700                         break;
701                 case 'i':
702                         index = strtoul(optarg, NULL, 0);
703                         break;
704                 case 'I':
705                         instance = strtoul(optarg, NULL, 0);
706                         break;
707                 case 'v':
708                         fmp_ph_params.fw_version = strtoul(optarg, NULL, 0);
709                         fmp_ph_params.have_header = true;
710                         break;
711                 case 'p':
712                         if (privkey_file) {
713                                 fprintf(stderr,
714                                         "Private Key already specified\n");
715                                 exit(EXIT_FAILURE);
716                         }
717                         privkey_file = optarg;
718                         break;
719                 case 'c':
720                         if (cert_file) {
721                                 fprintf(stderr,
722                                         "Certificate file already specified\n");
723                                 exit(EXIT_FAILURE);
724                         }
725                         cert_file = optarg;
726                         break;
727                 case 'm':
728                         mcount = strtoul(optarg, NULL, 0);
729                         break;
730                 case 'd':
731                         dump_sig = 1;
732                         break;
733                 case 'A':
734                         if (capsule_type) {
735                                 fprintf(stderr,
736                                         "Select either of Accept or Revert capsule generation\n");
737                                 exit(1);
738                         }
739                         capsule_type = CAPSULE_ACCEPT;
740                         break;
741                 case 'R':
742                         if (capsule_type) {
743                                 fprintf(stderr,
744                                         "Select either of Accept or Revert capsule generation\n");
745                                 exit(1);
746                         }
747                         capsule_type = CAPSULE_REVERT;
748                         break;
749                 case 'o':
750                         oemflags = strtoul(optarg, NULL, 0);
751                         if (oemflags > 0xffff) {
752                                 fprintf(stderr,
753                                         "oemflags must be between 0x0 and 0xffff\n");
754                                 exit(1);
755                         }
756                         break;
757                 default:
758                         print_usage();
759                         exit(EXIT_SUCCESS);
760                 }
761         }
762
763         /* check necessary parameters */
764         if ((capsule_type == CAPSULE_NORMAL_BLOB &&
765             ((argc != optind + 2) || !guid ||
766              ((privkey_file && !cert_file) ||
767               (!privkey_file && cert_file)))) ||
768             (capsule_type != CAPSULE_NORMAL_BLOB &&
769             ((argc != optind + 1) ||
770              ((capsule_type == CAPSULE_ACCEPT) && !guid) ||
771              ((capsule_type == CAPSULE_REVERT) && guid)))) {
772                 print_usage();
773                 exit(EXIT_FAILURE);
774         }
775
776         if (capsule_type != CAPSULE_NORMAL_BLOB) {
777                 if (create_empty_capsule(argv[argc - 1], guid,
778                                          capsule_type == CAPSULE_ACCEPT) < 0) {
779                         fprintf(stderr, "Creating empty capsule failed\n");
780                         exit(EXIT_FAILURE);
781                 }
782         } else  if (create_fwbin(argv[argc - 1], argv[argc - 2], guid,
783                                  index, instance, &fmp_ph_params, mcount, privkey_file,
784                                  cert_file, (uint16_t)oemflags) < 0) {
785                 fprintf(stderr, "Creating firmware capsule failed\n");
786                 exit(EXIT_FAILURE);
787         }
788
789         exit(EXIT_SUCCESS);
790 }