summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorSughosh Ganu <[email protected]>2022-10-21 18:16:06 +0530
committerTom Rini <[email protected]>2022-10-31 14:47:33 -0400
commit6da9271af112a3133748b624c27e2ff09b6ee842 (patch)
tree3fccd3393734ebd5fec17f8c5131cc4585702a6a /tools
parent873cf8ac70b620a0c1417d804bd4fb4246c34ebc (diff)
mkeficapsule: Add support for generating empty capsules
The Dependable Boot specification[1] describes the structure of the firmware accept and revert capsules. These are empty capsules which are used for signalling the acceptance or rejection of the updated firmware by the OS. Add support for generating these empty capsules. [1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf Signed-off-by: Sughosh Ganu <[email protected]> Acked-by: Ilias Apalodimas <[email protected]> Acked-by: Etienne Carriere <[email protected]>
Diffstat (limited to 'tools')
-rw-r--r--tools/eficapsule.h8
-rw-r--r--tools/mkeficapsule.c96
2 files changed, 97 insertions, 7 deletions
diff --git a/tools/eficapsule.h b/tools/eficapsule.h
index d63b8314432..072a4b5598b 100644
--- a/tools/eficapsule.h
+++ b/tools/eficapsule.h
@@ -41,6 +41,14 @@ typedef struct {
EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \
0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7)
+#define FW_ACCEPT_OS_GUID \
+ EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
+ 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
+
+#define FW_REVERT_OS_GUID \
+ EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
+ 0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
+
/* flags */
#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 5f74d23b9e3..25bfb39e5b3 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -29,7 +29,13 @@ static const char *tool_name = "mkeficapsule";
efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
-static const char *opts_short = "g:i:I:v:p:c:m:dh";
+static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
+
+enum {
+ CAPSULE_NORMAL_BLOB = 0,
+ CAPSULE_ACCEPT,
+ CAPSULE_REVERT,
+} capsule_type;
static struct option options[] = {
{"guid", required_argument, NULL, 'g'},
@@ -39,6 +45,8 @@ static struct option options[] = {
{"certificate", required_argument, NULL, 'c'},
{"monotonic-count", required_argument, NULL, 'm'},
{"dump-sig", no_argument, NULL, 'd'},
+ {"fw-accept", no_argument, NULL, 'A'},
+ {"fw-revert", no_argument, NULL, 'R'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
};
@@ -55,6 +63,8 @@ static void print_usage(void)
"\t-c, --certificate <cert file> signer's certificate file\n"
"\t-m, --monotonic-count <count> monotonic count\n"
"\t-d, --dump_sig dump signature (*.p7)\n"
+ "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n"
+ "\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n"
"\t-h, --help print a help message\n",
tool_name);
}
@@ -564,6 +574,49 @@ void convert_uuid_to_guid(unsigned char *buf)
buf[7] = c;
}
+static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept)
+{
+ struct efi_capsule_header header = { 0 };
+ FILE *f = NULL;
+ int ret = -1;
+ efi_guid_t fw_accept_guid = FW_ACCEPT_OS_GUID;
+ efi_guid_t fw_revert_guid = FW_REVERT_OS_GUID;
+ efi_guid_t capsule_guid;
+
+ f = fopen(path, "w");
+ if (!f) {
+ fprintf(stderr, "cannot open %s\n", path);
+ goto err;
+ }
+
+ capsule_guid = fw_accept ? fw_accept_guid : fw_revert_guid;
+
+ memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
+ header.header_size = sizeof(header);
+ header.flags = 0;
+
+ header.capsule_image_size = fw_accept ?
+ sizeof(header) + sizeof(efi_guid_t) : sizeof(header);
+
+ if (write_capsule_file(f, &header, sizeof(header),
+ "Capsule header"))
+ goto err;
+
+ if (fw_accept) {
+ if (write_capsule_file(f, guid, sizeof(*guid),
+ "FW Accept Capsule Payload"))
+ goto err;
+ }
+
+ ret = 0;
+
+err:
+ if (f)
+ fclose(f);
+
+ return ret;
+}
+
/**
* main - main entry function of mkeficapsule
* @argc: Number of arguments
@@ -592,6 +645,7 @@ int main(int argc, char **argv)
privkey_file = NULL;
cert_file = NULL;
dump_sig = 0;
+ capsule_type = CAPSULE_NORMAL_BLOB;
for (;;) {
c = getopt_long(argc, argv, opts_short, options, &idx);
if (c == -1)
@@ -639,22 +693,50 @@ int main(int argc, char **argv)
case 'd':
dump_sig = 1;
break;
- case 'h':
+ case 'A':
+ if (capsule_type) {
+ fprintf(stderr,
+ "Select either of Accept or Revert capsule generation\n");
+ exit(1);
+ }
+ capsule_type = CAPSULE_ACCEPT;
+ break;
+ case 'R':
+ if (capsule_type) {
+ fprintf(stderr,
+ "Select either of Accept or Revert capsule generation\n");
+ exit(1);
+ }
+ capsule_type = CAPSULE_REVERT;
+ break;
+ default:
print_usage();
exit(EXIT_SUCCESS);
}
}
/* check necessary parameters */
- if ((argc != optind + 2) || !guid ||
- ((privkey_file && !cert_file) ||
- (!privkey_file && cert_file))) {
+ if ((capsule_type == CAPSULE_NORMAL_BLOB &&
+ ((argc != optind + 2) || !guid ||
+ ((privkey_file && !cert_file) ||
+ (!privkey_file && cert_file)))) ||
+ (capsule_type != CAPSULE_NORMAL_BLOB &&
+ ((argc != optind + 1) ||
+ ((capsule_type == CAPSULE_ACCEPT) && !guid) ||
+ ((capsule_type == CAPSULE_REVERT) && guid)))) {
print_usage();
exit(EXIT_FAILURE);
}
- if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
- mcount, privkey_file, cert_file) < 0) {
+ if (capsule_type != CAPSULE_NORMAL_BLOB) {
+ if (create_empty_capsule(argv[argc - 1], guid,
+ capsule_type == CAPSULE_ACCEPT) < 0) {
+ fprintf(stderr, "Creating empty capsule failed\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if (create_fwbin(argv[argc - 1], argv[argc - 2], guid,
+ index, instance, mcount, privkey_file,
+ cert_file) < 0) {
fprintf(stderr, "Creating firmware capsule failed\n");
exit(EXIT_FAILURE);
}