From patchwork Mon Mar 20 05:54:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 665179 Delivered-To: patch@linaro.org Received: by 2002:a5d:5602:0:0:0:0:0 with SMTP id l2csp958185wrv; Sun, 19 Mar 2023 22:55:59 -0700 (PDT) X-Google-Smtp-Source: AK7set9UCMWuAEIPNdmJpG9T8lGwjuvhGAKWAf+godb6ADyMCzRk5NQQ8L3ApCMqwECqsXu7JqHA X-Received: by 2002:a05:622a:1214:b0:3e0:8c58:1dd with SMTP id y20-20020a05622a121400b003e08c5801ddmr5136280qtx.55.1679291759268; Sun, 19 Mar 2023 22:55:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679291759; cv=none; d=google.com; s=arc-20160816; b=YQ1upWHah65oYm8GCxb63LtzGOz2Y2QlT8PmieDzKBWQcyS49ghbOC+pB0mYex4kbt X1bgXzZRjjlxqPLQyMi0VgKFmHD4P8bX+V2VnGoPkbfd4CpY4TfstykXYQ0WYUlZNpFB yOymJhgzoBQzNXm5scc59KpQ29pAW0vvh5zsJPIC5tQxMofBz9K/VuBbVpXdqQ7Kwcw4 lxuji9F4sTbO6EntLmsBUbVBahSFgTFHTAUps0FtTa4STDj1+vG8jTffghxEy0z4/B5b kYqeis2xF1GeSeTYlT5osKyFNtyzoq4jnhAq3/F7Bv38NNSlGlAOs4PKzvzH9CJO0rSp k9/Q== 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:dkim-signature; bh=pEIt3FJyp+Umr6jRB2lh5v6AmlFjCqZfI6WOhOuwZ5M=; b=LvXCr1EpRw2wFntiYtpv2h+UqgPN5xOuKAr9Pl9VJxnBqEq5Onx5Cqf6cgq3k+x43F WMPGo2dHzLRsczzSwQMftoRgXZNBHwPLTjncDYQ05/k9AUrh6c3FFCpOFEiq0fI+HmTB VpluvtQKFgaqt8kYITMPNPTQ9rZChFV5xdt+zbb24mcvm/cZPHLoP69Ji76MTiyd7uXR 62xTuoWOT9RIdcC7ZS6tH9spJhw5l413quTh7qxcMW5B7Nell8wq0C8NPzUIAT+RbBa9 XU9UOKmvfQi/8Gs1Afz7Q8E/5ScvrRwTvYVcSlk/05sRJ9s6mTBZG5MNIrIkhGq5XV5V PDug== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=SmvtnBg2; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id bn45-20020a05620a2aed00b0074691447263si58652qkb.731.2023.03.19.22.55.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Mar 2023 22:55:59 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=SmvtnBg2; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (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 D6A5285B70; Mon, 20 Mar 2023 06:55:29 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="SmvtnBg2"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B1C0085A48; Mon, 20 Mar 2023 06:55:12 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x634.google.com (mail-pl1-x634.google.com [IPv6:2607:f8b0:4864:20::634]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 478AA85AC0 for ; Mon, 20 Mar 2023 06:55:05 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=masahisa.kojima@linaro.org Received: by mail-pl1-x634.google.com with SMTP id h8so11301959plf.10 for ; Sun, 19 Mar 2023 22:55:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1679291704; h=references:in-reply-to:message-id:date:subject:cc:to:from:from:to :cc:subject:date:message-id:reply-to; bh=pEIt3FJyp+Umr6jRB2lh5v6AmlFjCqZfI6WOhOuwZ5M=; b=SmvtnBg29MJqjFPfSi2ao84x+mRrb1nSBhRmVn922qPAy27iLxHpq1KrwVlbgbXhBv Fn9aPNFZ51EIXw2Ay6BBw7y94wyXWptx+h22KNPphBnMpl9wlXoSHDOjLksCVfwMV031 Nlo7iNNY9ufjExSRBLB0nupGNu8gSD5kJcfjq0Ofezn8pMZc/jmD7F4hyKj2WnJpzFfO FEzau1XSVlL6fCHuJTwegjmi8zA6BEf+MUgillMQUa1Yl6slBxTn4fmSCUIpoZz4Rzm+ fg00UAF9+kVpbbSWNK/RWgfXVNpjKv35PnS/LclEidkM8jogOlbYAxuLPqt7qkab1ocr 8FDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1679291704; h=references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=pEIt3FJyp+Umr6jRB2lh5v6AmlFjCqZfI6WOhOuwZ5M=; b=fxWVcoRMwHZ2HPtx5KI83KwjRJ4Sya5tKoVyhC064mGXxaCJ+sOVc7mz4oj9I8TJj9 RKujz9gbL2IfCCB/d5S1zM0CC9e5tr47dTNePyqHswcZp4EKE9as/A7ILWu7j5aL165L E2K/WqyGJI1HdfAyWgGyaC2Ao2FJvoBE/RQlR2OzOltyUhsVz47MjCqYjOjX6Rs55LDd P8Oq2o5UWWjiIva4u7xBmLwzmZ9CffnCueCDmcfCIdSsv5kK6rldq6XfGXwNfir08dae SkB6i9gxGdSV/4CP4rlZmBlrkoM+FwWF2/zU55qnDbY7UBgpBtufTLbJViTUSj/09u2k GBOw== X-Gm-Message-State: AO0yUKV5YF4mMPz4Cmh/z+h/2kaGxUQri+PaFC5Dn0pOeVXq1dvBzFY9 4rXCv8ZqyloUTNHQaahtfF9SGrZcNHXQTOLA6s4= X-Received: by 2002:a17:902:db0f:b0:1a1:8edc:c5f8 with SMTP id m15-20020a170902db0f00b001a18edcc5f8mr19211043plx.56.1679291704526; Sun, 19 Mar 2023 22:55:04 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id h6-20020a170902eec600b0019cb131b89csm4826718plb.254.2023.03.19.22.55.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Mar 2023 22:55:03 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Takahiro Akashi , Masahisa Kojima , Sughosh Ganu , Etienne Carriere Subject: [PATCH v3 4/4] mkeficapsule: add FMP Payload Header Date: Mon, 20 Mar 2023 14:54:47 +0900 Message-Id: <20230320055448.12439-5-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230320055448.12439-1-masahisa.kojima@linaro.org> References: <20230320055448.12439-1-masahisa.kojima@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.8 at phobos.denx.de X-Virus-Status: Clean Current mkeficapsule tool does not provide firmware version management. EDK2 reference implementation inserts the FMP Payload Header right before the payload. It coutains the fw_version and lowest supported version. This commit adds two new parameters required to generate the FMP Payload Header for mkeficapsule tool. '-v' indicates the firmware version. '-l' indicates the lowest supported version. When mkeficapsule tool is invoked with neither '-v' nor '-l' option, FMP Payload Header is not inserted, the behavior is same as current implementation. Signed-off-by: Masahisa Kojima --- Changes in v3: - remove '-f' option - move some definitions into tools/eficapsule.h - add dependency check of fw_version and lowest_supported_version - remove unexpected modification of existing fprintf() call - add documentation Newly created in v2 doc/mkeficapsule.1 | 16 ++++++++++++++ tools/eficapsule.h | 32 +++++++++++++++++++++++++++ tools/mkeficapsule.c | 51 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 94 insertions(+), 5 deletions(-) diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1 index 1ca245a10f..7c62b03c73 100644 --- a/doc/mkeficapsule.1 +++ b/doc/mkeficapsule.1 @@ -61,6 +61,22 @@ Specify an image index .BI "-I\fR,\fB --instance " instance Specify a hardware instance +.PP +FMP Payload Header is inserted right before the payload if +.BR --fw-version +or +.BR --lsv +are specified + + +.TP +.BI "-v\fR,\fB --fw-version " firmware-version +Specify a firmware version, 0 if omitted + +.TP +.BI "-l\fR,\fB --lsv " lowest-supported-version +Specify a lowest supported version, 0 if omitted + .PP For generation of firmware accept empty capsule .BR --guid diff --git a/tools/eficapsule.h b/tools/eficapsule.h index 072a4b5598..72500d1f84 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -113,4 +113,36 @@ struct efi_firmware_image_authentication { struct win_certificate_uefi_guid auth_info; } __packed; + +/* fmp payload header */ +#define SIGNATURE_16(A, B) ((A) | ((B) << 8)) +#define SIGNATURE_32(A, B, C, D) \ + (SIGNATURE_16(A, B) | (SIGNATURE_16(C, D) << 16)) + +#define FMP_PAYLOAD_HDR_SIGNATURE SIGNATURE_32('M', 'S', 'S', '1') + +/** + * struct fmp_payload_header - EDK2 header for the FMP payload + * + * This structure describes the header which is preprended to the + * FMP payload by the edk2 capsule generation scripts. + * + * @signature: Header signature used to identify the header + * @header_size: Size of the structure + * @fw_version: Firmware versions used + * @lowest_supported_version: Lowest supported version + */ +struct fmp_payload_header { + uint32_t signature; + uint32_t header_size; + uint32_t fw_version; + uint32_t lowest_supported_version; +}; + +struct fmp_payload_header_params { + bool have_header; + uint32_t fw_version; + uint32_t lowest_supported_version; +}; + #endif /* _EFI_CAPSULE_H */ diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index b71537beee..e50e6a8ed7 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,7 @@ 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:o:dhAR"; +static const char *opts_short = "g:i:I:v:l:p:c:m:o:dhAR"; enum { CAPSULE_NORMAL_BLOB = 0, @@ -41,6 +41,8 @@ static struct option options[] = { {"guid", required_argument, NULL, 'g'}, {"index", required_argument, NULL, 'i'}, {"instance", required_argument, NULL, 'I'}, + {"fw-version", required_argument, NULL, 'v'}, + {"lsv", required_argument, NULL, 'l'}, {"private-key", required_argument, NULL, 'p'}, {"certificate", required_argument, NULL, 'c'}, {"monotonic-count", required_argument, NULL, 'm'}, @@ -60,6 +62,8 @@ static void print_usage(void) "\t-g, --guid guid for image blob type\n" "\t-i, --index update image index\n" "\t-I, --instance update hardware instance\n" + "\t-v, --fw-version firmware version\n" + "\t-l, --lsv lowest supported version\n" "\t-p, --private-key private key file\n" "\t-c, --certificate signer's certificate file\n" "\t-m, --monotonic-count monotonic count\n" @@ -402,6 +406,7 @@ static void free_sig_data(struct auth_context *ctx) */ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, unsigned long index, unsigned long instance, + struct fmp_payload_header_params *fmp_ph_params, uint64_t mcount, char *privkey_file, char *cert_file, uint16_t oemflags) { @@ -410,10 +415,11 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, struct efi_firmware_management_capsule_image_header image; struct auth_context auth_context; FILE *f; - uint8_t *data; + uint8_t *data, *new_data, *buf; off_t bin_size; uint64_t offset; int ret; + struct fmp_payload_header payload_header; #ifdef DEBUG fprintf(stderr, "For output: %s\n", path); @@ -423,6 +429,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, auth_context.sig_size = 0; f = NULL; data = NULL; + new_data = NULL; ret = -1; /* @@ -431,12 +438,31 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, if (read_bin_file(bin, &data, &bin_size)) goto err; + buf = data; + + /* insert fmp payload header right before the payload */ + if (fmp_ph_params->have_header) { + new_data = malloc(bin_size + sizeof(payload_header)); + if (!new_data) + goto err; + + payload_header.signature = FMP_PAYLOAD_HDR_SIGNATURE; + payload_header.header_size = sizeof(payload_header); + payload_header.fw_version = fmp_ph_params->fw_version; + payload_header.lowest_supported_version = + fmp_ph_params->lowest_supported_version; + memcpy(new_data, &payload_header, sizeof(payload_header)); + memcpy(new_data + sizeof(payload_header), data, bin_size); + buf = new_data; + bin_size += sizeof(payload_header); + } + /* first, calculate signature to determine its size */ if (privkey_file && cert_file) { auth_context.key_file = privkey_file; auth_context.cert_file = cert_file; auth_context.auth.monotonic_count = mcount; - auth_context.image_data = data; + auth_context.image_data = buf; auth_context.image_size = bin_size; if (create_auth_data(&auth_context)) { @@ -536,7 +562,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, /* * firmware binary */ - if (write_capsule_file(f, data, bin_size, "Firmware binary")) + if (write_capsule_file(f, buf, bin_size, "Firmware binary")) goto err; ret = 0; @@ -545,6 +571,7 @@ err: fclose(f); free_sig_data(&auth_context); free(data); + free(new_data); return ret; } @@ -644,6 +671,7 @@ int main(int argc, char **argv) unsigned long oemflags; char *privkey_file, *cert_file; int c, idx; + struct fmp_payload_header_params fmp_ph_params = { 0 }; guid = NULL; index = 0; @@ -679,6 +707,14 @@ int main(int argc, char **argv) case 'I': instance = strtoul(optarg, NULL, 0); break; + case 'v': + fmp_ph_params.fw_version = strtoul(optarg, NULL, 0); + fmp_ph_params.have_header = true; + break; + case 'l': + fmp_ph_params.lowest_supported_version = strtoul(optarg, NULL, 0); + fmp_ph_params.have_header = true; + break; case 'p': if (privkey_file) { fprintf(stderr, @@ -744,6 +780,11 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } + if (fmp_ph_params.fw_version < fmp_ph_params.lowest_supported_version) { + fprintf(stderr, "fw_version is lower than lowest_supported_version\n"); + exit(EXIT_FAILURE); + } + if (capsule_type != CAPSULE_NORMAL_BLOB) { if (create_empty_capsule(argv[argc - 1], guid, capsule_type == CAPSULE_ACCEPT) < 0) { @@ -751,7 +792,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } } else if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, - index, instance, mcount, privkey_file, + index, instance, &fmp_ph_params, mcount, privkey_file, cert_file, (uint16_t)oemflags) < 0) { fprintf(stderr, "Creating firmware capsule failed\n"); exit(EXIT_FAILURE);