From patchwork Mon Feb 7 18:20:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sughosh Ganu X-Patchwork-Id: 540575 Delivered-To: patch@linaro.org Received: by 2002:ac0:f7d2:0:0:0:0:0 with SMTP id i18csp345297imr; Mon, 7 Feb 2022 10:22:49 -0800 (PST) X-Google-Smtp-Source: ABdhPJzcylmyTqVoZRQkSjL7VjoMvsJEWqdF9Ro1C0qOYosiAAMD84yta0YDds8PwZ6Ve6hw5ZHb X-Received: by 2002:a05:6402:2995:: with SMTP id eq21mr740945edb.61.1644258169166; Mon, 07 Feb 2022 10:22:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1644258169; cv=none; d=google.com; s=arc-20160816; b=sUcKh/qkSmmMQIX7aR+5irOqmZgBl7I8TKmsLvIjkLbQgUMq4X3ZVA2y+1hwMNu7bZ 0YqTcj5x+6DvdCi1r/3nJPfZWtNfMCu+1s2PG2+BLQR8KhDtUAkYWRR+2kq1TIL1y5cI VLfHgeDnfRzJwVjPgsRGbhKMsaFgHPbPhqZVenYsuhSS0ug18EBVXu1kDvxgP8ICXb5h bcKf5oneDlZa6YxVbspb/x2HSxhBd7Hih4KJtRYZ0dhk0OYqYPAu1ImVSRduKeHHVeOi tICqQBWTDCD0oZ+L0x9JcV3G9O79EE1+LCNj/cG/AHsyVU+NQyNVn1g6jwrUfDtQ0Q2H GIZA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from; bh=8nHHMVcIieJyz62wGLiu9PHC41ng5QJu4ErFG/t43tk=; b=SI5hhygwbNKrqvcfnrfjjhf7IKBsMheWVUA32C/IIMr8ryKuurvAQPrN5Jk+hpvEIy vb0WyYOW2UGS0p9KHpribvzAkV6elfevWvTwUZXO8ok3ZfAM2OoI2HC+i+X6Bc3+glTQ Vqq5Na+LO1FS+AdNMQPUd7vZwnQ1vdQE6Ei5sHSBh7QWA2rXgCbRVDtxuonoOv77PhUN JnP8WKV9FPhzKZFlwFNWxnW2EgCxucNItgp1GrHExzFepBnadWbdMyopUomp3Rwe4+kZ lZj1dJ+1cGfrN4FRRnzRndzJ8iOWg89vMdlrdVJqmFKElUWUczLCjvypvUBQA0J6ADiT +V9A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id i7si7609509edr.636.2022.02.07.10.22.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Feb 2022 10:22:49 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1238F83C2F; Mon, 7 Feb 2022 19:21:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 7572983C08; Mon, 7 Feb 2022 19:21:51 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.2 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_SOFTFAIL,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id 6BB4B83BE8 for ; Mon, 7 Feb 2022 19:21:46 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sughosh.ganu@linaro.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DCCBA11B3; Mon, 7 Feb 2022 10:21:45 -0800 (PST) Received: from a076522.blr.arm.com (a076522.blr.arm.com [10.162.16.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D7DD13F718; Mon, 7 Feb 2022 10:21:41 -0800 (PST) From: Sughosh Ganu To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Masami Hiramatsu , Patrick Delaunay , Patrice Chotard , Alexander Graf , AKASHI Takahiro , Simon Glass , Bin Meng , Ilias Apalodimas , Jose Marinho , Grant Likely , Tom Rini , Etienne Carriere , Sughosh Ganu Subject: [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules Date: Mon, 7 Feb 2022 23:50:00 +0530 Message-Id: <20220207182001.31270-11-sughosh.ganu@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220207182001.31270-1-sughosh.ganu@linaro.org> References: <20220207182001.31270-1-sughosh.ganu@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean The Dependable Boot specification 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. Signed-off-by: Sughosh Ganu --- Changes since V3: * Add related documentation for empty capsules in the mkeficapsule man page. * Add separate usage for empty capsules, with corresponding valid options. * Use ternary operators where possible. * Put a exclusivity check for the empty capsule options. doc/mkeficapsule.1 | 23 +++++++- tools/eficapsule.h | 8 +++ tools/mkeficapsule.c | 131 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 139 insertions(+), 23 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 8babb27ee8..75fc15906a 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot .SH SYNOPSIS .B mkeficapsule -.RI [ options "] " image-blob " " capsule-file +.RI [ options ] " " [ image-blob ] " " capsule-file .SH "DESCRIPTION" .B mkeficapsule @@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given private key. In this case, the update will be authenticated by verifying the signature before applying. +Additionally, an empty capsule file can be generated for acceptance or +rejection of firmware images by a governing component like an Operating +System. The empty capsules do not require an image-blob input file. + + .B mkeficapsule -takes any type of image files, including: +takes any type of image files when generating non empty capsules, including: .TP .I raw image format is a single binary blob of any type of firmware. @@ -43,7 +48,7 @@ specify a guid for the FMP driver. .SH "OPTIONS" One of .BR --fit ", " --raw " or " --guid -option must be specified. +option must be specified for non empty capsules. .TP .BR -f ", " --fit @@ -69,6 +74,18 @@ Specify an image index .BI "-I\fR,\fB --instance " instance Specify a hardware instance +.PP +For generation of firmware accept empty capsule +.BR --guid +is mandatory +.TP +.BI "-A\fR,\fB --fw-accept " +Generate a firmware acceptance empty capsule + +.TP +.BI "-R\fR,\fB --fw-revert " +Generate a firmware revert empty capsule + .TP .BR -h ", " --help Print a help message diff --git a/tools/eficapsule.h b/tools/eficapsule.h index 8c1560bb06..6001952bdc 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -50,6 +50,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 161affdd15..e5dbec3a92 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,6 +29,7 @@ #include "eficapsule.h" static const char *tool_name = "mkeficapsule"; +unsigned char accept_fw_capsule, revert_fw_capsule, empty_capsule; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_image_type_uboot_fit = @@ -38,9 +39,9 @@ efi_guid_t efi_guid_image_type_uboot_raw = efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; #ifdef CONFIG_TOOLS_LIBCRYPTO -static const char *opts_short = "frg:i:I:v:p:c:m:dh"; +static const char *opts_short = "frg:i:I:v:p:c:m:dhAR"; #else -static const char *opts_short = "frg:i:I:v:h"; +static const char *opts_short = "frg:i:I:v:hAR"; #endif static struct option options[] = { @@ -55,28 +56,50 @@ static struct option options[] = { {"monotonic-count", required_argument, NULL, 'm'}, {"dump-sig", no_argument, NULL, 'd'}, #endif + {"fw-accept", no_argument, NULL, 'A'}, + {"fw-revert", no_argument, NULL, 'R'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; static void print_usage(void) { - fprintf(stderr, "Usage: %s [options] \n" - "Options:\n" - - "\t-f, --fit FIT image type\n" - "\t-r, --raw raw image type\n" - "\t-g, --guid guid for image blob type\n" - "\t-i, --index update image index\n" - "\t-I, --instance update hardware instance\n" + if (empty_capsule) { + if (accept_fw_capsule) { + fprintf(stderr, "Usage: %s [options] \n", + tool_name); + fprintf(stderr, "Options:\n" + "\t-A, --fw-accept firmware accept capsule\n" + "\t-g, --guid guid for image blob type\n" + "\t-h, --help print a help message\n" + ); + } else { + fprintf(stderr, "Usage: %s [options] \n", + tool_name); + fprintf(stderr, "Options:\n" + "\t-R, --fw-revert firmware revert capsule\n" + "\t-h, --help print a help message\n" + ); + } + } else { + fprintf(stderr, "Usage: %s [options] \n", + tool_name); + fprintf(stderr, "Options:\n" + "\t-f, --fit FIT image type\n" + "\t-r, --raw raw image type\n" + "\t-g, --guid guid for image blob type\n" + "\t-i, --index update image index\n" + "\t-I, --instance update hardware instance\n" #ifdef CONFIG_TOOLS_LIBCRYPTO - "\t-p, --private-key private key file\n" - "\t-c, --certificate signer's certificate file\n" - "\t-m, --monotonic-count monotonic count\n" - "\t-d, --dump_sig dump signature (*.p7)\n" + "\t-p, --private-key private key file\n" + "\t-c, --certificate signer's certificate file\n" + "\t-m, --monotonic-count monotonic count\n" + "\t-d, --dump_sig dump signature (*.p7)\n" #endif - "\t-h, --help print a help message\n", - tool_name); + "\t-A, --fw-accept firmware accept capsule\n" + "\t-R, --fw-revert firmware revert capsule\n" + "\t-h, --help print a help message\n"); + } } /** @@ -598,6 +621,50 @@ 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; + 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 payload, 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) { + memcpy(&payload, guid, sizeof(efi_guid_t)); + if (write_capsule_file(f, &payload, sizeof(payload), + "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 @@ -625,6 +692,8 @@ int main(int argc, char **argv) mcount = 0; privkey_file = NULL; cert_file = NULL; + accept_fw_capsule = 0; + revert_fw_capsule = 0; dump_sig = 0; for (;;) { c = getopt_long(argc, argv, opts_short, options, &idx); @@ -691,22 +760,44 @@ int main(int argc, char **argv) dump_sig = 1; break; #endif /* CONFIG_TOOLS_LIBCRYPTO */ + case 'A': + accept_fw_capsule = 1; + break; + case 'R': + revert_fw_capsule = 1; + break; case 'h': print_usage(); exit(EXIT_SUCCESS); } } + if (accept_fw_capsule && revert_fw_capsule) { + fprintf(stderr, + "Select either of Accept or Revert capsule generation\n"); + exit(EXIT_FAILURE); + } + + empty_capsule = (accept_fw_capsule || revert_fw_capsule); + /* check necessary parameters */ - if ((argc != optind + 2) || !guid || - ((privkey_file && !cert_file) || + if ((!empty_capsule && argc != optind + 2) || + (empty_capsule && argc != optind + 1) || + (!revert_fw_capsule && !guid) || ((privkey_file && !cert_file) || (!privkey_file && cert_file))) { print_usage(); exit(EXIT_FAILURE); } - if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance, - mcount, privkey_file, cert_file) < 0) { + if (empty_capsule) { + if (create_empty_capsule(argv[argc - 1], guid, + accept_fw_capsule ? 1 : 0) < 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); }