From patchwork Tue Nov 17 00:27:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324537 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4491649ejb; Mon, 16 Nov 2020 16:29:22 -0800 (PST) X-Google-Smtp-Source: ABdhPJy44WfjAGh0LnY1ofBx9CfW7IsXbKFsHz5nAE7VgketPh6L/H7hvUGMumw5TXvrxiWro4Ej X-Received: by 2002:aa7:da81:: with SMTP id q1mr18102409eds.14.1605572962231; Mon, 16 Nov 2020 16:29:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605572962; cv=none; d=google.com; s=arc-20160816; b=bgXCf64qsHwvwOYncTMvwMk1zuRFNcoVhwGVvknbalrVqGe53c1dy0w5lXv5V2ksKs luHCkJXaFGA0v5uoeaJWplREkO7Td7pDHkgloi/qBX/ygSj+dWivFfnsuZb225XqI2pU d/sUsdK74Um4Cd2b5PrtY9OUW5sUKk+Y0eT61xxiRIA5SiinISZAukPMCF0h8ts9Rsj6 uyJvvvaVZXT8SMUXkFQdt2DRWiH4AANpQUm8fx2bwLdNEwKqcoiajS2L90m51QEBpD/t 00xa3qkkwnb1cFm2cbKCh6cxI2lV0nZFw6n6q7ZVnOW8StAwaKYcP6ShfadIcCkwPOOP WlyQ== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=pu+lQAY1CZxSX9sDOnT978qcpIO9JyGrFGDQfIyTYl0=; b=bU4n82hlv4wbk7QjX57VE9qrxOooymNxr1utMmqy4XLgdLPoJq+Hex6XHZROaw0V3I QKaJumFx2eL7b4MqXmkqGSVhfQGWxXWVsjP1ThKBdSJ22wjQkDy+N4nX5CeDic8+6dgk cBYiSg6IkB91ukkNpTpxX/pSjlDJasohEq2Z55uB+snYfuCIAABDZcPcIqu3lDxoOKy5 gYprGP4kdy2Rs7SyObboHotRjHZr1S9kS4p816aCcspylV+q31jq9qRUvDpXLbYbYC+v ce+GD2k6kdUodgDpXCqeF0Abdoh6aW4VjXfkkPiiPH2MpwBsE9cWhkrYwyYzKUEIL+4b L7Bw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Z9IgXL8B; 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 v9si11718685edb.48.2020.11.16.16.29.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:22 -0800 (PST) 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=Z9IgXL8B; 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 A8E3582366; Tue, 17 Nov 2020 01:29:10 +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="Z9IgXL8B"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C9A2682304; Tue, 17 Nov 2020 01:28:57 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) (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 88C8882304 for ; Tue, 17 Nov 2020 01:28:49 +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=takahiro.akashi@linaro.org Received: by mail-pf1-x442.google.com with SMTP id i8so2057194pfk.10 for ; Mon, 16 Nov 2020 16:28:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pu+lQAY1CZxSX9sDOnT978qcpIO9JyGrFGDQfIyTYl0=; b=Z9IgXL8BntNH34ysyvLQv8m2mP0fGCJyj1bzm+JXTZSE/aUL8kXS0QJ86WnYmjeypy LoGaKtWSXi6kcskyo/dWjrC+0+d/+WqwJOYIuh1VbWFrAi6nTbqhGk34cV6wrVAjj7mB KQWp5+XmyUWG/SHbmybrK7AgeODy4+8Bl9RKwduBIxa+D3FrzZU/FRDuiYU9Iem3hZBL AaB1QTYHMMU7hJq9ntlFE7byJwxRJrw8onhkovAZ8fdl08SLScK5doAj9xGaqj8XtBt6 If8Yj9n5tPYZpsyovIhvk/tK6fy7YPVqTn03FCQgxckOkI5JicIveEsmBmDAUlsPbIE7 CLNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pu+lQAY1CZxSX9sDOnT978qcpIO9JyGrFGDQfIyTYl0=; b=Fm1m0qjyZDgc2h/1tlLOktPUPhpc0NDMIs3DkGZlRZBnCQbLYPqakTeN82mb/FTAY3 0dtcbOSx/jlHphFrZv4K/xAd3mkRDSlVHs9COn2vMCW5kJ/+Lte5tMOl1s12VcjkBt5g 0K4nGQWEsruW/WeAtVyEBMnq9DADWHzXf+Yq0KuT0QWhYFt4TeBSjbu9GuROrdjqWmU0 Y31Sbt9jyE7syaYlSzfbFswhxR6VOdbKy6nnuHnM4Y9RdSDmC1PpM05uKQa3Z+sP1VPq mVj3fErfYMrkfI2dtGB0MVVXL+gOIYdLkvePPct7cbydtpd6lJ/BkyBUT7nE9rgLcxFm jkfA== X-Gm-Message-State: AOAM533wI7uiUzKno5TW3YlHJOkMWHQSmVG6fp6Jz7maivOmXSqQwYlS RGzl3THYGYhtj7wbgsrAJaYNqQ== X-Received: by 2002:a63:f91d:: with SMTP id h29mr1384085pgi.82.1605572927969; Mon, 16 Nov 2020 16:28:47 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.28.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:28:47 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 01/11] efi_loader: define UpdateCapsule api Date: Tue, 17 Nov 2020 09:27:55 +0900 Message-Id: <20201117002805.13902-2-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean In this commit, skeleton functions for capsule-related API's are added under CONFIG_EFI_UPDATE_CAPSULE configuration. Detailed implementation for a specific capsule type will be added in the succeeding patches. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 12 +++ include/efi_loader.h | 13 +++ lib/efi_loader/Kconfig | 11 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_capsule.c | 165 +++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_runtime.c | 104 ++++++++++++---------- lib/efi_loader/efi_setup.c | 64 +++++++++++--- 7 files changed, 316 insertions(+), 54 deletions(-) create mode 100644 lib/efi_loader/efi_capsule.c -- 2.28.0 diff --git a/include/efi_api.h b/include/efi_api.h index 5744f6aed86d..c128a0a66ce8 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -217,6 +217,10 @@ enum efi_reset_type { #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 #define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 +#define EFI_CAPSULE_REPORT_GUID \ + EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \ + 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -224,6 +228,14 @@ struct efi_capsule_header { u32 capsule_image_size; } __packed; +struct efi_capsule_result_variable_header { + u32 variable_total_size; + u32 reserved; + efi_guid_t capsule_guid; + struct efi_time capsule_processed; + efi_status_t capsule_status; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 diff --git a/include/efi_loader.h b/include/efi_loader.h index f550ced56876..d22f7a43ad09 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -207,6 +207,8 @@ extern const efi_guid_t efi_guid_cert_type_pkcs7; /* GUID of RNG protocol */ extern const efi_guid_t efi_guid_rng_protocol; +/* GUID of capsule update result */ +extern const efi_guid_t efi_guid_capsule_report; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; @@ -807,6 +809,17 @@ void efi_memcpy_runtime(void *dest, const void *src, size_t n); /* commonly used helper function */ u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index); +/* Capsule update */ +efi_status_t EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list); +efi_status_t EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type); + #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 075481428cdf..3ca396df3646 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -93,6 +93,17 @@ config EFI_SET_TIME Provide the SetTime() runtime service at boottime. This service can be used by an EFI application to adjust the real time clock. +config EFI_HAVE_CAPSULE_SUPPORT + bool + +config EFI_RUNTIME_UPDATE_CAPSULE + bool "UpdateCapsule() runtime service" + default n + select EFI_HAVE_CAPSULE_SUPPORT + help + Select this option if you want to use UpdateCapsule and + QueryCapsuleCapabilities API's. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 8892fb01e125..8d729abdfa78 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -23,6 +23,7 @@ endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_bootmgr.o obj-y += efi_boottime.o +obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o obj-y += efi_console.o obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c new file mode 100644 index 000000000000..575fa75b0a2f --- /dev/null +++ b/lib/efi_loader/efi_capsule.c @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI Capsule + * + * Copyright (c) 2018 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include + +const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; + +/** + * get_last_capsule - get the last capsule index + * + * Retrieve the index of the capsule invoked last time from "CapsuleLast" + * variable. + * + * Return: + * * > 0 - the last capsule index invoked + * * 0xffff - on error, or no capsule invoked yet + */ +static __maybe_unused unsigned int get_last_capsule(void) +{ + u16 value16[11]; /* "CapsuleXXXX": non-null-terminated */ + char value[11], *p; + efi_uintn_t size; + unsigned long index = 0xffff; + efi_status_t ret; + + size = sizeof(value16); + ret = efi_get_variable_int(L"CapsuleLast", &efi_guid_capsule_report, + NULL, &size, value16, NULL); + if (ret != EFI_SUCCESS || u16_strncmp(value16, L"Capsule", 7)) + goto err; + + p = value; + utf16_utf8_strcpy(&p, value16); + strict_strtoul(&value[7], 16, &index); +err: + return index; +} + +/** + * set_capsule_result - set a result variable + * @capsule: Capsule + * @return_status: Return status + * + * Create and set a result variable, "CapsuleXXXX", for the capsule, + * @capsule. + */ +static __maybe_unused +void set_capsule_result(int index, struct efi_capsule_header *capsule, + efi_status_t return_status) +{ + u16 variable_name16[12]; + struct efi_capsule_result_variable_header result; + struct efi_time time; + efi_status_t ret; + + efi_create_indexed_name(variable_name16, "Capsule", index); + + result.variable_total_size = sizeof(result); + result.capsule_guid = capsule->capsule_guid; + ret = EFI_CALL((*efi_runtime_services.get_time)(&time, NULL)); + if (ret == EFI_SUCCESS) + memcpy(&result.capsule_processed, &time, sizeof(time)); + else + memset(&result.capsule_processed, 0, sizeof(time)); + result.capsule_status = return_status; + ret = efi_set_variable(variable_name16, &efi_guid_capsule_report, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(result), &result); + if (ret) + printf("EFI: creating %ls failed\n", variable_name16); +} + +/** + * efi_update_capsule() - process information from operating system + * @capsule_header_array: Array of virtual address pointers + * @capsule_count: Number of pointers in capsule_header_array + * @scatter_gather_list: Array of physical address pointers + * + * This function implements the UpdateCapsule() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * Return: status code + */ +efi_status_t EFIAPI efi_update_capsule( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +{ + struct efi_capsule_header *capsule; + unsigned int i; + efi_status_t ret; + + EFI_ENTRY("%p, %lu, %llu\n", capsule_header_array, capsule_count, + scatter_gather_list); + + if (!capsule_count) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + ret = EFI_UNSUPPORTED; + for (i = 0, capsule = *capsule_header_array; i < capsule_count; + i++, capsule = *(++capsule_header_array)) { + } +out: + return EFI_EXIT(ret); +} + +/** + * efi_query_capsule_caps() - check if capsule is supported + * @capsule_header_array: Array of virtual pointers + * @capsule_count: Number of pointers in capsule_header_array + * @maximum_capsule_size: Maximum capsule size + * @reset_type: Type of reset needed for capsule update + * + * This function implements the QueryCapsuleCapabilities() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * Return: status code + */ +efi_status_t EFIAPI efi_query_capsule_caps( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type) +{ + struct efi_capsule_header *capsule __attribute__((unused)); + unsigned int i; + efi_status_t ret; + + EFI_ENTRY("%p, %lu, %p, %p\n", capsule_header_array, capsule_count, + maximum_capsule_size, reset_type); + + if (!maximum_capsule_size) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + *maximum_capsule_size = U64_MAX; + *reset_type = EFI_RESET_COLD; + + ret = EFI_SUCCESS; + for (i = 0, capsule = *capsule_header_array; i < capsule_count; + i++, capsule = *(++capsule_header_array)) { + /* TODO */ + } +out: + return EFI_EXIT(ret); +} diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 1fa1595e402f..0b171c1ff7bf 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -133,6 +133,10 @@ efi_status_t efi_init_runtime_supported(void) #ifdef CONFIG_EFI_HAVE_RUNTIME_RESET rt_table->runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM; #endif + if (IS_ENABLED(CONFIG_EFI_RUNTIME_UPDATE_CAPSULE)) + rt_table->runtime_services_supported |= + (EFI_RT_SUPPORTED_UPDATE_CAPSULE | + EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES); ret = efi_install_configuration_table(&efi_rt_properties_table_guid, rt_table); @@ -448,6 +452,50 @@ efi_status_t __weak __efi_runtime EFIAPI efi_set_time(struct efi_time *time) return EFI_UNSUPPORTED; } +/** + * efi_update_capsule_unsupported() - process information from operating system + * + * This function implements the UpdateCapsule() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @scatter_gather_list: pointer to array of physical pointers + * Returns: status code + */ +efi_status_t __efi_runtime EFIAPI efi_update_capsule_unsupported( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 scatter_gather_list) +{ + return EFI_UNSUPPORTED; +} + +/** + * efi_query_capsule_caps_unsupported() - check if capsule is supported + * + * This function implements the QueryCapsuleCapabilities() runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @capsule_header_array: pointer to array of virtual pointers + * @capsule_count: number of pointers in capsule_header_array + * @maximum_capsule_size: maximum capsule size + * @reset_type: type of reset needed for capsule update + * Returns: status code + */ +efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps_unsupported( + struct efi_capsule_header **capsule_header_array, + efi_uintn_t capsule_count, + u64 *maximum_capsule_size, + u32 *reset_type) +{ + return EFI_UNSUPPORTED; +} + /** * efi_is_runtime_service_pointer() - check if pointer points to runtime table * @@ -471,6 +519,13 @@ void efi_runtime_detach(void) efi_runtime_services.reset_system = efi_reset_system; efi_runtime_services.get_time = efi_get_time; efi_runtime_services.set_time = efi_set_time; + if (IS_ENABLED(CONFIG_EFI_RUNTIME_UPDATE_CAPSULE)) { + /* won't support at runtime */ + efi_runtime_services.update_capsule = + efi_update_capsule_unsupported; + efi_runtime_services.query_capsule_caps = + efi_query_capsule_caps_unsupported; + } /* Update CRC32 */ efi_update_table_header_crc32(&efi_runtime_services.hdr); @@ -879,50 +934,6 @@ static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void) return EFI_UNSUPPORTED; } -/** - * efi_update_capsule() - process information from operating system - * - * This function implements the UpdateCapsule() runtime service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * @capsule_header_array: pointer to array of virtual pointers - * @capsule_count: number of pointers in capsule_header_array - * @scatter_gather_list: pointer to arry of physical pointers - * Returns: status code - */ -efi_status_t __efi_runtime EFIAPI efi_update_capsule( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 scatter_gather_list) -{ - return EFI_UNSUPPORTED; -} - -/** - * efi_query_capsule_caps() - check if capsule is supported - * - * This function implements the QueryCapsuleCapabilities() runtime service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * @capsule_header_array: pointer to array of virtual pointers - * @capsule_count: number of pointers in capsule_header_array - * @maximum_capsule_size: maximum capsule size - * @reset_type: type of reset needed for capsule update - * Returns: status code - */ -efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( - struct efi_capsule_header **capsule_header_array, - efi_uintn_t capsule_count, - u64 *maximum_capsule_size, - u32 *reset_type) -{ - return EFI_UNSUPPORTED; -} - struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .hdr = { .signature = EFI_RUNTIME_SERVICES_SIGNATURE, @@ -940,7 +951,12 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = { .set_variable = efi_set_variable, .get_next_high_mono_count = (void *)&efi_unimplemented, .reset_system = &efi_reset_system_boottime, +#ifdef CONFIG_EFI_RUNTIME_UPDATE_CAPSULE .update_capsule = efi_update_capsule, .query_capsule_caps = efi_query_capsule_caps, +#else + .update_capsule = efi_update_capsule_unsupported, + .query_capsule_caps = efi_query_capsule_caps_unsupported, +#endif .query_variable_info = efi_query_variable_info, }; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 45226c5c1a53..070ac6147c72 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -100,9 +100,9 @@ static efi_status_t efi_init_secure_boot(void) ret = efi_set_variable_int(L"SignatureSupport", &efi_global_variable_guid, + EFI_VARIABLE_READ_ONLY | EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS | - EFI_VARIABLE_READ_ONLY, + EFI_VARIABLE_RUNTIME_ACCESS, sizeof(signature_types), &signature_types, false); if (ret != EFI_SUCCESS) @@ -117,6 +117,53 @@ static efi_status_t efi_init_secure_boot(void) } #endif /* CONFIG_EFI_SECURE_BOOT */ +/** + * efi_init_capsule - initialize capsule update state + * + * Return: status code + */ +static efi_status_t efi_init_capsule(void) +{ + efi_status_t ret = EFI_SUCCESS; + + if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) { + ret = efi_set_variable_int(L"CapsuleMax", + &efi_guid_capsule_report, + EFI_VARIABLE_READ_ONLY | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + 22, L"CapsuleFFFF", false); + if (ret != EFI_SUCCESS) + printf("EFI: cannot initialize CapsuleMax variable\n"); + } + + return ret; +} + +/** + * efi_init_os_indications() - indicate supported features for OS requests + * + * Set the OsIndicationsSupported variable. + * + * Return: status code + */ +static efi_status_t efi_init_os_indications(void) +{ + u64 os_indications_supported = 0; + + if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) + os_indications_supported |= + EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED; + + return efi_set_variable_int(L"OsIndicationsSupported", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_READ_ONLY, + sizeof(os_indications_supported), + &os_indications_supported, false); +} + /** * efi_init_obj_list() - Initialize and populate EFI object list * @@ -124,7 +171,6 @@ static efi_status_t efi_init_secure_boot(void) */ efi_status_t efi_init_obj_list(void) { - u64 os_indications_supported = 0; /* None */ efi_status_t ret = EFI_SUCCESS; /* Initialize once only */ @@ -167,13 +213,7 @@ efi_status_t efi_init_obj_list(void) goto out; /* Indicate supported features */ - ret = efi_set_variable_int(L"OsIndicationsSupported", - &efi_global_variable_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS | - EFI_VARIABLE_READ_ONLY, - sizeof(os_indications_supported), - &os_indications_supported, false); + ret = efi_init_os_indications(); if (ret != EFI_SUCCESS) goto out; @@ -226,6 +266,10 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + ret = efi_init_capsule(); + if (ret != EFI_SUCCESS) + goto out; + /* Initialize EFI runtime services */ ret = efi_reset_system_init(); if (ret != EFI_SUCCESS) From patchwork Tue Nov 17 00:27:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324538 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4491827ejb; Mon, 16 Nov 2020 16:29:38 -0800 (PST) X-Google-Smtp-Source: ABdhPJztdOb+/E7EFEmT8gt3Leb7i58Ap7rulaaImkjtEislIwjlTHL4qZmJ6ecV9rVZbuwg+kbQ X-Received: by 2002:a17:906:b783:: with SMTP id dt3mr16637302ejb.534.1605572977868; Mon, 16 Nov 2020 16:29:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605572977; cv=none; d=google.com; s=arc-20160816; b=rGpIDmaCVWCWecVy7Gr09rbuY6afRAKhr1sMeHB85205D7PrgXqF9yEPf49/rRHr63 NJu/pLgrGhSqeQkDXTrycDPcabyxDvDp3/XrIHi4skZDusBUSlnvRX9NPIDmAK+4NEYR JJj8+3UHcJRv0UiQeEO2pU+snji3kYPFQ+lVLM0ci/5LQIixecm1tmAdHEW8T8XRsWVd QfB0Jgq9F5Ag0pFgAjxC3r69IZrtdgnKSsWLIbuyxOTT/l78wb0IW2Hv9WklsQIVaqfb VOpQsEF6hIjtkERcSRo9BWYQKIb+5IiUp0BaWxiU3/onRtOzvIbv7kZWYvVdYgHUog2S aTrQ== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ZbxEob5KvWBzPqebXvrF1ZqllNSv9NuSaOVaeJf+Brg=; b=UDGIrILxY3nrrz8223GqbAyS8cO/D8FNCxpyjeID3jnJDRUfmWr/9myKrfcigbqCFE V7nfsTMmjOcyrlERpwg5dJNnj0weIWcI5SpnQWcoT8/P0t8ABSiDETVJAfxuea/i9LR9 u9fTKXOLIwxDyIQNezJQW1MS3pn0t+GIf2iNZeYn6iZzJ3ZmVZibgaIHivGJ7keyTu4C D0aMOa9fqMIhatuY2ckFoWqFHjSOWc+1hkGsnUGe1OryY8AXodGB5bczEU84p1NjHy0S QNXmLONfyRceLGYiJYz5UgYaCiwT43Cvi1QdDsL100eF8JKhjdxTLK6EZxhmSj9eiFGG VDBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xMTDmadn; 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=pass (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 b5si13416253edw.262.2020.11.16.16.29.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:37 -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; dkim=pass header.i=@linaro.org header.s=google header.b=xMTDmadn; 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=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 BD6B88255C; Tue, 17 Nov 2020 01:29:21 +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="xMTDmadn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4A01082574; Tue, 17 Nov 2020 01:29:06 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x541.google.com (mail-pg1-x541.google.com [IPv6:2607:f8b0:4864:20::541]) (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 6792D82366 for ; Tue, 17 Nov 2020 01:28:56 +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=takahiro.akashi@linaro.org Received: by mail-pg1-x541.google.com with SMTP id q28so4219258pgk.1 for ; Mon, 16 Nov 2020 16:28:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZbxEob5KvWBzPqebXvrF1ZqllNSv9NuSaOVaeJf+Brg=; b=xMTDmadnFiOcmsxDEadBbeFBM/uecaO8nC64SQ21MEN/VWo1yCy3NDW+XhNbokoS8P q7gt0MuTcPMWFqs0VNPlAcNNdMfxju8WOrNmc6IbDxzSnk88IOCJUBl7jM951iGlIfFW qzzIVbWjqMfw0J40mUmsx3P0WbP5V3dVx9JgcyFHbaLC4UpdguU4XRRxu8raOdztmo3Z DbAeHpo1Bp/W7Sh/VGJDkFtEGLAY0vU7O6Y25sjTlOCvLEjX6zchEW1ekt9NAwsQxsJx Nsh9TH4XWuQEwawkn3cGxXSsjYGXvAgqz7qs/4ZVQ4Ox4NCJBZZ3X1aXROHjsQCe4uhj Apow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZbxEob5KvWBzPqebXvrF1ZqllNSv9NuSaOVaeJf+Brg=; b=k588N2Zcu+bbtDD4+IRoR4Bf3+fNtS1l+4X1LNpFiqxgfaWpVLmO8Ol5/F/+4Aw0+L /1zjn6KhQILnTqkolIIy2W68Hp/MPC8P90488eeGcrZpjCURBVUSydc8tU6JYzltQgBG mM+jZq74QPR6GcwBPDx5yVKFdbgyUu++NlPU5PoHKDGdxfCDGb6rUB1bWc7Tcf6fWsda d7kGhEXq/AzzuxUBdwgMfnam1h4mVf5a3qyAGxRiBzMpUcsg4XpDkLWUwZTHSnrqrVsc 1pczDVWB6QV1SMULioCJj7JoJs+zNyG40ITkvvfXM2qHE2UGg09P4SllNEGNORgmFp6g 5dtw== X-Gm-Message-State: AOAM531KAC231nB8GU11d2yg80b/fgcSQ4kR+LSQk2xoQsVeLuG9bfBa 91fu7jWQP2adqeH3V/rVY/ZSQA== X-Received: by 2002:aa7:8b12:0:b029:18c:7b88:d7fc with SMTP id f18-20020aa78b120000b029018c7b88d7fcmr15795771pfd.53.1605572930834; Mon, 16 Nov 2020 16:28:50 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.28.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:28:50 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 02/11] efi_loader: capsule: add capsule_on_disk support Date: Tue, 17 Nov 2020 09:27:56 +0900 Message-Id: <20201117002805.13902-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean Capsule data can be loaded into the system either via UpdateCapsule runtime service or files on a file system (of boot device). The latter case is called "capsules on disk", and actual updates will take place at the next boot time. In this commit, we will support capsule on disk mechanism. Please note that U-Boot itself has no notion of "boot device" and all the capsule files to be executed will be detected only if they are located in a specific directory, \EFI\UpdateCapsule, on a device that is identified as a boot device by "BootXXXX" variables. Signed-off-by: AKASHI Takahiro --- common/main.c | 4 + include/efi_loader.h | 9 + lib/efi_loader/Kconfig | 22 ++ lib/efi_loader/efi_capsule.c | 498 +++++++++++++++++++++++++++++++++++ lib/efi_loader/efi_setup.c | 8 + 5 files changed, 541 insertions(+) -- 2.28.0 diff --git a/common/main.c b/common/main.c index 4b3cd302c3e2..ae5bcdb32f8b 100644 --- a/common/main.c +++ b/common/main.c @@ -16,6 +16,7 @@ #include #include #include +#include static void run_preboot_environment_command(void) { @@ -53,6 +54,9 @@ void main_loop(void) if (IS_ENABLED(CONFIG_UPDATE_TFTP)) update_tftp(0UL, NULL, NULL); + if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)) + efi_launch_capsules(); + s = bootdelay_process(); if (cli_process_fdt(&s)) cli_secure_boot_cmd(s); diff --git a/include/efi_loader.h b/include/efi_loader.h index d22f7a43ad09..eb57e7455eb1 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -820,6 +820,11 @@ efi_status_t EFIAPI efi_query_capsule_caps( u64 *maximum_capsule_size, u32 *reset_type); +#define EFI_CAPSULE_DIR L"\\EFI\\UpdateCapsule\\" + +/* Hook at initialization */ +efi_status_t efi_launch_capsules(void); + #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ @@ -836,6 +841,10 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr, const char *path) { } static inline void efi_net_set_dhcp_ack(void *pkt, int len) { } static inline void efi_print_image_infos(void *pc) { } +static inline efi_status_t efi_launch_capsules(void) +{ + return EFI_SUCCESS; +} #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 3ca396df3646..e1ac5ac055de 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -104,6 +104,28 @@ config EFI_RUNTIME_UPDATE_CAPSULE Select this option if you want to use UpdateCapsule and QueryCapsuleCapabilities API's. +config EFI_CAPSULE_ON_DISK + bool "Enable capsule-on-disk support" + select EFI_HAVE_CAPSULE_SUPPORT + default n + help + Select this option if you want to use capsule-on-disk feature, + that is, capsules can be fetched and executed from files + under a specific directory on UEFI system partition instead of + via UpdateCapsule API. + +config EFI_CAPSULE_ON_DISK_EARLY + bool "Initiate capsule-on-disk at U-Boot boottime" + depends on EFI_CAPSULE_ON_DISK + default n + select EFI_SETUP_EARLY + help + Normally, without this option enabled, capsules will be + executed only at the first time of invoking one of efi command. + If this option is enabled, capsules will be enforced to be + executed as part of U-Boot initialisation so that they will + surely take place whatever is set to distro_bootcmd. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 575fa75b0a2f..b3c7d1b735b6 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -11,10 +11,16 @@ #include #include #include +#include #include const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; +#ifdef CONFIG_EFI_CAPSULE_ON_DISK +/* for file system access */ +static struct efi_file_handle *bootdev_root; +#endif + /** * get_last_capsule - get the last capsule index * @@ -163,3 +169,495 @@ efi_status_t EFIAPI efi_query_capsule_caps( out: return EFI_EXIT(ret); } + +#ifdef CONFIG_EFI_CAPSULE_ON_DISK +/** + * get_dp_device - retrieve a device path from boot variable + * @boot_var: Boot variable name + * @device_dp Device path + * + * Retrieve a device patch from boot variable, @boot_var. + * + * Return: status code + */ +static efi_status_t get_dp_device(u16 *boot_var, + struct efi_device_path **device_dp) +{ + void *buf = NULL; + efi_uintn_t size; + struct efi_load_option lo; + struct efi_device_path *file_dp; + efi_status_t ret; + + size = 0; + ret = efi_get_variable_int(boot_var, &efi_global_variable_guid, + NULL, &size, NULL, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) { + buf = malloc(size); + if (!buf) + return EFI_OUT_OF_RESOURCES; + ret = efi_get_variable_int(boot_var, &efi_global_variable_guid, + NULL, &size, buf, NULL); + } + if (ret != EFI_SUCCESS) + return ret; + + efi_deserialize_load_option(&lo, buf, &size); + + if (lo.attributes & LOAD_OPTION_ACTIVE) { + efi_dp_split_file_path(lo.file_path, device_dp, &file_dp); + efi_free_pool(file_dp); + + ret = EFI_SUCCESS; + } else { + ret = EFI_NOT_FOUND; + } + + free(buf); + + return ret; +} + +/** + * device_is_present_and_system_part - check if a device exists + * @dp Device path + * + * Check if a device pointed to by the device path, @dp, exists and is + * located in UEFI system partition. + * + * Return: true - yes, false - no + */ +static bool device_is_present_and_system_part(struct efi_device_path *dp) +{ + efi_handle_t handle; + + handle = efi_dp_find_obj(dp, NULL); + if (!handle) + return false; + + return efi_disk_is_system_part(handle); +} + +/** + * find_boot_device - identify the boot device + * + * Identify the boot device from boot-related variables as UEFI + * specification describes and put its handle into bootdev_root. + * + * Return: status code + */ +static efi_status_t find_boot_device(void) +{ + char boot_var[9]; + u16 boot_var16[9], *p, bootnext, *boot_order = NULL; + efi_uintn_t size; + int i, num; + struct efi_simple_file_system_protocol *volume; + struct efi_device_path *boot_dev = NULL; + efi_status_t ret; + + /* find active boot device in BootNext */ + bootnext = 0; + size = sizeof(bootnext); + ret = efi_get_variable_int(L"BootNext", + (efi_guid_t *)&efi_global_variable_guid, + NULL, &size, &bootnext, NULL); + if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { + /* BootNext does exist here */ + if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) { + printf("BootNext must be 16-bit integer\n"); + goto skip; + } + sprintf((char *)boot_var, "Boot%04X", bootnext); + p = boot_var16; + utf8_utf16_strcpy(&p, boot_var); + + ret = get_dp_device(boot_var16, &boot_dev); + if (ret == EFI_SUCCESS) { + if (device_is_present_and_system_part(boot_dev)) { + goto out; + } else { + efi_free_pool(boot_dev); + boot_dev = NULL; + } + } + } + +skip: + /* find active boot device in BootOrder */ + size = 0; + ret = efi_get_variable_int(L"BootOrder", &efi_global_variable_guid, + NULL, &size, NULL, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) { + boot_order = malloc(size); + if (!boot_order) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + ret = efi_get_variable_int(L"BootOrder", + &efi_global_variable_guid, + NULL, &size, boot_order, NULL); + } + if (ret != EFI_SUCCESS) + goto out; + + /* check in higher order */ + num = size / sizeof(u16); + for (i = 0; i < num; i++) { + sprintf((char *)boot_var, "Boot%04X", boot_order[i]); + p = boot_var16; + utf8_utf16_strcpy(&p, boot_var); + ret = get_dp_device(boot_var16, &boot_dev); + if (ret != EFI_SUCCESS) + continue; + + if (device_is_present_and_system_part(boot_dev)) + break; + + efi_free_pool(boot_dev); + boot_dev = NULL; + } +out: + if (boot_dev) { + u16 *path_str; + + path_str = efi_dp_str(boot_dev); + EFI_PRINT("EFI Capsule: bootdev is %ls\n", path_str); + efi_free_pool(path_str); + + volume = efi_fs_from_path(boot_dev); + if (!volume) + ret = EFI_DEVICE_ERROR; + else + ret = EFI_CALL(volume->open_volume(volume, + &bootdev_root)); + efi_free_pool(boot_dev); + } else { + ret = EFI_NOT_FOUND; + } + free(boot_order); + + return ret; +} + +/** + * efi_capsule_scan_dir - traverse a capsule directory in boot device + * @files: Array of file names + * @num: Number of elements in @files + * + * Traverse a capsule directory in boot device. + * Called by initialization code, and returns an array of capsule file + * names in @files. + * + * Return: status code + */ +static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num) +{ + struct efi_file_handle *dirh; + struct efi_file_info *dirent; + efi_uintn_t dirent_size, tmp_size; + unsigned int count; + u16 **tmp_files; + efi_status_t ret; + + ret = find_boot_device(); + if (ret == EFI_NOT_FOUND) { + EFI_PRINT("EFI Capsule: bootdev is not set\n"); + *num = 0; + return EFI_SUCCESS; + } else if (ret != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + /* count capsule files */ + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh, + EFI_CAPSULE_DIR, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) { + *num = 0; + return EFI_SUCCESS; + } + + dirent_size = 256; + dirent = malloc(dirent_size); + if (!dirent) + return EFI_OUT_OF_RESOURCES; + + count = 0; + while (1) { + tmp_size = dirent_size; + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent)); + if (ret == EFI_BUFFER_TOO_SMALL) { + dirent = realloc(dirent, tmp_size); + if (!dirent) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + dirent_size = tmp_size; + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent)); + } + if (ret != EFI_SUCCESS) + goto err; + if (!tmp_size) + break; + + if (!(dirent->attribute & EFI_FILE_DIRECTORY) && + u16_strcmp(dirent->file_name, L".") && + u16_strcmp(dirent->file_name, L"..")) + count++; + } + + ret = EFI_CALL((*dirh->setpos)(dirh, 0)); + if (ret != EFI_SUCCESS) + goto err; + + /* make a list */ + tmp_files = malloc(count * sizeof(*files)); + if (!tmp_files) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + + count = 0; + while (1) { + tmp_size = dirent_size; + ret = EFI_CALL((*dirh->read)(dirh, &tmp_size, dirent)); + if (ret != EFI_SUCCESS) + goto err; + if (!tmp_size) + break; + + if (!(dirent->attribute & EFI_FILE_DIRECTORY) && + u16_strcmp(dirent->file_name, L".") && + u16_strcmp(dirent->file_name, L"..")) + tmp_files[count++] = u16_strdup(dirent->file_name); + } + /* ignore an error */ + EFI_CALL((*dirh->close)(dirh)); + + /* in ascii order */ + /* FIXME: u16 version of strcasecmp */ + qsort(tmp_files, count, sizeof(*tmp_files), + (int (*)(const void *, const void *))strcasecmp); + *files = tmp_files; + *num = count; + ret = EFI_SUCCESS; +err: + free(dirent); + + return ret; +} + +/** + * efi_capsule_read_file - read in a capsule file + * @filename: File name + * @capsule: Pointer to buffer for capsule + * + * Read a capsule file and put its content in @capsule. + * + * Return: status code + */ +static efi_status_t efi_capsule_read_file(const u16 *filename, + struct efi_capsule_header **capsule) +{ + struct efi_file_handle *dirh, *fh; + struct efi_file_info *file_info = NULL; + struct efi_capsule_header *buf = NULL; + efi_uintn_t size; + efi_status_t ret; + + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh, + EFI_CAPSULE_DIR, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) + return ret; + ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename, + EFI_FILE_MODE_READ, 0)); + /* ignore an error */ + EFI_CALL((*dirh->close)(dirh)); + if (ret != EFI_SUCCESS) + return ret; + + /* file size */ + size = 0; + ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid, + &size, file_info)); + if (ret == EFI_BUFFER_TOO_SMALL) { + file_info = malloc(size); + if (!file_info) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + ret = EFI_CALL((*fh->getinfo)(fh, &efi_file_info_guid, + &size, file_info)); + } + if (ret != EFI_SUCCESS) + goto err; + size = file_info->file_size; + free(file_info); + buf = malloc(size); + if (!buf) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + + /* fetch data */ + ret = EFI_CALL((*fh->read)(fh, &size, buf)); + if (ret == EFI_SUCCESS) { + if (size >= buf->capsule_image_size) { + *capsule = buf; + } else { + free(buf); + ret = EFI_INVALID_PARAMETER; + } + } else { + free(buf); + } +err: + EFI_CALL((*fh->close)(fh)); + + return ret; +} + +/** + * efi_capsule_delete_file - delete a capsule file + * @filename: File name + * + * Delete a capsule file from capsule directory. + * + * Return: status code + */ +static efi_status_t efi_capsule_delete_file(const u16 *filename) +{ + struct efi_file_handle *dirh, *fh; + efi_status_t ret; + + ret = EFI_CALL((*bootdev_root->open)(bootdev_root, &dirh, + EFI_CAPSULE_DIR, + EFI_FILE_MODE_READ, 0)); + if (ret != EFI_SUCCESS) + return ret; + ret = EFI_CALL((*dirh->open)(dirh, &fh, (u16 *)filename, + EFI_FILE_MODE_READ, 0)); + /* ignore an error */ + EFI_CALL((*dirh->close)(dirh)); + + ret = EFI_CALL((*fh->delete)(fh)); + + return ret; +} + +/** + * efi_capsule_scan_done - reset a scan help function + * + * Reset a scan help function + */ +static void efi_capsule_scan_done(void) +{ + EFI_CALL((*bootdev_root->close)(bootdev_root)); + bootdev_root = NULL; +} + +/** + * arch_efi_load_capsule_drivers - initialize capsule drivers + * + * Architecture or board specific initialization routine + * + * Return: status code + */ +efi_status_t __weak arch_efi_load_capsule_drivers(void) +{ + return EFI_SUCCESS; +} + +/** + * efi_launch_capsule - launch capsules + * + * Launch all the capsules in system at boot time. + * Called by efi init code + * + * Return: status codde + */ +efi_status_t efi_launch_capsules(void) +{ + u64 os_indications; + efi_uintn_t size; + struct efi_capsule_header *capsule = NULL; + u16 **files; + unsigned int nfiles, index, i; + u16 variable_name16[12]; + efi_status_t ret; + + size = sizeof(os_indications); + ret = efi_get_variable_int(L"OsIndications", &efi_global_variable_guid, + NULL, &size, &os_indications, NULL); + if (ret != EFI_SUCCESS || + !(os_indications + & EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED)) + return EFI_SUCCESS; + + index = get_last_capsule(); + + /* Load capsule drivers */ + ret = arch_efi_load_capsule_drivers(); + if (ret != EFI_SUCCESS) + return ret; + + /* + * Find capsules on disk. + * All the capsules are collected at the beginning because + * capsule files will be removed instantly. + */ + nfiles = 0; + files = NULL; + ret = efi_capsule_scan_dir(&files, &nfiles); + if (ret != EFI_SUCCESS) + return ret; + if (!nfiles) + return EFI_SUCCESS; + + /* Launch capsules */ + for (i = 0, ++index; i < nfiles; i++, index++) { + EFI_PRINT("capsule from %ls ...\n", files[i]); + if (index > 0xffff) + index = 0; + ret = efi_capsule_read_file(files[i], &capsule); + if (ret == EFI_SUCCESS) { + ret = EFI_CALL(efi_update_capsule(&capsule, 1, 0)); + if (ret != EFI_SUCCESS) + printf("EFI Capsule update failed at %ls\n", + files[i]); + + free(capsule); + } else { + printf("EFI: reading capsule failed: %ls\n", + files[i]); + } + /* create CapsuleXXXX */ + set_capsule_result(index, capsule, ret); + + /* delete a capsule either in case of success or failure */ + ret = efi_capsule_delete_file(files[i]); + if (ret != EFI_SUCCESS) + printf("EFI: deleting a capsule file failed: %ls\n", + files[i]); + } + efi_capsule_scan_done(); + + for (i = 0; i < nfiles; i++) + free(files[i]); + free(files); + + /* CapsuleLast */ + efi_create_indexed_name(variable_name16, "Capsule", index - 1); + efi_set_variable_int(L"CapsuleLast", &efi_guid_capsule_report, + EFI_VARIABLE_READ_ONLY | + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + 22, variable_name16, false); + + return ret; +} +#endif /* CONFIG_EFI_CAPSULE_ON_DISK */ diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 070ac6147c72..0735e4755b60 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -155,6 +155,10 @@ static efi_status_t efi_init_os_indications(void) os_indications_supported |= EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED; + if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK)) + os_indications_supported |= + EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED; + return efi_set_variable_int(L"OsIndicationsSupported", &efi_global_variable_guid, EFI_VARIABLE_BOOTSERVICE_ACCESS | @@ -275,6 +279,10 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + /* Execute capsules after reboot */ + if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) && + !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)) + ret = efi_launch_capsules(); out: efi_obj_list_initialized = ret; return ret; From patchwork Tue Nov 17 00:27:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324541 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4492420ejb; Mon, 16 Nov 2020 16:30:37 -0800 (PST) X-Google-Smtp-Source: ABdhPJxpqXqNv2vN/22pnUDHXtomY2Jvw0TF2cNYXfzdjh2pyyl6v2yNQW42yx5RN1Rm0Oxuuzkn X-Received: by 2002:a05:6402:783:: with SMTP id d3mr18577247edy.168.1605573037419; Mon, 16 Nov 2020 16:30:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573037; cv=none; d=google.com; s=arc-20160816; b=qeclp7GIoiYLQylFOii76lqOeeQVEPbD1ZWkhqU34e9vqj/I3DvusLxWoHitB0nNYq v+9zuoGpM8ATkIa1BYbUOF5eM0D2Y0jBCOOQvCfJLWRQjxjnEbTYKDa99WrMj5YV4ZNU Nn3jzvOpF4n8WV63NwxR0fpIVPbnp4JK+is+G+jJQyCTUi4xCCCmntqyb2ruDmOmQzp9 6O+WTWDmqGYwRhmukyuz9S0d/yHWp7a/40+A7zzdE5ASgpWFUaBRxDFykMYykMj6doXl wOolNGO83ST8o18VEc3fmedJR/oZkM/6P6EDNeiHM7ZZIaVohS9EssvlY5BnqeiGCF0Q qMow== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=pfzS9a249CGCsTB62oWKa+nEqo4kbxAX5xW5fvW6X+k=; b=TXc443bH4QC/vqKhHFeAVZs9ohdeebVxIU5abU2kaZ474W79Rusj6JDcOxPLXAb3vW pA74qcdKOCIELz6HjDUhskU/YejjtCMy+OlrVWSOHkhmu6CUrNrf41xjk6yC9DuiRIAT dgO+DuNJpndDdkqG7TLywOlGdN92btWbcrsUJik5W8Yu3Xukri3F+nXcq8Lp4jBVcU6j 6JM23O0Z1Ar8ficxtkZzQZqYuBWUbT4LX4nqp8gNN4PSZqSBa0if57HHgTcvu7iC1VSH mdXYqA/KcxDUXGAfVdnzkkZth3JHGecFdPlvElSPo0N/gmtZoX4EMGXr4A66l3fHGtMy nRsw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Nj5IsVqz; 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 c15si13420537ejr.181.2020.11.16.16.30.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:30:37 -0800 (PST) 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=Nj5IsVqz; 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 386D382569; Tue, 17 Nov 2020 01:29:52 +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="Nj5IsVqz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8DEA1825A0; Tue, 17 Nov 2020 01:29:21 +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.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,T_SPF_HELO_TEMPERROR autolearn=no autolearn_force=no version=3.4.2 Received: from mail-pf1-x442.google.com (mail-pf1-x442.google.com [IPv6:2607:f8b0:4864:20::442]) (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 BFF018255C for ; Tue, 17 Nov 2020 01:29:02 +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=takahiro.akashi@linaro.org Received: by mail-pf1-x442.google.com with SMTP id g7so15791707pfc.2 for ; Mon, 16 Nov 2020 16:29:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pfzS9a249CGCsTB62oWKa+nEqo4kbxAX5xW5fvW6X+k=; b=Nj5IsVqz7qtDUZ3AalZ86U7ldq9gnx+4Lhsl/95GVRqfFXA+IqJcQ4MwGcmy/CAD1I rqqEJNqQ63ILBqrGYRMLxfXNqE2rFjyb3IZ9qCyqF+K9p9mzwX3q4bZVHGNmux5RmvuB /npGrr/Ha7w+zwUom4Cw9gad6Ax4bOqG/juQY5FN/UwSczqpqGO78mqfMKSJD2uvN0dn MayPPhFfNW4yErKLJzmpthNqG8dOTPwTYjMzTk1iYXkjgc5mx0FMBF44hLrYvXpFUsq7 yHgZPFKjfSaUJLjrPgw/rK0o5QjwrtuOAUv0bQMN3dEpn6+USNQeFTCNRihoeX+6wMI1 8ISg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pfzS9a249CGCsTB62oWKa+nEqo4kbxAX5xW5fvW6X+k=; b=ZktGdnOYjoaW4xE3GfQzvP9mdNl07IaKSqnwmJa3ZEdzaMI7W9DZlBuYoAAzJzyRQr nJl+RzN2z2zbjK6wR8G4I1pyEKTsjW1jcZNfA16i28csbcY7Mbr3zHNQnJLqvwX18r9W MCWMQ9D5LGJKh0dqeNPMdBQRppYTZiHBrgTZThumXFWw0S+50pKQkctx3WghHTdSx6wv iAjJfUJ8A/B1ekQJIWt63ndXoGQhRSKcZVP801jOeK0MuK02ku1g9CmNR9Wu41jOrOAF YktnMbOxH51p1YRpirO3K4P4y2Jfborw54cGnfuY1efFmAv0L5plmoFkMi8yu9MnjSW3 j/oQ== X-Gm-Message-State: AOAM5330oOeHrTBY6CbvJqz4ub7FJzWpXp75jxyoF1etyCa2mh6FjJVc 2XesqRcmm1+tlT17zUOloa0O+w== X-Received: by 2002:a17:90a:7d06:: with SMTP id g6mr1597416pjl.5.1605572933180; Mon, 16 Nov 2020 16:28:53 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.28.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:28:52 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 03/11] efi_loader: capsule: add memory range capsule definitions Date: Tue, 17 Nov 2020 09:27:57 +0900 Message-Id: <20201117002805.13902-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean Memory range capsule gives us a way to notify that some memory regions should be left untouched across the next reset. See UEFI specification, section 8.5.3. Since how we should handle this kind of capsule is totally up to the system, no implementation will be added in this commit. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) -- 2.28.0 diff --git a/include/efi_api.h b/include/efi_api.h index c128a0a66ce8..7a2a087c60ed 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -221,6 +221,10 @@ enum efi_reset_type { EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \ 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) +#define EFI_MEMORY_RANGE_CAPSULE_GUID \ + EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \ + 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -236,6 +240,19 @@ struct efi_capsule_result_variable_header { efi_status_t capsule_status; } __packed; +struct efi_memory_range { + efi_physical_addr_t address; + u64 length; +}; + +struct efi_memory_range_capsule { + struct efi_capsule_header *header; + /* EFI_MEMORY_TYPE: 0x80000000-0xFFFFFFFF */ + enum efi_mem_type os_requested_memory_type; + u64 number_of_memory_ranges; + struct efi_memory_range memory_ranges[]; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 From patchwork Tue Nov 17 00:27:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324539 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4492007ejb; Mon, 16 Nov 2020 16:29:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJwc31utdVyNvd7vtvHDo9jE9/VOgu5m9t241z193/P7XbhyNjqCrMgafIpOf4Fded6Hr7Au X-Received: by 2002:aa7:c2c4:: with SMTP id m4mr19208023edp.66.1605572998952; Mon, 16 Nov 2020 16:29:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605572998; cv=none; d=google.com; s=arc-20160816; b=hLguE3GtdrPmdX7kXik2N6+4T6TeQOdyae+nFeYonLbA6k/kKq9XMJ01XQyz5Ep97U uZ8TZpauNlgxE1rxZP3h1vEchOH3+cDtL6xbyNshfEgrBfn2PpsaCgWljYu6bNETJhiB UZQvcOWgu6qs5A4CG7ksJjPVygAQNUY/JTk9/Majoe2yWzj/mD3Q2vJgBe8teisMrz+O FGzCKl5hoaC9ixPtPxnUniQAwxFWOz0NB6lCbloo7n5/dMNMclgVptqYHNpCEEBpEAUe TWhwWAnYV2e/CQkBnau4QVHIzi843lZUReKKyhmJAyrdgYgHbFDNLfCyvFkVda9n+3xs R2mA== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=lqT8ni4KOQD405gWDmUW62k9YxiUBqJdoiWQmaLbIms=; b=Se1pDZOvSqCWr4k8wsAZ4gVI0tV8Lz6vLZlDJBF1kdHEd5h7tR20d0Nr58CgfjySkN eS01tbriiwtre4nR1hSj2bpF2I7oxStcPVomenBGrGik0xOfytM5HKSHRgigunduApeN xQmyTRZW5x+XRglQGLx/cP00l/UBw+OiSxf38AYZfvvRVhpRO6gXnToKfi16clv7elb2 ZWZrAu91z88ieGLqox0rlrotlDXXuiNSOYmupfjCQfyZcXNW+Ji8bzHMeWAyYRniWb7p K5Yu9eTXVjzxYrSuBHKw8gvH+Q3oXa7/E3IWqqq2Yzt50InzVS7Gyf4hQ1kbfcrLoM3I WZ2Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=MQL98LZ6; 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 p8si12021399ejf.396.2020.11.16.16.29.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:58 -0800 (PST) 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=MQL98LZ6; 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 56DEB82573; Tue, 17 Nov 2020 01:29:27 +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="MQL98LZ6"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D179982585; Tue, 17 Nov 2020 01:29: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=-1.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,T_SPF_HELO_TEMPERROR,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) (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 497EF821F7 for ; Tue, 17 Nov 2020 01:28:57 +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=takahiro.akashi@linaro.org Received: by mail-pg1-x52f.google.com with SMTP id q28so4219390pgk.1 for ; Mon, 16 Nov 2020 16:28:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lqT8ni4KOQD405gWDmUW62k9YxiUBqJdoiWQmaLbIms=; b=MQL98LZ6ZxAjA5wnwAZ/5UpwAnPD0/BGflpZqmZxNDIaIeutOy08bLA7lYVg2xOZDL 5SQsZVuVpX9TTnUWbVy8Ct25tn24vvhRpXJhCARXi3SprKa74fXDW7HpmUefxkGG2D/r QVgwFtR7TdDyZL4jrJsTMY4vRfV7xetvNyz4j0ItTzuSvK/qya7JGaQ4UBJrMHTBwzq7 qF7d08fvPg4BWj3BFgNIZ8Mj1J1ySFV+SGZ7C/ERlhfKZ1+B03AZwo8h8LV0DA4Ba96+ Y917xV4Gep9ZcEfaG4RZly24boOXTuZ0hu/vl2NG5E7hK9e6AX1DGC/H9SKGcxaKmfyc jaUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lqT8ni4KOQD405gWDmUW62k9YxiUBqJdoiWQmaLbIms=; b=Jrvm5yf1J3jmkR1d5NOJKbVXCx6jGWEXAbIASRjhJZc+x4qBJgbcL365HlY7oWojRo HAk6UqbY5kMGbnM6oWlai/ydGkYGqnDO2Eu2nGUjYk2xojNbB7W9Nwcwz5AozFogZnn7 O1bhviJvr72h/7nlCcTtW/ARMeLK+YMFmkTs7CSc6c02bqRO1KIJqfjL79bD4awzwex/ LoAH9RMMgNYOw48qvLlBKr1p5VKAsIL8Qplx97DifkYkICqhrHLLnV2XFeFVU2rSe18g lExKorq74u/uvU+euXZSb0RqCWKDyTR+yFBiqVdSWz7W9hJ3pufCZ1Ld/KiPygtV5d1h 1ALA== X-Gm-Message-State: AOAM533Ju899M4IAcyoqBuk70HFz47eRt3sDUwgELALoKTq76U0I95wU C7lKZfuNgzlQv2Fk7Am+Za4Q8A== X-Received: by 2002:a17:90a:fa93:: with SMTP id cu19mr1701311pjb.117.1605572935764; Mon, 16 Nov 2020 16:28:55 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.28.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:28:55 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 04/11] efi_loader: capsule: support firmware update Date: Tue, 17 Nov 2020 09:27:58 +0900 Message-Id: <20201117002805.13902-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean A capsule tagged with the guid, EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID, is handled as a firmware update object. What efi_update_capsule() basically does is to load any firmware management protocol (or fmp) drivers contained in a capsule, find out an appropriate fmp driver and then invoke its set_image() interface against each binary in a capsule. In this commit, however, loading drivers is not supported. The result of applying a capsule is set to be stored in "CapsuleXXXX" variable, but its implementation is deferred to a fmp driver. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 129 +++++++++++++++++++ include/efi_loader.h | 2 + lib/efi_loader/Kconfig | 8 ++ lib/efi_loader/efi_capsule.c | 238 ++++++++++++++++++++++++++++++++++- lib/efi_loader/efi_setup.c | 4 + 5 files changed, 380 insertions(+), 1 deletion(-) -- 2.28.0 diff --git a/include/efi_api.h b/include/efi_api.h index 7a2a087c60ed..966bc6e590bf 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -217,6 +217,9 @@ enum efi_reset_type { #define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 #define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 +#define CAPSULE_SUPPORT_AUTHENTICATION 0x0000000000000001 +#define CAPSULE_SUPPORT_DEPENDENCY 0x0000000000000002 + #define EFI_CAPSULE_REPORT_GUID \ EFI_GUID(0x39b68c46, 0xf7fb, 0x441b, 0xb6, 0xec, \ 0x16, 0xb0, 0xf6, 0x98, 0x21, 0xf3) @@ -225,6 +228,10 @@ enum efi_reset_type { EFI_GUID(0xde9f0ec, 0x88b6, 0x428f, 0x97, 0x7a, \ 0x25, 0x8f, 0x1d, 0xe, 0x5e, 0x72) +#define EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID \ + EFI_GUID(0x6dcbd5ed, 0xe82d, 0x4c44, 0xbd, 0xa1, \ + 0x71, 0x94, 0x19, 0x9a, 0xd9, 0x2a) + struct efi_capsule_header { efi_guid_t capsule_guid; u32 header_size; @@ -253,6 +260,33 @@ struct efi_memory_range_capsule { struct efi_memory_range memory_ranges[]; } __packed; +struct efi_firmware_management_capsule_header { + u32 version; + u16 embedded_driver_count; + u16 payload_item_count; + u64 item_offset_list[]; +} __packed; + +struct efi_firmware_management_capsule_image_header { + u32 version; + efi_guid_t update_image_type_id; + u8 update_image_index; + u8 reserved[3]; + u32 update_image_size; + u32 update_vendor_code_size; + u64 update_hardware_instance; + u64 image_capsule_support; +} __packed; + +struct efi_capsule_result_variable_fmp { + u16 version; + u8 payload_index; + u8 update_image_index; + efi_guid_t update_image_type_id; + // u16 capsule_file_name[]; + // u16 capsule_target[]; +} __packed; + #define EFI_RT_SUPPORTED_GET_TIME 0x0001 #define EFI_RT_SUPPORTED_SET_TIME 0x0002 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004 @@ -1808,4 +1842,99 @@ struct efi_signature_list { /* struct efi_signature_data signatures[...][signature_size]; */ } __attribute__((__packed__)); +/* + * Firmware management protocol + */ +#define EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID \ + EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \ + 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7) + +#define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x0000000000000001 +#define IMAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 +#define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x0000000000000004 +#define IMAGE_ATTRIBUTE_IN_USE 0x0000000000000008 +#define IMAGE_ATTRIBUTE_UEFI_IMAGE 0x0000000000000010 +#define IMAGE_ATTRIBUTE_DEPENDENCY 0x0000000000000020 + +#define IMAGE_COMPATIBILITY_CHECK_SUPPORTED 0x0000000000000001 + +#define IMAGE_UPDATABLE_VALID 0x0000000000000001 +#define IMAGE_UPDATABLE_INVALID 0x0000000000000002 +#define IMAGE_UPDATABLE_INVALID_TYPE 0x0000000000000004 +#define IMAGE_UPDATABLE_INVALID_OLLD 0x0000000000000008 +#define IMAGE_UPDATABLE_VALID_WITH_VENDOR_CODE 0x0000000000000010 + +#define PACKAGE_ATTRIBUTE_VERSION_UPDATABLE 0x0000000000000001 +#define PACKAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 +#define PACKAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x0000000000000004 + +#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION 4 + +typedef struct efi_firmware_image_dependencies { + u8 dependencies[0]; +} efi_firmware_image_dep_t; + +struct efi_firmware_image_descriptor { + u8 image_index; + efi_guid_t image_type_id; + u64 image_id; + u16 *image_id_name; + u32 version; + u16 *version_name; + efi_uintn_t size; + u64 attributes_supported; + u64 attributes_setting; + u64 compatibilities; + u32 lowest_supported_image_version; + u32 last_attempt_version; + u32 last_attempt_status; + u64 hardware_instance; + efi_firmware_image_dep_t *dependencies; +}; + +struct efi_firmware_management_protocol { + efi_status_t (EFIAPI *get_image_info)( + struct efi_firmware_management_protocol *this, + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, + u32 *package_version, + u16 **package_version_name); + efi_status_t (EFIAPI *get_image)( + struct efi_firmware_management_protocol *this, + u8 image_index, + void *image, + efi_uintn_t *image_size); + efi_status_t (EFIAPI *set_image)( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t image_size, + const void *vendor_code, + efi_status_t (*progress)(efi_uintn_t completion), + u16 **abort_reason); + efi_status_t (EFIAPI *check_image)( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t *image_size, + u32 *image_updatable); + efi_status_t (EFIAPI *get_package_info)( + struct efi_firmware_management_protocol *this, + u32 *package_version, + u16 **package_version_name, + u32 *package_version_name_maxlen, + u64 *attributes_supported, + u64 *attributes_setting); + efi_status_t (EFIAPI *set_package_info)( + struct efi_firmware_management_protocol *this, + const void *image, + efi_uintn_t *image_size, + const void *vendor_code, + u32 package_version, + const u16 *package_version_name); +}; + #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index eb57e7455eb1..1a728bf9702d 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -209,6 +209,8 @@ extern const efi_guid_t efi_guid_cert_type_pkcs7; extern const efi_guid_t efi_guid_rng_protocol; /* GUID of capsule update result */ extern const efi_guid_t efi_guid_capsule_report; +/* GUID of firmware management protocol */ +extern const efi_guid_t efi_guid_firmware_management_protocol; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index e1ac5ac055de..5cb34687c26a 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -126,6 +126,14 @@ config EFI_CAPSULE_ON_DISK_EARLY executed as part of U-Boot initialisation so that they will surely take place whatever is set to distro_bootcmd. +config EFI_CAPSULE_FIRMWARE_MANAGEMENT + bool "Capsule: Firmware Management Protocol" + depends on EFI_HAVE_CAPSULE_SUPPORT + default y + help + Select this option if you want to enable capsule-based + firmware update using Firmware Management Protocol. + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index b3c7d1b735b6..2f41c17f5057 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -15,6 +15,10 @@ #include const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; +static const efi_guid_t efi_guid_firmware_management_capsule_id = + EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; +const efi_guid_t efi_guid_firmware_management_protocol = + EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID; #ifdef CONFIG_EFI_CAPSULE_ON_DISK /* for file system access */ @@ -88,6 +92,218 @@ void set_capsule_result(int index, struct efi_capsule_header *capsule, printf("EFI: creating %ls failed\n", variable_name16); } +#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT +/** + * efi_fmp_find - search for Firmware Management Protocol drivers + * @image_type: Image type guid + * @instance: Instance number + * @handles: Handles of FMP drivers + * @no_handles: Number of handles + * + * Search for Firmware Management Protocol drivers, matching the image + * type, @image_type and the machine instance, @instance, from the list, + * @handles. + * + * Return: + * * Protocol instance - on success + * * NULL - on failure + */ +static struct efi_firmware_management_protocol * +efi_fmp_find(efi_guid_t *image_type, u64 instance, efi_handle_t *handles, + efi_uintn_t no_handles) +{ + efi_handle_t *handle; + struct efi_firmware_management_protocol *fmp; + struct efi_firmware_image_descriptor *image_info, *desc; + efi_uintn_t info_size, descriptor_size; + u32 descriptor_version; + u8 descriptor_count; + u32 package_version; + u16 *package_version_name; + bool found = false; + int i, j; + efi_status_t ret; + + for (i = 0, handle = handles; i < no_handles; i++, handle++) { + ret = EFI_CALL(efi_handle_protocol( + *handle, + &efi_guid_firmware_management_protocol, + (void **)&fmp)); + if (ret != EFI_SUCCESS) + continue; + + /* get device's image info */ + info_size = 0; + image_info = NULL; + descriptor_version = 0; + descriptor_count = 0; + descriptor_size = 0; + package_version = 0; + package_version_name = NULL; + ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, + image_info, + &descriptor_version, + &descriptor_count, + &descriptor_size, + &package_version, + &package_version_name)); + if (ret != EFI_BUFFER_TOO_SMALL) + goto skip; + + image_info = malloc(info_size); + if (!image_info) + goto skip; + + ret = EFI_CALL(fmp->get_image_info(fmp, &info_size, + image_info, + &descriptor_version, + &descriptor_count, + &descriptor_size, + &package_version, + &package_version_name)); + if (ret != EFI_SUCCESS) + goto skip; + + /* matching */ + for (j = 0, desc = image_info; j < descriptor_count; + j++, desc = (void *)desc + descriptor_size) { + EFI_PRINT("+++ desc[%d] index: %d, name: %ls\n", + j, desc->image_index, desc->image_id_name); + if (!guidcmp(&desc->image_type_id, image_type) && + (!instance || + !desc->hardware_instance || + (descriptor_version >= 3 && + desc->hardware_instance == instance))) + found = true; + } + +skip: + efi_free_pool(package_version_name); + free(image_info); + EFI_CALL(efi_close_protocol( + (efi_handle_t)fmp, + &efi_guid_firmware_management_protocol, + NULL, NULL)); + if (found) + return fmp; + } + + return NULL; +} + +/** + * efi_capsule_update_firmware - update firmware from capsule + * @capsule_data: Capsule + * + * Update firmware, using a capsule, @capsule_data. Loading any FMP + * drivers embedded in a capsule is not supported. + * + * Return: status code + */ +static efi_status_t efi_capsule_update_firmware( + struct efi_capsule_header *capsule_data) +{ + struct efi_firmware_management_capsule_header *capsule; + struct efi_firmware_management_capsule_image_header *image; + size_t capsule_size; + void *image_binary, *vendor_code; + efi_handle_t *handles; + efi_uintn_t no_handles; + int item; + struct efi_firmware_management_protocol *fmp; + u16 *abort_reason; + efi_status_t ret = EFI_SUCCESS; + + /* sanity check */ + if (capsule_data->header_size < sizeof(*capsule) || + capsule_data->header_size >= capsule_data->capsule_image_size) + return EFI_INVALID_PARAMETER; + + capsule = (void *)capsule_data + capsule_data->header_size; + capsule_size = capsule_data->capsule_image_size + - capsule_data->header_size; + + if (capsule->version != 0x00000001) + return EFI_INVALID_PARAMETER; + + /* Drivers */ + /* TODO: support loading drivers */ + + handles = NULL; + ret = EFI_CALL(efi_locate_handle_buffer( + BY_PROTOCOL, + &efi_guid_firmware_management_protocol, + NULL, &no_handles, (efi_handle_t **)&handles)); + if (ret != EFI_SUCCESS) + return EFI_UNSUPPORTED; + + /* Payload */ + for (item = capsule->embedded_driver_count; + item < capsule->embedded_driver_count + + capsule->payload_item_count; item++) { + /* sanity check */ + if ((capsule->item_offset_list[item] + sizeof(*image) + >= capsule_size)) { + printf("EFI: A capsule has not enough size of data\n"); + ret = EFI_INVALID_PARAMETER; + goto out; + } + + image = (void *)capsule + capsule->item_offset_list[item]; + + if (image->version != 0x00000001 && + image->version != 0x00000002 && + image->version != 0x00000003) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + /* find a device for update firmware */ + /* TODO: should we pass index as well, or nothing but type? */ + fmp = efi_fmp_find(&image->update_image_type_id, + image->version == 0x1 ? 0 : + image->update_hardware_instance, + handles, no_handles); + if (!fmp) { + printf("EFI Capsule: driver not found for firmware type: %pUl, hardware instance: %lld\n", + &image->update_image_type_id, + image->version == 0x1 ? 0 : + image->update_hardware_instance); + ret = EFI_UNSUPPORTED; + goto out; + } + + /* do it */ + image_binary = (void *)image + sizeof(*image); + vendor_code = image_binary + image->update_image_size; + + abort_reason = NULL; + ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index, + image_binary, + image->update_image_size, + vendor_code, NULL, + &abort_reason)); + if (ret != EFI_SUCCESS) { + printf("EFI Capsule: firmware update failed: %ls\n", + abort_reason); + efi_free_pool(abort_reason); + goto out; + } + } + +out: + efi_free_pool(handles); + + return ret; +} +#else +static efi_status_t efi_capsule_update_firmware( + struct efi_capsule_header *capsule_data) +{ + return EFI_UNSUPPORTED; +} +#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */ + /** * efi_update_capsule() - process information from operating system * @capsule_header_array: Array of virtual address pointers @@ -118,9 +334,29 @@ efi_status_t EFIAPI efi_update_capsule( goto out; } - ret = EFI_UNSUPPORTED; + ret = EFI_SUCCESS; for (i = 0, capsule = *capsule_header_array; i < capsule_count; i++, capsule = *(++capsule_header_array)) { + /* sanity check */ + if (capsule->header_size < sizeof(*capsule) || + capsule->capsule_image_size < sizeof(*capsule)) { + printf("EFI: A capsule has not enough size of data\n"); + continue; + } + + EFI_PRINT("Capsule[%d] (guid:%pUl)\n", + i, &capsule->capsule_guid); + if (!guidcmp(&capsule->capsule_guid, + &efi_guid_firmware_management_capsule_id)) { + ret = efi_capsule_update_firmware(capsule); + } else { + printf("EFI: not support capsule type: %pUl\n", + &capsule->capsule_guid); + ret = EFI_UNSUPPORTED; + } + + if (ret != EFI_SUCCESS) + goto out; } out: return EFI_EXIT(ret); diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 0735e4755b60..feec9b53c8ed 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -159,6 +159,10 @@ static efi_status_t efi_init_os_indications(void) os_indications_supported |= EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED; + if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT)) + os_indications_supported |= + EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED; + return efi_set_variable_int(L"OsIndicationsSupported", &efi_global_variable_guid, EFI_VARIABLE_BOOTSERVICE_ACCESS | From patchwork Tue Nov 17 00:27:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324543 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4492800ejb; Mon, 16 Nov 2020 16:31:17 -0800 (PST) X-Google-Smtp-Source: ABdhPJxrdowQuuylq451NyuQRWZQzOrr/im/+S3vhlra51x/GYbJC6SJWK49Gou3VEyargwbt+P0 X-Received: by 2002:a05:6402:755:: with SMTP id p21mr18619885edy.349.1605573077181; Mon, 16 Nov 2020 16:31:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573077; cv=none; d=google.com; s=arc-20160816; b=Fp6Buz1J46Uyo8ZsN4Wwzp5O1IMe1YgWkGZm+M13ZD4PJYPJx2SMJ+WR9vDMozqJXw oMViyMRngtJCpw2RTFnkL5I83GLZGLMO3S5nWUwQNX42h6EV7/z06SBcS7J2e+5yfu0r /fElXrBsHeDdF4FrFRUDOFSD4vyzo12W0vDwCPfrnGJcuydCSOdEIEfG/8AYNTRAP3Tz /5eHnDlwQ1QEZg7VuMzaXnT9UdcInq4E0Phm2nYvVKiXAQbbJ0qIAdTI68A5EBR63tyc 5ng5dX0/yB7+ytB3uIwwvsGJkWmfTt/BCZ5SoJ9ft5QCXawP2/APqqyWj1KcfuLKcRwY 6eSg== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=q6z4HjlyA7O0gQeA71lvSzxS7vDbm2z5JuZFK5x9dw0=; b=XpQXIY6vN3siz2/43t4Kgcb0vQGm8Zkg1QVZF2WMTsWRN0kkCiB5wSY072uIeCTeN7 0QK9d6N7WaP/EaCl2Mff/R9p6bvVOYTc4Fbd6dpH7aZnoGb91AyvJPVkl+Uct8tMmB+w 7CYzUeHCceRsX7hwiBBx8gxjqHXYAZqSXnRK1puf/biPzlpV8wOE7hzN4n3XTBm8QoRN l2ebSUMck8qmKLVHubyBxqoVDNKWetl558O/9iidk/sRXrOFT5gq6JDDkMqKom+RnAG2 Inz5YrllRphtvjMZunvhTnqbZCfgB8YejNhbL9JEPxSZ4tUqCcRzHSTIg2hBw0i9pJEe ahOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="yjv8x/6q"; 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 lt14si12202025ejb.291.2020.11.16.16.31.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:31:17 -0800 (PST) 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="yjv8x/6q"; 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 CB5A282588; Tue, 17 Nov 2020 01:30:17 +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="yjv8x/6q"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2C27C825A3; Tue, 17 Nov 2020 01:29:23 +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.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,T_SPF_HELO_TEMPERROR autolearn=no autolearn_force=no version=3.4.2 Received: from mail-pl1-x641.google.com (mail-pl1-x641.google.com [IPv6:2607:f8b0:4864:20::641]) (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 4B55182573 for ; Tue, 17 Nov 2020 01:29: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=takahiro.akashi@linaro.org Received: by mail-pl1-x641.google.com with SMTP id s2so9253191plr.9 for ; Mon, 16 Nov 2020 16:29:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=q6z4HjlyA7O0gQeA71lvSzxS7vDbm2z5JuZFK5x9dw0=; b=yjv8x/6qP+JjjQq4+LwP+Vfil08BsgjI1ZQbt2zRDjniBlDhGVpU4NCfVdcGrkntDg WDRq0pxOtrBhjlTvuJsnpHCgapJLkx1xn+nrughv12dl26D/ktfytxrYsBj1CMYv3LWY 25kgbkyuAeG6jFJvg7pMitlIkJlzI6auLZGzOhbw3SWEuLqpMrHLGt9jprMHymlUizro j1BHzQJFYzaZ48Q7UUtD16t8jtb4kfp1neOOfHGdeNmhnqyddW0LRakz8jnDwRhDDnmL nI2hvMiQQSsadq0armj2Er8eGOBTj3GN6DuQRMFKdbXZxXu2rBb7OuCOGqO9FmkClrBY Bg6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=q6z4HjlyA7O0gQeA71lvSzxS7vDbm2z5JuZFK5x9dw0=; b=rXNaIzp6+Zp9/0rmAJUbZf55rOY+5yq8pEkaxRolJml5rwIpWUO+NXNcoC0ea6fnWl gpzNhD2VBKoeQy2C9j6ysMSfi46uTy+liPl0xawYjh1TKXGN3hfriChSa7GBgea7F2L4 y3ljwOEC+/xDVNAo/UPrFijYrrlLCWIx+D/SnkPjTERBADDVd6W4LRFlhyad0rewNmaJ RoSHpnYXIEKfnuCjtE2i/Yk/pa9uCUyl+THgShCRhq/r95kcleE4TMHLHnQbClz/aCh+ T7JB630aa/3FsoR/IniG/9ZwecPZt80wRfwhCul7oZPBC7xuOSipLeLKOiMhH7yyUgYh 9Y9w== X-Gm-Message-State: AOAM530BG1Hu/j9gODtDMGTPUYP+TfDYENWFQkwDOhTyBIXKOUZDcwDq cLwBHbaMHS54zqfl2Tj9dr7pFA== X-Received: by 2002:a17:902:a5c7:b029:d8:edae:f4ea with SMTP id t7-20020a170902a5c7b02900d8edaef4eamr6000717plq.75.1605572938486; Mon, 16 Nov 2020 16:28:58 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.28.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:28:57 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 05/11] efi_loader: add firmware management protocol for FIT image Date: Tue, 17 Nov 2020 09:27:59 +0900 Message-Id: <20201117002805.13902-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean In this commit, a very simple firmware management protocol driver is implemented. It will take a common FIT image firmware in a capsule file and apply the data using dfu backend storage drivers via update_fit() interface. So "dfu_alt_info" variable should be properly set to specify a device and location to be updated. Please read README.dfu. Fit image is a common file format for firmware update on U-Boot, and this protocol works neatly just as a wrapper for one. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 4 + include/efi_loader.h | 2 + lib/efi_loader/Kconfig | 11 ++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_capsule.c | 12 +- lib/efi_loader/efi_firmware.c | 291 ++++++++++++++++++++++++++++++++++ 6 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 lib/efi_loader/efi_firmware.c -- 2.28.0 diff --git a/include/efi_api.h b/include/efi_api.h index 966bc6e590bf..071d0ba866c7 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1849,6 +1849,10 @@ struct efi_signature_list { EFI_GUID(0x86c77a67, 0x0b97, 0x4633, 0xa1, 0x87, \ 0x49, 0x10, 0x4d, 0x06, 0x85, 0xc7) +#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID \ + EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \ + 0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47) + #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x0000000000000001 #define IMAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 #define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x0000000000000004 diff --git a/include/efi_loader.h b/include/efi_loader.h index 1a728bf9702d..d24d0ff0e78a 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -811,6 +811,8 @@ void efi_memcpy_runtime(void *dest, const void *src, size_t n); /* commonly used helper function */ u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index); +extern const struct efi_firmware_management_protocol efi_fmp_fit; + /* Capsule update */ efi_status_t EFIAPI efi_update_capsule( struct efi_capsule_header **capsule_header_array, diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 5cb34687c26a..159400fec39e 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -134,6 +134,17 @@ config EFI_CAPSULE_FIRMWARE_MANAGEMENT Select this option if you want to enable capsule-based firmware update using Firmware Management Protocol. +config EFI_CAPSULE_FIRMWARE_FIT + bool "FMP driver for FIT image" + depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT + depends on FIT + select UPDATE_FIT + select DFU + default n + help + Select this option if you want to enable firmware management protocol + driver for FIT image + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 8d729abdfa78..dedb702c5d43 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_bootmgr.o obj-y += efi_boottime.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o obj-y += efi_console.o obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 2f41c17f5057..8265aac226f2 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -804,7 +804,17 @@ static void efi_capsule_scan_done(void) */ efi_status_t __weak arch_efi_load_capsule_drivers(void) { - return EFI_SUCCESS; + __maybe_unused efi_handle_t handle; + efi_status_t ret = EFI_SUCCESS; + + if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_FIT)) { + handle = NULL; + ret = EFI_CALL(efi_install_multiple_protocol_interfaces( + &handle, &efi_guid_firmware_management_protocol, + &efi_fmp_fit, NULL)); + } + + return ret; } /** diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c new file mode 100644 index 000000000000..4c395f4eb5d9 --- /dev/null +++ b/lib/efi_loader/efi_firmware.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI Firmware management protocol + * + * Copyright (c) 2020 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include + +/* + * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update + * method with existing FIT image format, and handles + * - multiple regions of firmware via DFU + * but doesn't support + * - versioning of firmware image + * - package information + */ +const efi_guid_t efi_firmware_image_type_uboot_fit = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; + +/** + * efi_get_dfu_info - return information about the current firmware image + * @this: Protocol instance + * @image_info_size: Size of @image_info + * @image_info: Image information + * @descriptor_version: Pointer to version number + * @descriptor_count: Pointer to number of descriptors + * @descriptor_size: Pointer to descriptor size + * package_version: Package version + * package_version_name: Package version's name + * image_type: Image type GUID + * + * Return information bout the current firmware image in @image_info. + * @image_info will consist of a number of descriptors. + * Each descriptor will be created based on "dfu_alt_info" variable. + * + * Return status code + */ +static efi_status_t efi_get_dfu_info( + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, + u32 *package_version, + u16 **package_version_name, + const efi_guid_t *image_type) +{ + struct dfu_entity *dfu; + size_t names_len, total_size; + int dfu_num, i; + u16 *name, *next; + + dfu_init_env_entities(NULL, NULL); + + names_len = 0; + dfu_num = 0; + list_for_each_entry(dfu, &dfu_list, list) { + names_len += (utf8_utf16_strlen(dfu->name) + 1) * 2; + dfu_num++; + } + if (!dfu_num) { + EFI_PRINT("Probably dfu_alt_info not defined\n"); + *image_info_size = 0; + dfu_free_entities(); + + return EFI_SUCCESS; + } + + total_size = sizeof(*image_info) * dfu_num + names_len; + /* + * we will assume that sizeof(*image_info) * dfu_name + * is, at least, a multiple of 2. So the start address for + * image_id_name would be aligned with 2 bytes. + */ + if (*image_info_size < total_size) { + *image_info_size = total_size; + dfu_free_entities(); + + return EFI_BUFFER_TOO_SMALL; + } + *image_info_size = total_size; + + *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; + *descriptor_count = dfu_num; + *descriptor_size = sizeof(*image_info); + *package_version = 0xffffffff; /* not supported */ + *package_version_name = NULL; /* not supported */ + + /* DFU alt number should correspond to image_index */ + i = 0; + /* Name area starts just after descriptors */ + name = (u16 *)((u8 *)image_info + sizeof(*image_info) * dfu_num); + next = name; + list_for_each_entry(dfu, &dfu_list, list) { + image_info[i].image_index = dfu->alt + 1; + image_info[i].image_type_id = *image_type; + image_info[i].image_id = dfu->alt; + + /* copy the DFU entity name */ + utf8_utf16_strcpy(&next, dfu->name); + image_info[i].image_id_name = name; + name = ++next; + + image_info[i].version = 0; /* not supported */ + image_info[i].version_name = NULL; /* not supported */ + image_info[i].size = 0; + image_info[i].attributes_supported = + IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; + image_info[i].attributes_setting = + IMAGE_ATTRIBUTE_IMAGE_UPDATABLE; + image_info[i].lowest_supported_image_version = 0; + image_info[i].last_attempt_version = 0; + image_info[i].last_attempt_status = LAST_ATTEMPT_STATUS_SUCCESS; + image_info[i].hardware_instance = 1; + image_info[i].dependencies = NULL; + + i++; + } + + dfu_free_entities(); + + return EFI_SUCCESS; +} + +/** + * efi_firmware_fit_get_image_info - return information about the current + * firmware image + * @this: Protocol instance + * @image_info_size: Size of @image_info + * @image_info: Image information + * @descriptor_version: Pointer to version number + * @descriptor_count: Pointer to number of descriptors + * @descriptor_size: Pointer to descriptor size + * package_version: Package version + * package_version_name: Package version's name + * + * Return information bout the current firmware image in @image_info. + * @image_info will consist of a number of descriptors. + * Each descriptor will be created based on "dfu_alt_info" variable. + * + * Return status code + */ +static +efi_status_t EFIAPI efi_firmware_fit_get_image_info( + struct efi_firmware_management_protocol *this, + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, + u32 *package_version, + u16 **package_version_name) +{ + efi_status_t ret; + + EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, + image_info_size, image_info, + descriptor_version, descriptor_count, descriptor_size, + package_version, package_version_name); + + if (!image_info_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (*image_info_size && + (!image_info || !descriptor_version || !descriptor_count || + !descriptor_size || !package_version || !package_version_name)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + ret = efi_get_dfu_info(image_info_size, image_info, + descriptor_version, descriptor_count, + descriptor_size, + package_version, package_version_name, + &efi_firmware_image_type_uboot_fit); + + return EFI_EXIT(ret); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_get_image_unsupported( + struct efi_firmware_management_protocol *this, + u8 image_index, + void *image, + efi_uintn_t *image_size) +{ + EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +/** + * efi_firmware_fit_set_image - update the firmware image + * @this: Protocol instance + * @image_index: Image index number + * @image: New image + * @image_size: Size of new image + * @vendor_code: Vendor-specific update policy + * @progress: Function to report the progress of update + * @abort_reason: Pointer to string of abort reason + * + * Update the firmware to new image, using dfu. The new image should + * have FIT image format commonly used in U-Boot. + * @vendor_code, @progress and @abort_reason are not supported. + * + * Return: status code + */ +static +efi_status_t EFIAPI efi_firmware_fit_set_image( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t image_size, + const void *vendor_code, + efi_status_t (*progress)(efi_uintn_t completion), + u16 **abort_reason) +{ + EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image, + image_size, vendor_code, progress, abort_reason); + + if (!image || image_index != 1) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (fit_update(image)) + return EFI_EXIT(EFI_DEVICE_ERROR); + + return EFI_EXIT(EFI_SUCCESS); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_check_image_unsupported( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t *image_size, + u32 *image_updatable) +{ + EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size, + image_updatable); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_get_package_info_unsupported( + struct efi_firmware_management_protocol *this, + u32 *package_version, + u16 **package_version_name, + u32 *package_version_name_maxlen, + u64 *attributes_supported, + u64 *attributes_setting) +{ + EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version, + package_version_name, package_version_name_maxlen, + attributes_supported, attributes_setting); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_set_package_info_unsupported( + struct efi_firmware_management_protocol *this, + const void *image, + efi_uintn_t *image_size, + const void *vendor_code, + u32 package_version, + const u16 *package_version_name) +{ + EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code, + package_version, package_version_name); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +const struct efi_firmware_management_protocol efi_fmp_fit = { + .get_image_info = efi_firmware_fit_get_image_info, + .get_image = efi_firmware_get_image_unsupported, + .set_image = efi_firmware_fit_set_image, + .check_image = efi_firmware_check_image_unsupported, + .get_package_info = efi_firmware_get_package_info_unsupported, + .set_package_info = efi_firmware_set_package_info_unsupported, +}; From patchwork Tue Nov 17 00:28:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324540 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4492200ejb; Mon, 16 Nov 2020 16:30:19 -0800 (PST) X-Google-Smtp-Source: ABdhPJwYJxf3N4S22sozkw7sJnTUTxJxldsuIKNFUBiQIrhEzOLSZntuZNEzbEGFFyrC8H6i3cpZ X-Received: by 2002:a05:6402:2da:: with SMTP id b26mr17868410edx.176.1605573019048; Mon, 16 Nov 2020 16:30:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573019; cv=none; d=google.com; s=arc-20160816; b=ElAgQT5nu62Y4fg+TeZkkzwYZ1JQpaVKIkp3GKIPWtXQa9Pf1ZiHikmQ/jGYXhLqb7 G1mZ1fkk4hE3Vyr51/oCHuI/g7E9mr8chIZNx19ebSrGeM5cYTpgag5ZOZC0wK0yL/A7 EGBcSn/1STbMtjTtxz5vJuJot8nByi9L9egCvNlM5W90D5z3RL2Gle7TiDDnIXUb4FFF gf5hyqgmDfr8AtnGmvrykAENY/L9zsAYo+FGxWKo4ZN61TVYzWi2SxC6/UnlxBvbwQ2P UvxaAjO1JkotTwFCQqJwPDu8vl8uaTriQ69gFPQ3CBkyu1sJoskdQQIphk4D7m51GElk 3R8g== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=3dtdYttzmeGN2H9/XHJjDOYppWV1djfzkAM7+42HV9Q=; b=C1mKI8qU0QU11ZHM7hGYBAGB1kJDBLSPqewiHFliG0ayqxFdyEN4pcYKilUooOm8vD s7VkCRgQmAEfPJo84CR+P/EismSN8nVLhRINYURktwe+HgZ0Z2G1S1DReN8ZE4OhSBit wUM6Lcg/0xTYTVuzMF8QprX6XCwN8qOz/1LOqvG/ffaqfdLixlmhSryWRsA9qyLHu2DM kOkv5nPdmgb4FEwiKdAttiCxaHEX37smmqB6mIlN4YxSs8jToadfw0Kv+Xf1XwO2qO6Y H24OIjM+JwRb6/ICjt7xs3g28+P/5Y99tAH27yc013Z/V75lz5sZJAiYIR4q8zy9C+cj HBsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="EQay//qY"; 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 r1si12842772ejz.334.2020.11.16.16.30.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:30:19 -0800 (PST) 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="EQay//qY"; 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 C2F09825B4; Tue, 17 Nov 2020 01:29:37 +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="EQay//qY"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 61DE482580; Tue, 17 Nov 2020 01:29:23 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,T_SPF_HELO_TEMPERROR autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x543.google.com (mail-pg1-x543.google.com [IPv6:2607:f8b0:4864:20::543]) (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 C6B3E82563 for ; Tue, 17 Nov 2020 01:29:02 +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=takahiro.akashi@linaro.org Received: by mail-pg1-x543.google.com with SMTP id 34so11461829pgp.10 for ; Mon, 16 Nov 2020 16:29:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3dtdYttzmeGN2H9/XHJjDOYppWV1djfzkAM7+42HV9Q=; b=EQay//qYIMEEn5utXWAkuVM5YwSEE9h3nqevnU7fhiCJQa60uHetXcHw1M97UTEuMh iScTpPBuWbJi70tswRo3uVxZbS58vv/Sp+UwOdwQejwVIzq18nP/KAVjS6UCOCnuSiqh ydgJmZPmFkkKhYkUUY0cg8ij+cLgfXjm1AigF+hm13ZRPE7GpZqRqGmWwtsJXHQN/Jhg 0WbqtskFRDt+dOTw673GyNRX3BtoIqS07SwmzrU6p4fZy/rKvGG5tirN8+Az7YGWf1zS g8icQXZdgNLofEhQG5KClBr/KU4E5n37frfizfzCmd4YoPwfBolvyjfm/z6gaOqszA+Z W3TQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3dtdYttzmeGN2H9/XHJjDOYppWV1djfzkAM7+42HV9Q=; b=GEreOuZ47h1OndE+tJCoz8uiHH7yi88aTtjnWV8vDuaU+sy97Ds6OTNQYUoz8AqApz Fp8ydHzTrunIn3umraYKaM51iY6TO2rBBE05b1skDjomuZ5EBwGEKE1YQCHyxkmQnoH0 IweXSO4MH7/Won59QybIBDtxuIXdHnfymet11fJVMzzvxbaJQuhTcxcgWUV52V+b1fDD CVzIYEFswjp7AiR+2+JRGkdZ3Wjq2HbieVgFA7SSbwJ59B2zCpLg4s8u5H0EeDeQDxgR Qgbl25yVm+N59RCqdHypcvKTAyH1yVtyzhGzWlPy1lKSDbAQGnyVuCc0FN/0/Wcj6y3i sNMg== X-Gm-Message-State: AOAM532wQQNeoVipbKcQpeaYmfUx1nH/lGlrAKRObl0qAe59WjSGN6dz LSKWsG72DxbgLlbndt4SVtnnSg== X-Received: by 2002:a17:90b:1881:: with SMTP id mn1mr1026831pjb.113.1605572941202; Mon, 16 Nov 2020 16:29:01 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.28.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:00 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 06/11] efi_loader: add firmware management protocol for raw image Date: Tue, 17 Nov 2020 09:28:00 +0900 Message-Id: <20201117002805.13902-7-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean In this commit, a very simple firmware management protocol driver is implemented. It will take a binary image in a capsule file and apply the data using dfu backend storage drivers via dfu_write_by_alt() interface. So "dfu_alt_info" variable should be properly set to specify a device and location to be updated. Please read README.dfu. Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 4 + include/efi_loader.h | 1 + lib/efi_loader/Kconfig | 16 +++ lib/efi_loader/Makefile | 2 +- lib/efi_loader/efi_capsule.c | 8 ++ lib/efi_loader/efi_firmware.c | 226 +++++++++++++++++++++++++--------- 6 files changed, 199 insertions(+), 58 deletions(-) -- 2.28.0 diff --git a/include/efi_api.h b/include/efi_api.h index 071d0ba866c7..c7038f863ab2 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1853,6 +1853,10 @@ struct efi_signature_list { EFI_GUID(0xae13ff2d, 0x9ad4, 0x4e25, 0x9a, 0xc8, \ 0x6d, 0x80, 0xb3, 0xb2, 0x21, 0x47) +#define EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID \ + EFI_GUID(0xe2bb9c06, 0x70e9, 0x4b14, 0x97, 0xa3, \ + 0x5a, 0x79, 0x13, 0x17, 0x6e, 0x3f) + #define IMAGE_ATTRIBUTE_IMAGE_UPDATABLE 0x0000000000000001 #define IMAGE_ATTRIBUTE_RESET_REQUIRED 0x0000000000000002 #define IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED 0x0000000000000004 diff --git a/include/efi_loader.h b/include/efi_loader.h index d24d0ff0e78a..1b19faf76941 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -812,6 +812,7 @@ void efi_memcpy_runtime(void *dest, const void *src, size_t n); u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index); extern const struct efi_firmware_management_protocol efi_fmp_fit; +extern const struct efi_firmware_management_protocol efi_fmp_raw; /* Capsule update */ efi_status_t EFIAPI efi_update_capsule( diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 159400fec39e..8332a5072d42 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -126,6 +126,10 @@ config EFI_CAPSULE_ON_DISK_EARLY executed as part of U-Boot initialisation so that they will surely take place whatever is set to distro_bootcmd. +config EFI_CAPSULE_FIRMWARE + bool + default n + config EFI_CAPSULE_FIRMWARE_MANAGEMENT bool "Capsule: Firmware Management Protocol" depends on EFI_HAVE_CAPSULE_SUPPORT @@ -140,11 +144,23 @@ config EFI_CAPSULE_FIRMWARE_FIT depends on FIT select UPDATE_FIT select DFU + select EFI_CAPSULE_FIRMWARE default n help Select this option if you want to enable firmware management protocol driver for FIT image +config EFI_CAPSULE_FIRMWARE_RAW + bool "FMP driver for raw image" + depends on EFI_CAPSULE_FIRMWARE_MANAGEMENT + select DFU + select DFU_WRITE_ALT + select EFI_CAPSULE_FIRMWARE + default n + help + Select this option if you want to enable firmware management protocol + driver for raw image + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index dedb702c5d43..9a3496350ea4 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-y += efi_bootmgr.o obj-y += efi_boottime.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o -obj-$(CONFIG_EFI_CAPSULE_FIRMWARE_FIT) += efi_firmware.o +obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o obj-y += efi_console.o obj-y += efi_device_path.o obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 8265aac226f2..f385e5837805 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -814,6 +814,14 @@ efi_status_t __weak arch_efi_load_capsule_drivers(void) &efi_fmp_fit, NULL)); } + if (IS_ENABLED(CONFIG_EFI_CAPSULE_FIRMWARE_RAW)) { + handle = NULL; + ret = EFI_CALL(efi_install_multiple_protocol_interfaces( + &efi_root, + &efi_guid_firmware_management_protocol, + &efi_fmp_raw, NULL)); + } + return ret; } diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 4c395f4eb5d9..7e5607738319 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -13,16 +13,66 @@ #include #include -/* - * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update - * method with existing FIT image format, and handles - * - multiple regions of firmware via DFU - * but doesn't support - * - versioning of firmware image - * - package information - */ -const efi_guid_t efi_firmware_image_type_uboot_fit = - EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_get_image_unsupported( + struct efi_firmware_management_protocol *this, + u8 image_index, + void *image, + efi_uintn_t *image_size) +{ + EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_check_image_unsupported( + struct efi_firmware_management_protocol *this, + u8 image_index, + const void *image, + efi_uintn_t *image_size, + u32 *image_updatable) +{ + EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size, + image_updatable); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_get_package_info_unsupported( + struct efi_firmware_management_protocol *this, + u32 *package_version, + u16 **package_version_name, + u32 *package_version_name_maxlen, + u64 *attributes_supported, + u64 *attributes_setting) +{ + EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version, + package_version_name, package_version_name_maxlen, + attributes_supported, attributes_setting); + + return EFI_EXIT(EFI_UNSUPPORTED); +} + +/* Place holder; not supported */ +static +efi_status_t EFIAPI efi_firmware_set_package_info_unsupported( + struct efi_firmware_management_protocol *this, + const void *image, + efi_uintn_t *image_size, + const void *vendor_code, + u32 package_version, + const u16 *package_version_name) +{ + EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code, + package_version, package_version_name); + + return EFI_EXIT(EFI_UNSUPPORTED); +} /** * efi_get_dfu_info - return information about the current firmware image @@ -129,6 +179,18 @@ static efi_status_t efi_get_dfu_info( return EFI_SUCCESS; } +#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT +/* + * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update + * method with existing FIT image format, and handles + * - multiple regions of firmware via DFU + * but doesn't support + * - versioning of firmware image + * - package information + */ +const efi_guid_t efi_firmware_image_type_uboot_fit = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; + /** * efi_firmware_fit_get_image_info - return information about the current * firmware image @@ -182,19 +244,6 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info( return EFI_EXIT(ret); } -/* Place holder; not supported */ -static -efi_status_t EFIAPI efi_firmware_get_image_unsupported( - struct efi_firmware_management_protocol *this, - u8 image_index, - void *image, - efi_uintn_t *image_size) -{ - EFI_ENTRY("%p %d %p %p\n", this, image_index, image, image_size); - - return EFI_EXIT(EFI_UNSUPPORTED); -} - /** * efi_firmware_fit_set_image - update the firmware image * @this: Protocol instance @@ -233,59 +282,122 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( return EFI_EXIT(EFI_SUCCESS); } -/* Place holder; not supported */ -static -efi_status_t EFIAPI efi_firmware_check_image_unsupported( - struct efi_firmware_management_protocol *this, - u8 image_index, - const void *image, - efi_uintn_t *image_size, - u32 *image_updatable) -{ - EFI_ENTRY("%p %d %p %p %p\n", this, image_index, image, image_size, - image_updatable); +const struct efi_firmware_management_protocol efi_fmp_fit = { + .get_image_info = efi_firmware_fit_get_image_info, + .get_image = efi_firmware_get_image_unsupported, + .set_image = efi_firmware_fit_set_image, + .check_image = efi_firmware_check_image_unsupported, + .get_package_info = efi_firmware_get_package_info_unsupported, + .set_package_info = efi_firmware_set_package_info_unsupported, +}; +#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_FIT */ - return EFI_EXIT(EFI_UNSUPPORTED); -} +#ifdef CONFIG_EFI_CAPSULE_FIRMWARE_RAW +/* + * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update + * method with raw data. + */ +const efi_guid_t efi_firmware_image_type_uboot_raw = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID; -/* Place holder; not supported */ +/** + * efi_firmware_raw_get_image_info - return information about the current + firmware image + * @this: Protocol instance + * @image_info_size: Size of @image_info + * @image_info: Image information + * @descriptor_version: Pointer to version number + * @descriptor_count: Pointer to number of descriptors + * @descriptor_size: Pointer to descriptor size + * package_version: Package version + * package_version_name: Package version's name + * + * Return information bout the current firmware image in @image_info. + * @image_info will consist of a number of descriptors. + * Each descriptor will be created based on "dfu_alt_info" variable. + * + * Return status code + */ static -efi_status_t EFIAPI efi_firmware_get_package_info_unsupported( +efi_status_t EFIAPI efi_firmware_raw_get_image_info( struct efi_firmware_management_protocol *this, + efi_uintn_t *image_info_size, + struct efi_firmware_image_descriptor *image_info, + u32 *descriptor_version, + u8 *descriptor_count, + efi_uintn_t *descriptor_size, u32 *package_version, - u16 **package_version_name, - u32 *package_version_name_maxlen, - u64 *attributes_supported, - u64 *attributes_setting) + u16 **package_version_name) { - EFI_ENTRY("%p %p %p %p %p %p\n", this, package_version, - package_version_name, package_version_name_maxlen, - attributes_supported, attributes_setting); + efi_status_t ret = EFI_SUCCESS; - return EFI_EXIT(EFI_UNSUPPORTED); + EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this, + image_info_size, image_info, + descriptor_version, descriptor_count, descriptor_size, + package_version, package_version_name); + + if (!image_info_size) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (*image_info_size && + (!image_info || !descriptor_version || !descriptor_count || + !descriptor_size || !package_version || !package_version_name)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + ret = efi_get_dfu_info(image_info_size, image_info, + descriptor_version, descriptor_count, + descriptor_size, + package_version, package_version_name, + &efi_firmware_image_type_uboot_raw); + + return EFI_EXIT(ret); } -/* Place holder; not supported */ +/** + * efi_firmware_raw_set_image - update the firmware image + * @this: Protocol instance + * @image_index: Image index number + * @image: New image + * @image_size: Size of new image + * @vendor_code: Vendor-specific update policy + * @progress: Function to report the progress of update + * @abort_reason: Pointer to string of abort reason + * + * Update the firmware to new image, using dfu. The new image should + * be a single raw image. + * @vendor_code, @progress and @abort_reason are not supported. + * + * Return: status code + */ static -efi_status_t EFIAPI efi_firmware_set_package_info_unsupported( +efi_status_t EFIAPI efi_firmware_raw_set_image( struct efi_firmware_management_protocol *this, + u8 image_index, const void *image, - efi_uintn_t *image_size, + efi_uintn_t image_size, const void *vendor_code, - u32 package_version, - const u16 *package_version_name) + efi_status_t (*progress)(efi_uintn_t completion), + u16 **abort_reason) { - EFI_ENTRY("%p %p %p %p %x %p\n", this, image, image_size, vendor_code, - package_version, package_version_name); + EFI_ENTRY("%p %d %p %ld %p %p %p\n", this, image_index, image, + image_size, vendor_code, progress, abort_reason); - return EFI_EXIT(EFI_UNSUPPORTED); + if (!image) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + if (dfu_write_by_alt(image_index - 1, (void *)image, image_size, + NULL, NULL)) + return EFI_EXIT(EFI_DEVICE_ERROR); + + return EFI_EXIT(EFI_SUCCESS); } -const struct efi_firmware_management_protocol efi_fmp_fit = { - .get_image_info = efi_firmware_fit_get_image_info, +const struct efi_firmware_management_protocol efi_fmp_raw = { + .get_image_info = efi_firmware_raw_get_image_info, .get_image = efi_firmware_get_image_unsupported, - .set_image = efi_firmware_fit_set_image, + .set_image = efi_firmware_raw_set_image, .check_image = efi_firmware_check_image_unsupported, .get_package_info = efi_firmware_get_package_info_unsupported, .set_package_info = efi_firmware_set_package_info_unsupported, }; +#endif /* CONFIG_EFI_CAPSULE_FIRMWARE_RAW */ From patchwork Tue Nov 17 00:28:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324542 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4492638ejb; Mon, 16 Nov 2020 16:30:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJzGtAAYlz96zlvslX+V6IVGd0OflYltVG3FuPoo86ypYFiNx18mFizakBmxBjUzTwb4CAhk X-Received: by 2002:a17:906:a891:: with SMTP id ha17mr17054066ejb.116.1605573059848; Mon, 16 Nov 2020 16:30:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573059; cv=none; d=google.com; s=arc-20160816; b=Zn8qDuZ/WrNyQbLs/OpXzgbBky6DhFs0otRKolznWdxrH3mqNQdXzKNpL9oj6eoLkM K2UEykH+7iBInu6EJ004dWc9iTsRwysqU3MYTa/7UGoYs+rmhe4wceAUH6gD03glTRX7 bPNoiiY1gR5k/ZRoIFdpP4vR3HyhdS1RjpusSWb4pmVsyE2dWek4IqHY4hLXLYGXETK4 Gq2aiu+6Mi+7dBAQ8plpbhKTmZcUUA2eGbLg6qIJysvfdvh341ba6G8Lv3YY4KKSFX1F 0cRm3t/ffMB+0ZQi6fygdu+8wJDBRqzFF7KEfGRQo24GL/Mx50dPLrHpw90HDjmPo4wy AqZQ== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=yqrxDc6ObQsRN+ZFvwOxoruSMgmdQxuJIuaGjJP56Ic=; b=tjWVxq3DOVqnT4JKq/6o1Lv1QwG9MY3BqMKkjsNEjYqr2x4JIiC62qbstqdIvATogn 3ssFUp21OJAand1sKyId04e9xpwv4h2+mIK0aFQPv01ZBpm7LDj7NGKM0N6/en9XUTpY j9XLLjI2TYskRod62u6NJN6qxbzxFdpNB9JbVUhZgqt9h1OMfl7B6QJso8kNgEYDN68P 3HAKIo9h36miWGG1iWvMh0URuwM5KkrPU7CRnvMTia/letatQoeVisdKDDqFzzCYYcGK Ti5NOVey3r4Yfv0AyVVeoKpZf6Cjmt+xzpQ7IVoDBIp7Fti3wPbmN4SMQiHY9PuDbn3f 7WeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dnLHFaSd; 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=pass (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 c1si5940023edx.275.2020.11.16.16.30.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:30:59 -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; dkim=pass header.i=@linaro.org header.s=google header.b=dnLHFaSd; 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=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 EE86C8257F; Tue, 17 Nov 2020 01:29:59 +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="dnLHFaSd"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7667382573; Tue, 17 Nov 2020 01:29:23 +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.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,T_SPF_HELO_TEMPERROR autolearn=no autolearn_force=no version=3.4.2 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) (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 31DDE82571 for ; Tue, 17 Nov 2020 01:29: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=takahiro.akashi@linaro.org Received: by mail-pg1-x532.google.com with SMTP id 81so6341909pgf.0 for ; Mon, 16 Nov 2020 16:29:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=yqrxDc6ObQsRN+ZFvwOxoruSMgmdQxuJIuaGjJP56Ic=; b=dnLHFaSd4JKcecNigV1Q4ZDIZFTKRxZpzrccbfOv3F1EAjoRFSNU5Om4RxdluG6xqC YIkqZ97SVnZ0D10Dp2fT69Wml8lnkhFvu5J1Jx3GlcBzHKSbKvDET7JHnqWcQA6BuDJr IC8rS8qRKcr6O4frgGHpFlYMd5BKu/C/J8K25jZIFBuTLiSylFbWF/20P/ECVltnJScl Us6zXD1Lh/czY7IOoqSiSPeTE9Bue68r3LCIyTI2pt2k6iil25rlzi1FuDTye6V8rFg5 snUtsKBxL8HCU7k+bYrOT09pWle1yV1JqfzxqkAVhl7RkVso/CRAj+nCwirVel7j5f1l ETBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=yqrxDc6ObQsRN+ZFvwOxoruSMgmdQxuJIuaGjJP56Ic=; b=IPe9hHDlxDrKyLheaFo21ORJSCtrNkghQSnukjXGrhY5WUCfRTBX96ZWdwSw4wGp6e 3RgjrlBHPfolZ9OPO97d4nQj0CxqYOof0B5ke3D6n2TWZwulP/jDZrj8iGJnBpPZugpO dkjHUimdALczE2LtlkNhjUWXhquvVfwmd2CWcnNInOyorSQgakvfVoCV9zNWvZzrLsHH iyas8JFO2jEUcb9+Gx/A2dfbHlm+/CbtU/AzomoJFSpB4udiK+QnWyJfAvcNm6lD5DVo A/IdWSpUSVcwvq90m53WACLpA2Q/Sg7HwDP93Wp3FSJCUk95IuQtDNEHRuihKQ+n+0Qa K4+Q== X-Gm-Message-State: AOAM5302LH6tWaTKGE2BmFeiLoU8MXaWEM7VJKyISFuz529Yr9VsWXYT Rkx9nkApjMafWH0tUFBmXPTGbg== X-Received: by 2002:a63:1d12:: with SMTP id d18mr1446335pgd.314.1605572943703; Mon, 16 Nov 2020 16:29:03 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.29.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:03 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 07/11] cmd: add "efidebug capsule" command Date: Tue, 17 Nov 2020 09:28:01 +0900 Message-Id: <20201117002805.13902-8-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean "efidebug capsule" is more or less a debugging utility. efidebug capsule update: invoke UpdateCapsule against data on memory efidebug capsule show: show a capsule header efidebug capsule result: dump a capsule result variable Signed-off-by: AKASHI Takahiro --- cmd/efidebug.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) -- 2.28.0 diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 5288b9920b4d..7d327c82681f 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -19,6 +19,228 @@ #include #define BS systab.boottime +#define RT systab.runtime + +#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT +/** + * do_efi_capsule_update() - process a capsule update + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule update" sub-command. + * process a capsule update. + * + * efidebug capsule update [-v] + */ +static int do_efi_capsule_update(struct cmd_tbl *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct efi_capsule_header *capsule; + int verbose = 0; + char *endp; + efi_status_t ret; + + if (argc != 2 && argc != 3) + return CMD_RET_USAGE; + + if (argc == 3) { + if (strcmp(argv[1], "-v")) + return CMD_RET_USAGE; + + verbose = 1; + argc--; + argv++; + } + + capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16); + if (endp == argv[1]) { + printf("Invalid address: %s", argv[1]); + return CMD_RET_FAILURE; + } + + if (verbose) { + printf("Capsule guid: %pUl\n", &capsule->capsule_guid); + printf("Capsule flags: 0x%x\n", capsule->flags); + printf("Capsule header size: 0x%x\n", capsule->header_size); + printf("Capsule image size: 0x%x\n", + capsule->capsule_image_size); + } + + ret = EFI_CALL(RT->update_capsule(&capsule, 1, (u64)NULL)); + if (ret) { + printf("Cannot handle a capsule at %p", capsule); + return CMD_RET_FAILURE; + } + + return CMD_RET_SUCCESS; +} + +/** + * do_efi_capsule_show() - show capsule information + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule show" sub-command. + * show capsule information. + * + * efidebug capsule show + */ +static int do_efi_capsule_show(struct cmd_tbl *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct efi_capsule_header *capsule; + char *endp; + + if (argc != 2) + return CMD_RET_USAGE; + + capsule = (typeof(capsule))simple_strtoul(argv[1], &endp, 16); + if (endp == argv[1]) { + printf("Invalid address: %s", argv[1]); + return CMD_RET_FAILURE; + } + + printf("Capsule guid: %pUl\n", &capsule->capsule_guid); + printf("Capsule flags: 0x%x\n", capsule->flags); + printf("Capsule header size: 0x%x\n", capsule->header_size); + printf("Capsule image size: 0x%x\n", + capsule->capsule_image_size); + + return CMD_RET_SUCCESS; +} + +/** + * do_efi_capsule_res() - show a capsule update result + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule result" sub-command. + * show a capsule update result. + * If result number is not specified, CapsuleLast will be shown. + * + * efidebug capsule result [] + */ +static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag, + int argc, char * const argv[]) +{ + int capsule_id; + char *endp; + char var_name[12]; + u16 var_name16[12], *p; + efi_guid_t guid; + struct efi_capsule_result_variable_header *result = NULL; + efi_uintn_t size; + efi_status_t ret; + + if (argc != 1 && argc != 2) + return CMD_RET_USAGE; + + guid = efi_guid_capsule_report; + if (argc == 1) { + size = sizeof(var_name16); + ret = EFI_CALL(RT->get_variable(L"CapsuleLast", &guid, NULL, + &size, var_name16)); + if (ret != EFI_SUCCESS) { + if (ret == EFI_NOT_FOUND) + printf("CapsuleLast doesn't exist\n"); + else + printf("Failed to get CapsuleLast\n"); + + return CMD_RET_FAILURE; + } + printf("CapsuleLast is %ls\n", var_name16); + } else { + argc--; + argv++; + + capsule_id = simple_strtoul(argv[0], &endp, 16); + if (capsule_id < 0 || capsule_id > 0xffff) + return CMD_RET_USAGE; + + sprintf(var_name, "Capsule%04X", capsule_id); + p = var_name16; + utf8_utf16_strncpy(&p, var_name, 9); + } + + size = 0; + ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL) { + result = malloc(size); + ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, + result)); + if (ret != EFI_SUCCESS) { + free(result); + printf("Failed to get %ls\n", var_name16); + + return CMD_RET_FAILURE; + } + } + + printf("Result total size: 0x%x\n", result->variable_total_size); + printf("Capsule guid: %pUl\n", &result->capsule_guid); + printf("Time processed: %04d-%02d-%02d %02d:%02d:%02d\n", + result->capsule_processed.year, result->capsule_processed.month, + result->capsule_processed.day, result->capsule_processed.hour, + result->capsule_processed.minute, + result->capsule_processed.second); + printf("Capsule status: 0x%lx\n", result->capsule_status); + + free(result); + + return CMD_RET_SUCCESS; +} + +static struct cmd_tbl cmd_efidebug_capsule_sub[] = { + U_BOOT_CMD_MKENT(update, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_update, + "", ""), + U_BOOT_CMD_MKENT(show, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_show, + "", ""), + U_BOOT_CMD_MKENT(result, CONFIG_SYS_MAXARGS, 1, do_efi_capsule_res, + "", ""), +}; + +/** + * do_efi_capsule() - manage UEFI capsules + * + * @cmdtp: Command table + * @flag: Command flag + * @argc: Number of arguments + * @argv: Argument array + * Return: CMD_RET_SUCCESS on success, + * CMD_RET_USAGE or CMD_RET_RET_FAILURE on failure + * + * Implement efidebug "capsule" sub-command. + */ +static int do_efi_capsule(struct cmd_tbl *cmdtp, int flag, + int argc, char * const argv[]) +{ + struct cmd_tbl *cp; + + if (argc < 2) + return CMD_RET_USAGE; + + argc--; argv++; + + cp = find_cmd_tbl(argv[0], cmd_efidebug_capsule_sub, + ARRAY_SIZE(cmd_efidebug_capsule_sub)); + if (!cp) + return CMD_RET_USAGE; + + return cp->cmd(cmdtp, flag, argc, argv); +} +#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT */ /** * efi_get_device_handle_info() - get information of UEFI device @@ -1237,6 +1459,10 @@ static int do_efi_query_info(struct cmd_tbl *cmdtp, int flag, static struct cmd_tbl cmd_efidebug_sub[] = { U_BOOT_CMD_MKENT(boot, CONFIG_SYS_MAXARGS, 1, do_efi_boot_opt, "", ""), +#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT + U_BOOT_CMD_MKENT(capsule, CONFIG_SYS_MAXARGS, 1, do_efi_capsule, + "", ""), +#endif U_BOOT_CMD_MKENT(devices, CONFIG_SYS_MAXARGS, 1, do_efi_show_devices, "", ""), U_BOOT_CMD_MKENT(drivers, CONFIG_SYS_MAXARGS, 1, do_efi_show_drivers, @@ -1311,6 +1537,15 @@ static char efidebug_help_text[] = "efidebug boot order [ [ [ [...]]]]\n" " - set/show UEFI boot order\n" "\n" +#ifdef CONFIG_EFI_HAVE_CAPSULE_SUPPORT + "efidebug capsule update [-v] \n" + " - process a capsule\n" + "efidebug capsule show \n" + " - show capsule information\n" + "efidebug capsule result []\n" + " - show a capsule update result\n" + "\n" +#endif "efidebug devices\n" " - show UEFI devices\n" "efidebug drivers\n" From patchwork Tue Nov 17 00:28:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324544 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4493046ejb; Mon, 16 Nov 2020 16:31:40 -0800 (PST) X-Google-Smtp-Source: ABdhPJz1ZpTdhzetmyq1bX/m1GVJJi8wZSFLGfBhR8GXxBuiMczrungKJWtYPMJ/tPOZvEaW8NWa X-Received: by 2002:aa7:d404:: with SMTP id z4mr18584632edq.334.1605573100334; Mon, 16 Nov 2020 16:31:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573100; cv=none; d=google.com; s=arc-20160816; b=ZbUcPayF7M1oBym6ZuVmBe2rSzvE1jdRc5NnUlTMLtFfMiLhMctPLW3Oyzh1BTjrcn 7RSwvjzVEUo860b9lWv1td7/TmKwtBnqB6cAzVO0WWhaz92rpZXEiZDC38KA5CrnCoXI Tjxfivf2/o2E8nfL9k1xzx2aRXhLZf3hNg39ycC6ABShcRzSZnWEYCbal2dL0DW29rPK WCA5QAntlrXKR1l7TcocByxtZT2uy7IQ0hRoClLSdj/phHX8bxnYGagCHxLbrOEUALVT 4gE6GIcnctfegZ4HT0cLU9gJth4drA7dG1hCqZj3OgEUf6g2pGMf7NoIvVOBj1CMRUe7 oZ0w== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Z+/O5+FTtGlaZoI0+NvnfBAMCvpzihjClRuaSmYgNho=; b=ZGBqzPjKlm6Va7D091UYHjHwkAiAtD5nR94lvkpaBrI3JyUN/0weHnLjAN065z0Kae aoCz6ilaie/WZf+pfUiGW8AJ+fUFvG5T3yFl6A7SFAjjIio+Tf/7GfcWS0EN6kHc3wtb eFkvU07YX7Ur0O5GSn9wxNzsYkVJOYynKhiIYuUkdNLw4wHG6DUiDy45RFc9h0M4gpq3 4UvV7t13AkwpoYlhKswz77JEnmPgq3h8IpaF/Trh9rIQ+YecRYMpunT/gsSqTat5pQdZ WUSzgtMZq5OxsP6/TxCOfdIeLbMl3qC0ycZ9WWpIOm2xO+bY/be5SZoF/PZX4/21ivA5 wupw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=emr7skuD; 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=pass (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 s8si13492865edc.481.2020.11.16.16.31.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:31:40 -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; dkim=pass header.i=@linaro.org header.s=google header.b=emr7skuD; 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=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 6B8AA825BE; Tue, 17 Nov 2020 01:30:24 +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="emr7skuD"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A705C8258E; Tue, 17 Nov 2020 01:29:34 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) (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 9EE1C8257F for ; Tue, 17 Nov 2020 01:29:12 +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=takahiro.akashi@linaro.org Received: by mail-pl1-x635.google.com with SMTP id j5so9257361plk.7 for ; Mon, 16 Nov 2020 16:29:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Z+/O5+FTtGlaZoI0+NvnfBAMCvpzihjClRuaSmYgNho=; b=emr7skuDdFoFPUMsItfkYq4g01Wrplkun4qT5wow0/26ArTZIdjOT/cEHYBTXrvuRE MQ0ssKNZQxlYyMwjhkZgxsmTIY0cu+C7G/oeYnZRZFK30RoVibNEcfTXcF3gNVbCxFUB JEAku/IKL6Ulr9s3SBbt0qqgcAlNkt1WyjcWWd1HAiQ6Et8vDeKybvcK0/nGNZ+HU8US A01KXw4YLubNKjep31bjNMb6X9cVKXulH13Ekuv/nO6mP2GlQRUprHL5MKh6YRDMT/Wd ynICWZExjR7Yx95+1XxlKBVlAz5zHTzpPYlPqsgavaX/d3oBjTJS+0mBqBaLsL5fRoBv Ljqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Z+/O5+FTtGlaZoI0+NvnfBAMCvpzihjClRuaSmYgNho=; b=N9NZkMwMiJuNnBgqFn3q/zi9tRHF8Sf9l7NxBEiXq4iFf2Ce6y+2HwfubMo2Qpsx28 4O/bBPM3PdsXYBGxTImfnJRo+uO1RsEQLhN9PB3+n1XPc49P1weC2SjAPoMm77YxiIbL 8P6JgsGvrgOhpMHUH6fxZv5XbVG3gDPd+vl9U9JBZHZ6CKVrDoKZKBia2/oGudfGjVX5 //MltgDsq3Lo3+dnpyGlvzgaOExo4TUWJyyWgPVmWSssjEvkrK4wM/iznjnaxpIQN8fj FtaM7X2dQ2hYfw/BW4MVpuIvQ36n/5Uw9ESQpBG/B9vuhzt0RhmNhHbVF3YwPwaLJSIO 2SlQ== X-Gm-Message-State: AOAM530Z9RS/BuCVOFQSRLsjgwmkzSTpD1fxQZatVkSAnKIlkK/pgUdS nwc79iF1cSgtIS/s6Qf10RKLlgk/jqYnFw== X-Received: by 2002:a17:902:8f82:b029:d6:d7e4:6451 with SMTP id z2-20020a1709028f82b02900d6d7e46451mr15072267plo.55.1605572946121; Mon, 16 Nov 2020 16:29:06 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.29.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:05 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 08/11] tools: add mkeficapsule command for UEFI capsule update Date: Tue, 17 Nov 2020 09:28:02 +0900 Message-Id: <20201117002805.13902-9-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean This is a utility mainly for test purpose. mkeficapsule -f: create a test capsule file for FIT image firmware Having said that, you will be able to customize the code to fit your specific requirements for your platform. Signed-off-by: AKASHI Takahiro --- tools/Makefile | 2 + tools/mkeficapsule.c | 238 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 tools/mkeficapsule.c -- 2.28.0 diff --git a/tools/Makefile b/tools/Makefile index 51123fd92983..66d9376803e3 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -218,6 +218,8 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs hostprogs-$(CONFIG_ASN1_COMPILER) += asn1_compiler HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include +hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule + # We build some files with extra pedantic flags to try to minimize things # that won't build on some weird host compiler -- though there are lots of # exceptions for files that aren't complaint. diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c new file mode 100644 index 000000000000..db95426457cc --- /dev/null +++ b/tools/mkeficapsule.c @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef __u8 u8; +typedef __u16 u16; +typedef __u32 u32; +typedef __u64 u64; +typedef __s16 s16; +typedef __s32 s32; + +#define aligned_u64 __aligned_u64 + +#ifndef __packed +#define __packed __attribute__((packed)) +#endif + +#include +#include + +static const char *tool_name = "mkeficapsule"; + +efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; +efi_guid_t efi_guid_image_type_uboot_fit = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID; +efi_guid_t efi_guid_image_type_uboot_raw = + EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID; + +static struct option options[] = { + {"fit", required_argument, NULL, 'f'}, + {"raw", required_argument, NULL, 'r'}, + {"index", required_argument, NULL, 'i'}, + {"instance", required_argument, NULL, 'I'}, + {"version", required_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}, +}; + +static void print_usage(void) +{ + printf("Usage: %s [options] \n" + "Options:\n" + "\t--fit new FIT image file\n" + "\t--raw new raw image file\n" + "\t--index update image index\n" + "\t--instance update hardware instance\n" + "\t--version firmware version\n" + "\t--help print a help message\n", + tool_name); +} + +static int create_fwbin(char *path, char *bin, efi_guid_t *guid, + unsigned long version, unsigned long index, + unsigned long instance) +{ + struct efi_capsule_header header; + struct efi_firmware_management_capsule_header capsule; + struct efi_firmware_management_capsule_image_header image; + FILE *f, *g; + struct stat bin_stat; + u8 *data; + size_t size; + +#ifdef DEBUG + printf("For output: %s\n", path); + printf("\tbin: %s\n\ttype: %pUl\n" bin, guid); + printf("\tversion: %ld\n\tindex: %ld\n\tinstance: %ld\n", + version, index, instance); +#endif + + g = fopen(bin, "r"); + if (!g) { + printf("cannot open %s\n", bin); + return -1; + } + if (stat(bin, &bin_stat) < 0) { + printf("cannot determine the size of %s\n", bin); + goto err_1; + } + data = malloc(bin_stat.st_size); + if (!data) { + printf("cannot allocate memory: %lx\n", bin_stat.st_size); + goto err_1; + } + f = fopen(path, "w"); + if (!f) { + printf("cannot open %s\n", path); + goto err_2; + } + header.capsule_guid = efi_guid_fm_capsule; + header.header_size = sizeof(header); + header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */ + header.capsule_image_size = sizeof(header) + + sizeof(capsule) + sizeof(u64) + + sizeof(image) + + bin_stat.st_size; + + size = fwrite(&header, 1, sizeof(header), f); + if (size < sizeof(header)) { + printf("write failed (%lx)\n", size); + goto err_3; + } + + capsule.version = 0x00000001; + capsule.embedded_driver_count = 0; + capsule.payload_item_count = 1; + capsule.item_offset_list[0] = sizeof(capsule) + sizeof(u64); + size = fwrite(&capsule, 1, sizeof(capsule) + sizeof(u64), f); + if (size < (sizeof(capsule) + sizeof(u64))) { + printf("write failed (%lx)\n", size); + goto err_3; + } + + image.version = version; + memcpy(&image.update_image_type_id, guid, sizeof(*guid)); + image.update_image_index = index; + image.update_image_size = bin_stat.st_size; + image.update_vendor_code_size = 0; /* none */ + image.update_hardware_instance = instance; + image.image_capsule_support = 0; + + size = fwrite(&image, 1, sizeof(image), f); + if (size < sizeof(image)) { + printf("write failed (%lx)\n", size); + goto err_3; + } + size = fread(data, 1, bin_stat.st_size, g); + if (size < bin_stat.st_size) { + printf("read failed (%lx)\n", size); + goto err_3; + } + size = fwrite(data, 1, bin_stat.st_size, f); + if (size < bin_stat.st_size) { + printf("write failed (%lx)\n", size); + goto err_3; + } + + fclose(f); + fclose(g); + free(data); + + return 0; + +err_3: + fclose(f); +err_2: + free(data); +err_1: + fclose(g); + + return -1; +} + +/* + * Usage: + * $ mkeficapsule -f + */ +int main(int argc, char **argv) +{ + char *file; + efi_guid_t *guid; + unsigned long index, instance, version; + int c, idx; + + file = NULL; + guid = NULL; + index = 0; + instance = 0; + version = 0; + for (;;) { + c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx); + if (c == -1) + break; + + switch (c) { + case 'f': + if (file) { + printf("Image already specified\n"); + return -1; + } + file = optarg; + guid = &efi_guid_image_type_uboot_fit; + break; + case 'r': + if (file) { + printf("Image already specified\n"); + return -1; + } + file = optarg; + guid = &efi_guid_image_type_uboot_raw; + break; + case 'i': + index = strtoul(optarg, NULL, 0); + break; + case 'I': + instance = strtoul(optarg, NULL, 0); + break; + case 'v': + version = strtoul(optarg, NULL, 0); + break; + case 'h': + print_usage(); + return 0; + } + } + + /* need a output file */ + if (argc != optind + 1) { + print_usage(); + return -1; + } + + /* need a fit image file or raw image file */ + if (!file) { + print_usage(); + return -1; + } + + if (create_fwbin(argv[optind], file, guid, version, index, instance) + < 0) { + printf("Creating firmware capsule failed\n"); + return -1; + } + + return 0; +} From patchwork Tue Nov 17 00:28:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324545 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4493206ejb; Mon, 16 Nov 2020 16:32:00 -0800 (PST) X-Google-Smtp-Source: ABdhPJx8ahCBLiKx8yUSg+3SJF23dGV86kCltIh1mEUFf17XllxfGFFpdXW0YxE/b2ZhM8cb6RNF X-Received: by 2002:a17:906:1c84:: with SMTP id g4mr18062112ejh.155.1605573120186; Mon, 16 Nov 2020 16:32:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573120; cv=none; d=google.com; s=arc-20160816; b=cug2ovHPYAkVA0QiO/b0YND6qb9oVQNIJpcdDJDycbaL/iEbzx28H5ccu8TAHgRGnR fB4F7vokuxSqJdNxJS5XFHCm6A/llv/8F7VFazkDSlb21CDUnibKz5vTkhKUM6sw4aCx ZdD0KOwUHhrR+1r7jUrS2qKd2IxcbHt7iEbBb3/PwvXxYRLHGl2yDw1BXYfYKJbKUjt6 +17n77KfiaE/0zmpSD6v9n1BmXXXtYTsisC2PNMaTsQvxzItUmqja2CMFskQVpbtOZeQ wIT9CFDDSpGrC7O5JlYJj0R/+gq4JZ5HU93JH51OzEkSifr4Jn2hKtv4e8DqmAPMlSaC S44g== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=IOj4c1X+9memoc+2cEZx30TU3aSICxNNSOf9x+26d+0=; b=KyNh3cNQi9FqUNkZwW3VJMydb/9VOhlGE6NlxmlY8MK68tB6y3WkDUjraH/2c94Ksy 89AzrP997iUfxoq4QceeBbZZT0X+bRSSUmCuEEoO+nEn/E7sULV3H1B/f2AuSFmgZcRv HPLcP7AVjHM28C/wu7pmDCz200Cp8rIZrzk9Y62GfdDXHOH6vbLn8J9j6HV40lMNm3rO 2Uj7ngivOMYndRE6fRHpL6Fpt0VrDcJf9E1jWwIe1PrrKWgG1gwGyi4K2iOhFt3niQEk Y4bAhx47zCotkermfMV+sbn5FsDiuLkccaj9yQtwh/Uw1nzjyNQtymh30cur9tXvLM0X z7fQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=FBKg6pcK; 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=pass (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 a2si13938214edn.504.2020.11.16.16.31.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:32:00 -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; dkim=pass header.i=@linaro.org header.s=google header.b=FBKg6pcK; 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=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 AF0BA82573; Tue, 17 Nov 2020 01:30:37 +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="FBKg6pcK"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6CFDC825A3; Tue, 17 Nov 2020 01:29:38 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,T_SPF_HELO_TEMPERROR,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) (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 BA33C82590 for ; Tue, 17 Nov 2020 01:29:15 +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=takahiro.akashi@linaro.org Received: by mail-pg1-x52e.google.com with SMTP id w4so14698863pgg.13 for ; Mon, 16 Nov 2020 16:29:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IOj4c1X+9memoc+2cEZx30TU3aSICxNNSOf9x+26d+0=; b=FBKg6pcKkvj7DkvGmikREqu2IZS5MJgYxvlz42sDhEdXlo8KGY+orTdbX4xtAN6o8X we3jBsBESiD+tzgecJjzRtL4BFwAz4tASJeamMtrSz2tNCMAxbBi8ppdk4g2qR9EkrzU bG+pH4yGc+dcRl4iPMXA3dFojm1yei6dg+iidPov0n5Oty1sq5brRceL9NWTYHhsJOZ9 lFUb2K6r7RxbpegrBpcewIk+X/6dnYdJZw3fZ1bgd2gbm+sWTkvW2pNVVtVR3T7SI0fm w4CR+eNI4LVLJWter0DLAJxMcUsXaHtiLoZtRh6I9/rI4G0xtGezq5mp6Wk9OtLusnmK vbIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IOj4c1X+9memoc+2cEZx30TU3aSICxNNSOf9x+26d+0=; b=Z9lUzIPXCsAHnHofPFosSB2Jm6jUjRv5lzGjogibpIbZxuzKDP4UkUqxL57aodxnco DXMqOdCK2a/Zi5oCR4bgOhfUHAXZxfueGX/Sp+Bb+TKUB17DpTR4NC16kciPIv2v0Trq my2s/nKM47UzaQgkm/xE2VOqridhUXnySAE+eZJ4JxTrvbJCrh2tJqeBzSkSJ+bctL1o zOyqSJIF43RGGlpD3nIIvoDtVkT4KSAVp++/3ABNyEKezfHnrdDYxtjrpbNTl833lTAW zWrXt/pvxoDcuJJD8Hj5NnOJtkfuyjT+uBqxjExz1rbPMvjYPkDq4zxAVEgmAyFOB33U vYQA== X-Gm-Message-State: AOAM532nDJsFmOWS5G++gChT8Me9cYt8JHMYIv4XZyq/tKG268ahOKJ7 IVMPNWbKLwgOYm8//+vYYaJNVg== X-Received: by 2002:aa7:970a:0:b029:18b:5773:13e6 with SMTP id a10-20020aa7970a0000b029018b577313e6mr15960580pfg.34.1605572948982; Mon, 16 Nov 2020 16:29:08 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.29.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:08 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 09/11] test/py: efi_capsule: test for FIT image capsule Date: Tue, 17 Nov 2020 09:28:03 +0900 Message-Id: <20201117002805.13902-10-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean The test can run on sandbox build and it attempts to execute a firmware update via a capsule-on-disk, using a FIT image capsule, CONFIG_EFI_CAPSULE_FIT. To run this test successfully, you need configure U-Boot specifically; See test_capsule_firmware.py for requirements, and hence it won't run on Travis CI, at least, for now. Signed-off-by: AKASHI Takahiro --- .../py/tests/test_efi_capsule/capsule_defs.py | 5 + test/py/tests/test_efi_capsule/conftest.py | 71 +++++++ .../test_efi_capsule/test_capsule_firmware.py | 178 ++++++++++++++++++ .../tests/test_efi_capsule/uboot_bin_env.its | 36 ++++ tools/mkeficapsule.c | 3 +- 5 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 test/py/tests/test_efi_capsule/capsule_defs.py create mode 100644 test/py/tests/test_efi_capsule/conftest.py create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware.py create mode 100644 test/py/tests/test_efi_capsule/uboot_bin_env.its -- 2.28.0 diff --git a/test/py/tests/test_efi_capsule/capsule_defs.py b/test/py/tests/test_efi_capsule/capsule_defs.py new file mode 100644 index 000000000000..4fd6353c2040 --- /dev/null +++ b/test/py/tests/test_efi_capsule/capsule_defs.py @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ + +# Directories +CAPSULE_DATA_DIR = '/EFI/CapsuleTestData' +CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule' diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py new file mode 100644 index 000000000000..147266189912 --- /dev/null +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Linaro Limited +# Author: AKASHI Takahiro + +import os +import os.path +import re +from subprocess import call, check_call, check_output, CalledProcessError +import pytest +from capsule_defs import * + +# +# Fixture for UEFI secure boot test +# + + +@pytest.fixture(scope='session') +def efi_capsule_data(request, u_boot_config): + """Set up a file system to be used in UEFI capsule test. + + Args: + request: Pytest request object. + u_boot_config: U-boot configuration. + + Return: + A path to disk image to be used for testing + """ + global CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR + + mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule' + data_dir = mnt_point + CAPSULE_DATA_DIR + install_dir = mnt_point + CAPSULE_INSTALL_DIR + image_path = u_boot_config.persistent_data_dir + '/test_efi_capsule.img' + + try: + # Create a target device + check_call('dd if=/dev/zero of=./spi.bin bs=1MiB count=16', shell=True) + + check_call('rm -rf %s' % mnt_point, shell=True) + check_call('mkdir -p %s' % data_dir, shell=True) + check_call('mkdir -p %s' % install_dir, shell=True) + + # Create capsule files + # two regions: one for u-boot.bin and the other for u-boot.env + check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old -> u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir, + shell=True) + check_call('sed -e \"s?BINFILE1?u-boot.bin.new?\" -e \"s?BINFILE2?u-boot.env.new?\" %s/test/py/tests/test_efi_capsule/uboot_bin_env.its > %s/uboot_bin_env.its' % + (u_boot_config.source_dir, data_dir), + shell=True) + check_call('cd %s; %s/tools/mkimage -f uboot_bin_env.its uboot_bin_env.itb' % + (data_dir, u_boot_config.build_dir), + shell=True) + check_call('cd %s; %s/tools/mkeficapsule --fit uboot_bin_env.itb --version 1 --index 1 Test01' % + (data_dir, u_boot_config.build_dir), + shell=True) + + # Create a disk image with EFI system partition + check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' % + (mnt_point, image_path), shell=True) + check_call('sgdisk %s -A 1:set:0 -t 1:C12A7328-F81F-11D2-BA4B-00A0C93EC93B' % + image_path, shell=True) + + except CalledProcessError as exception: + pytest.skip('Setup failed: %s' % exception.cmd) + return + else: + yield image_path + finally: + call('rm -rf %s' % mnt_point, shell=True) + call('rm -f %s' % image_path, shell=True) + call('rm -f ./spi.bin', shell=True) diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py new file mode 100644 index 000000000000..d8e27707fd79 --- /dev/null +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py @@ -0,0 +1,178 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Firmware Update Test + +""" +This test verifies capsule-on-disk firmware update +""" + +from subprocess import check_call, check_output, CalledProcessError +import pytest +from capsule_defs import * + + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_capsule_firmware_fit') +@pytest.mark.buildconfigspec('efi_capsule_on_disk') +@pytest.mark.buildconfigspec('dfu') +@pytest.mark.buildconfigspec('dfu_sf') +@pytest.mark.buildconfigspec('cmd_efidebug') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_memory') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.buildconfigspec('cmd_sf') +@pytest.mark.slow +class TestEfiCapsuleFirmwareFit(object): + def test_efi_capsule_fw1( + self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 1 - Update U-Boot and U-Boot environment on SPI Flash + but with OsIndications unset + No update should happen + 0x100000-0x150000: U-Boot binary (but dummy) + 0x150000-0x200000: U-Boot environment (but dummy) + """ + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 1-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""', + 'efidebug boot order 1', + 'env set -e OsIndications', + 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"', + 'env save']) + + # initialize contents + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 100000 10', + 'sf read 5000000 100000 10', + 'md.b 5000000 10']) + assert 'Old' in ''.join(output) + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 150000 10', + 'sf read 5000000 150000 10', + 'md.b 5000000 10']) + assert 'Old' in ''.join(output) + + # place a capsule file + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + # reboot + u_boot_console.restart_uboot() + + capsule_early = u_boot_config.buildconfig.get( + 'config_efi_capsule_on_disk_early') + with u_boot_console.log.section('Test Case 1-b, after reboot'): + if not capsule_early: + # make sure that dfu_alt_info exists even persistent variables + # are not available. + output = u_boot_console.run_command_list([ + 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"', + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + # need to run uefi command to initiate capsule handling + output = u_boot_console.run_command( + 'env print -e -all Capsule0000') + + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 100000 10', + 'md.b 4000000 10']) + assert 'u-boot:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 150000 10', + 'md.b 4000000 10']) + assert 'u-boot-env:Old' in ''.join(output) + + def test_efi_capsule_fw2( + self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 2 - Update U-Boot and U-Boot environment on SPI Flash + 0x100000-0x150000: U-Boot binary (but dummy) + 0x150000-0x200000: U-Boot environment (but dummy) + """ + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 2-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""', + 'efidebug boot order 1', + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', + 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"', + 'env save']) + + # initialize contents + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 100000 10', + 'sf read 5000000 100000 10', + 'md.b 5000000 10']) + assert 'Old' in ''.join(output) + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot.env.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 150000 10', + 'sf read 5000000 150000 10', + 'md.b 5000000 10']) + assert 'Old' in ''.join(output) + + # place a capsule file + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + # reboot + u_boot_console.restart_uboot() + + capsule_early = u_boot_config.buildconfig.get( + 'config_efi_capsule_on_disk_early') + with u_boot_console.log.section('Test Case 2-b, after reboot'): + if not capsule_early: + # make sure that dfu_alt_info exists even persistent variables + # are not available. + output = u_boot_console.run_command_list([ + 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"', + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + # need to run uefi command to initiate capsule handling + output = u_boot_console.run_command( + 'env print -e -all Capsule0000') + + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' not in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 100000 10', + 'md.b 4000000 10']) + assert 'u-boot:New' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 150000 10', + 'md.b 4000000 10']) + assert 'u-boot-env:New' in ''.join(output) diff --git a/test/py/tests/test_efi_capsule/uboot_bin_env.its b/test/py/tests/test_efi_capsule/uboot_bin_env.its new file mode 100644 index 000000000000..31e2f8049f9a --- /dev/null +++ b/test/py/tests/test_efi_capsule/uboot_bin_env.its @@ -0,0 +1,36 @@ +/* + * Automatic software update for U-Boot + * Make sure the flashing addresses ('load' prop) is correct for your board! + */ + +/dts-v1/; + +/ { + description = "Automatic U-Boot environment update"; + #address-cells = <2>; + + images { + u-boot-bin@100000 { + description = "U-Boot binary on SPI Flash"; + data = /incbin/("BINFILE1"); + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + hash-1 { + algo = "sha1"; + }; + }; + u-boot-env@150000 { + description = "U-Boot environment on SPI Flash"; + data = /incbin/("BINFILE2"); + compression = "none"; + type = "firmware"; + arch = "sandbox"; + load = <0>; + hash-1 { + algo = "sha1"; + }; + }; + }; +}; diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index db95426457cc..45e27d74a5e9 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -101,7 +101,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, } header.capsule_guid = efi_guid_fm_capsule; header.header_size = sizeof(header); - header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; /* TODO */ + /* TODO: The current implementation ignores flags */ + header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; header.capsule_image_size = sizeof(header) + sizeof(capsule) + sizeof(u64) + sizeof(image) From patchwork Tue Nov 17 00:28:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324546 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4493298ejb; Mon, 16 Nov 2020 16:32:10 -0800 (PST) X-Google-Smtp-Source: ABdhPJwO/rEsfeFLTYcTtH9zLcTSaz1cMI7uTxnIq9wdrV57btBPifc0sIlO2ct3mPwXRMYR/YKE X-Received: by 2002:aa7:cc0e:: with SMTP id q14mr17539020edt.326.1605573130247; Mon, 16 Nov 2020 16:32:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573130; cv=none; d=google.com; s=arc-20160816; b=kUtNaWEPYb7GV65VVh7WQzrJc4+4qUfJDheR6QJl/BgCjTDEJhz2MFeWD6sZvW3SDv i3eyBIkEmOGqq6PFMDHyyR8pk33rrH0Uh+DywDcS1DO9e+pVDDylJXZe0GAihsuSl+uC ns9xpyMe8ka7wkugGrbhTX0apwYM+SvFYsw4Bl4Tx9IpwT6NBzOVO911n3iV1QpZLrVq ws7zWDgFQMsJEP+g/xvWw4ryzNySkEQYOXOHe1x+qmwntwzhVX7x/K9xNCI8aN+k57mQ +HkA+banWR+hNPRc9CUWIrhCHr6Y0rakBm9yc2C261gq0rEhiPasTGHtwmxYpXLd8zpD UD5Q== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1V5zlCoZ1xTo6TQ0f5yeAmrzEUbapMfNgI1FhlifC0A=; b=CppuBgZ5xZXlTmnZVBoZsQfZwo14+cb5MdSUdAle4aHPQscHqjfB3+8USJI4pPu6ta xtIR9tKzucxBwLhcF/BzqSQdRmpe4kXtRJd5BIVdJxY0HRHZxwW4VvjUb/MMFAPpiXo1 g2Gj4vCqPx/FPTfDLDOYRaoDF0LGjcy4kIjP+1An0812b/J8uIdNnous6XV1i53aaX7J 4FPqevnOb/0Otu6/2sGzKpHgf5xtvNCQz4lHeZ0s3ixoq7MmpKCfRx+6zwmgqlnhbcJ4 kY8xeZ2Bg+Vj2LuVQktmtfR1Ob3OkFysLiXxumtDSkPqeb/vtZqcxjlJ+8bplkuLVsK/ zNhw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="EPmX/Ot3"; 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=pass (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 ob22si245741ejb.735.2020.11.16.16.32.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:32:10 -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; dkim=pass header.i=@linaro.org header.s=google header.b="EPmX/Ot3"; 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=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 5D720825AC; Tue, 17 Nov 2020 01:30:50 +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="EPmX/Ot3"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1A4CD825AE; Tue, 17 Nov 2020 01:29:39 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,T_SPF_HELO_TEMPERROR,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com [IPv6:2607:f8b0:4864:20::535]) (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 ED79682588 for ; Tue, 17 Nov 2020 01:29:12 +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=takahiro.akashi@linaro.org Received: by mail-pg1-x535.google.com with SMTP id f18so14719219pgi.8 for ; Mon, 16 Nov 2020 16:29:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1V5zlCoZ1xTo6TQ0f5yeAmrzEUbapMfNgI1FhlifC0A=; b=EPmX/Ot32ecOr3Oabucy4Kc6g19CdUT85SOjCl5A5IcsZW8F/hPc3fBEsojevNuLgN xzz3I2/tmZorrnx9JqhIIEqpB5vy9Cf1RcJ0IePt9UMpz5IkJtMt7cNRfB8MsAc0bqGD wBTwWzySoRtUiKZYUb6bGD1WjAlO3ReYIlsPZcWNBEGH5XiJOXqbeFOvowRDw0/WHs12 rxFk6rMn4JLzzk7VTb62/qibfBoTfyOL485H/7+i4gZ/jiH7LZUTV2xR29fKW8Y5S033 HUGhPBjX9uJ5Q6PMnaB7F+eRyYI45wl7kacMvMFb2MTDVTR9/oHv7oloJ3xTPb7CJPYa g3Gw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1V5zlCoZ1xTo6TQ0f5yeAmrzEUbapMfNgI1FhlifC0A=; b=o4/cdfvnmMf1IzdFnRpnakY4OE37x1XU59GwvBBKk0oqAbgRWUKcsCRuX0vYUB63P3 NNMmDxujCZmnhKhKCl6eFZEm103UCgxLITA1XBxr2uvVTo1+oNVG0n04N9No7rRcQHw+ IIDzlbBD9I6SawwCHEE6V6SAAZb19Z70qdQDId/YySgOtUwzFEp7x50AI6h+8zEILQtD v0cGdAOim268lyefIIL2//ZBHVUUbsgJ97cQRWP6DS01IynQQFLCbtSai9Pzy2gU66Z7 lepEDXEqfU7bxHnhVjKXpl7sqqrGgrH96JwbG5DJoyjOvyy6RDn6LmqkA0fXUvX+PMjz qApA== X-Gm-Message-State: AOAM530yg46gDd5rcBPpRFRqUAXmjKjzHaHnE6u6mDVGrmvJeFoUedxS 2oJYUor8O0r15axVN12bD59+Hw== X-Received: by 2002:aa7:8744:0:b029:18b:a9e1:803d with SMTP id g4-20020aa787440000b029018ba9e1803dmr15586963pfo.50.1605572951469; Mon, 16 Nov 2020 16:29:11 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.29.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:10 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 10/11] test/py: efi_capsule: test for raw image capsule Date: Tue, 17 Nov 2020 09:28:04 +0900 Message-Id: <20201117002805.13902-11-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean The test can run on sandbox build and it attempts to execute a firmware update via a capsule-on-disk, using a raw image capsule, CONFIG_EFI_CAPSULE_RAW. To run this test successfully, you need configure U-Boot specifically; See test_capsule_firmware.py for requirements, and hence it won't run on Travis CI, at least, for now. Signed-off-by: AKASHI Takahiro --- test/py/tests/test_efi_capsule/conftest.py | 3 + .../test_efi_capsule/test_capsule_firmware.py | 63 +++++++++++++++++++ 2 files changed, 66 insertions(+) -- 2.28.0 diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py index 147266189912..e037bd20560d 100644 --- a/test/py/tests/test_efi_capsule/conftest.py +++ b/test/py/tests/test_efi_capsule/conftest.py @@ -53,6 +53,9 @@ def efi_capsule_data(request, u_boot_config): check_call('cd %s; %s/tools/mkeficapsule --fit uboot_bin_env.itb --version 1 --index 1 Test01' % (data_dir, u_boot_config.build_dir), shell=True) + check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --version 1 --index 1 Test02' % + (data_dir, u_boot_config.build_dir), + shell=True) # Create a disk image with EFI system partition check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' % diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware.py b/test/py/tests/test_efi_capsule/test_capsule_firmware.py index d8e27707fd79..f006fa95d650 100644 --- a/test/py/tests/test_efi_capsule/test_capsule_firmware.py +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware.py @@ -15,6 +15,7 @@ from capsule_defs import * @pytest.mark.boardspec('sandbox') @pytest.mark.buildconfigspec('efi_capsule_firmware_fit') +@pytest.mark.buildconfigspec('efi_capsule_firmware_raw') @pytest.mark.buildconfigspec('efi_capsule_on_disk') @pytest.mark.buildconfigspec('dfu') @pytest.mark.buildconfigspec('dfu_sf') @@ -176,3 +177,65 @@ class TestEfiCapsuleFirmwareFit(object): 'sf read 4000000 150000 10', 'md.b 4000000 10']) assert 'u-boot-env:New' in ''.join(output) + + def test_efi_capsule_fw3( + self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 3 - Update U-Boot on SPI Flash, raw image format + 0x100000-0x150000: U-Boot binary (but dummy) + """ + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 3-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 TEST host 0:1 /helloworld.efi ""', + 'efidebug boot order 1', + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', + 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"', + 'env save']) + + # initialize content + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 100000 10', + 'sf read 5000000 100000 10', + 'md.b 5000000 10']) + assert 'Old' in ''.join(output) + + # place a capsule file + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test02' in ''.join(output) + + # reboot + u_boot_console.restart_uboot() + + capsule_early = u_boot_config.buildconfig.get( + 'config_efi_capsule_on_disk_early') + with u_boot_console.log.section('Test Case 3-b, after reboot'): + if not capsule_early: + # make sure that dfu_alt_info exists even persistent variables + # are not available. + output = u_boot_console.run_command_list([ + 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"', + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test02' in ''.join(output) + + # need to run uefi command to initiate capsule handling + output = u_boot_console.run_command( + 'env print -e -all Capsule0000') + + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test02' not in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 100000 10', + 'md.b 4000000 10']) + assert 'u-boot:New' in ''.join(output) From patchwork Tue Nov 17 00:28:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 324547 Delivered-To: patch@linaro.org Received: by 2002:a17:906:d156:0:0:0:0 with SMTP id br22csp4493437ejb; Mon, 16 Nov 2020 16:32:21 -0800 (PST) X-Google-Smtp-Source: ABdhPJzn1SX1kXca4vbOeZe7eeaFGCSlCTrKA0Y5ALRC8yAqNOhz+1g/vEPc3048lXIMvzHZLIPE X-Received: by 2002:a17:906:2818:: with SMTP id r24mr17794610ejc.100.1605573141791; Mon, 16 Nov 2020 16:32:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605573141; cv=none; d=google.com; s=arc-20160816; b=PHxjNayLBlt5C19kyqObH5gLqA9v51bCcEgZpzB+t8PYJtj+AjThQxXw2ziSTRPQfK gjDzIgnZWw2oIzJ8vXWzP8tGp2eRmaKYQ6cRnnPL+iivCVmYM0WKJD/qSb0ZKhEfqleT sYNqlJz9p0V/z54L9qzv/a+8UFHdhGPAGOS/3hX9Iwq1rfS5XMyD6hYHQ0dHJO1RZlXf nVF3Nc47c1nYRYhsZkvtvSC1ItHzWLGqu4EtuoJEoHnJaQ4S9ZwP/MeRGPrKvmuZhdQR Q7R81ML0RC8AxEiM+QFm8SlrflIZbpSdSdgOeeXQrgwT2//elJNgT31zN5s4USC6hA/d TbVg== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1q6dfJV585KCVgW4EI5erEsoW8f7cX5vuTNO9p46u3c=; b=fkdLqn6XoS/iuDPI8B72z1kdJx07YXi17EuwH4gV7xtaoh8WkBZ8sB3flwCDNyvYA3 r8K1IZPIz795vy7WcNN6gDdP74Dfiw86WXMLUexGGCpm4kR1/KJT/t8KrQ7YKEY8snER vHLQ7BQkOgpnxdt9khlNxAPxB1j+oUarUFuP9ta5pyVA0rDKmraxVTZs8pSPeOBqzfZk FSwI5Rm0NQpNuKMV/xc+wg/J/iQilQsaQM8Umnj8DkvowIl1qyv/XGuuLWHsFfNPyX4r Y1Mr58R5iZkYnG2B/WURiMrCDhwjTCNluUGwRGjkL5FaHkaOPIo93Sr2HX+rsTpFbfcX PvOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="GhGk0HG/"; 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 d21si12172735ejy.662.2020.11.16.16.32.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:32:21 -0800 (PST) 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="GhGk0HG/"; 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 2A1CD825C3; Tue, 17 Nov 2020 01:30:53 +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="GhGk0HG/"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id A01A382590; Tue, 17 Nov 2020 01:29:39 +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.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,T_SPF_HELO_TEMPERROR autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) (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 70F7382586 for ; Tue, 17 Nov 2020 01:29:15 +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=takahiro.akashi@linaro.org Received: by mail-pg1-x532.google.com with SMTP id v21so2009025pgi.2 for ; Mon, 16 Nov 2020 16:29:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1q6dfJV585KCVgW4EI5erEsoW8f7cX5vuTNO9p46u3c=; b=GhGk0HG/zLd03gUQlohhOOJja+g2TCyDOJ9MQ7GwRisckNOJFf8OF3fMFgGfW3ND15 fPO2Gmwmbe3unjDqSNqjr5XSdbz4CTAIcW37eVQ7eRGETe6GIXJabCD6oT+gaqFaw4mD 6d/NKYkZfNntz2OPdY7NJ9vBwWyKzRDvZeZ6PdzSrQu8eJd21u/x8+QFaR5SfOVrYwNT imkCI3WcXf4gIvcBQWeH3DOnA9NqeqHrUX8lv7mMH3uYCzEQyu/jQRpwdMwSKkQivyMp sggVJyJNZ3x3AYcUTQHYDWwl4AoT3JyCELbFiICdroemQcGi/ZDIIHqQKdOhpqRURNdo 7MBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1q6dfJV585KCVgW4EI5erEsoW8f7cX5vuTNO9p46u3c=; b=OpfgStHCHWWnOlyS9/nUEjAalrHFe1TdK6A2a6wXEmLlqkuhLSw3ZgpS5LkXeBfYqg R3kreQu8LJUGVpkVs3tddNTL/J7lnULHVyivjxBVyYeq3lNFVv8q+r0AFC3kSXRisqKN PTl+HzHj4bvIYwGK+iATBEUZFCqb9h3HASpunrgRpzWsgyqdHnlLTiXHR2xx6fFGGiDU iBcqhRXcj+OU7jts/fUuxlx8FPpLZhQ0TDSHzC1cO/EgmxKF1XN0bDXKJCsTSAhIAuO5 dYbkAcy+3pI7p8gAswsv/D38zJKghsApRjBy3dBiqtL+LSAxzVdib6WYpIMyfU4LAQhC ZOHA== X-Gm-Message-State: AOAM530zGH+De2T/Zlhq0MzDYp+96aBZSIfC3L/3T6qGwWEcaYW1p4wL mEVeMA/gO/4omJV4A+5im66ziw== X-Received: by 2002:a63:d74e:: with SMTP id w14mr1391788pgi.360.1605572953945; Mon, 16 Nov 2020 16:29:13 -0800 (PST) Received: from localhost.localdomain (p784a5642.tkyea130.ap.so-net.ne.jp. [120.74.86.66]) by smtp.gmail.com with ESMTPSA id t64sm20116506pfd.36.2020.11.16.16.29.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 16 Nov 2020 16:29:13 -0800 (PST) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de Cc: sughosh.ganu@linaro.org, u-boot@lists.denx.de, AKASHI Takahiro Subject: [PATCH v9 11/11] sandbox: enable capsule update for testing Date: Tue, 17 Nov 2020 09:28:05 +0900 Message-Id: <20201117002805.13902-12-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201117002805.13902-1-takahiro.akashi@linaro.org> References: <20201117002805.13902-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean Add more configuration options to allow for efi capsule update on sandbox. Signed-off-by: AKASHI Takahiro --- configs/sandbox64_defconfig | 6 ++++++ configs/sandbox_defconfig | 6 ++++++ 2 files changed, 12 insertions(+) -- 2.28.0 diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index dc993cd13aaa..661830763feb 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -231,3 +231,9 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +# +CONFIG_DFU_SF=y +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index f2a767a4cdea..e385425b7d91 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -274,3 +274,9 @@ CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +# +CONFIG_DFU_SF=y +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y +CONFIG_EFI_CAPSULE_ON_DISK=y +CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y