From patchwork Thu Jan 20 15:31:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masami Hiramatsu X-Patchwork-Id: 533550 Delivered-To: patch@linaro.org Received: by 2002:ad5:5d50:0:0:0:0:0 with SMTP id x16csp1677476imu; Thu, 20 Jan 2022 07:31:29 -0800 (PST) X-Google-Smtp-Source: ABdhPJx1H5MfpOiIp9i3tAgnrBSW3LO+8ESukVlomDi342vAdtYTQemvY+KgTNDUzRYKXqhKNvwV X-Received: by 2002:a17:906:1744:: with SMTP id d4mr30299992eje.569.1642692689270; Thu, 20 Jan 2022 07:31:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1642692689; cv=none; d=google.com; s=arc-20160816; b=McoGlIUwBHoEKqM7CrT5m64vmK8rRE9bcY2QumGlm8KHF16rT2s2EW1jSmL2lSjDCK DhlHmLE0EOHyeofLCE0YJhD1V8CDLqsgo72oTGyPvL1ukVtE/OlO4W3L6F9muUTQlu4W FU/SjYUl9+tkWBDma6IHS+o2yThT+qAMNSi7Ie8zzN8d2NLA9Th5iFJurx1V3MJAOBJS CrzdceNTnx5pVWVNNGfodtQb6UEN09WPgDXd/0bj3uWuU80en4xU+IMdw9ouDYKdsNXU WkcnWI5fF3GqESQcNpzWMhL6eFIM1ALMnrmhLz1rApbxD48gaue2rWmK4lxtzHKnbbHg 6GQw== 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:user-agent:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=CNxP4yuPQA/1DdN5JN2f2VwcHuCd9bwF9iKzqvnifYQ=; b=UpiNC3X+2UBlVn1UaYPfqI11FO/z5521N9UQN9PthL6DxBthcJw4NI/ziAZAkjRUPw dSKF/wQhq8h4h7s5tt8jCgqEpPIvcYbIVdnk8aJsTfeMwdu5oJWJBPAR8dQOWd9wm3bR W5/KoXuIyb3XD8++gelGMtlHMgwIVHAOFy17MxoEEjnp40sJzGhG0+gCP6MI8SgMy0RH Cxtv5OOeukJH2W8+Ju00xi0CDLL75iRnVvfWs6gOlPPrjw+9vNFVGkOSv9kE2nkpuWsF 41z3VRabotPxXYx1LXQAihBhNKZOmIKFrCOsTrWe1x5exXpbtDcjJFB2qJyfHZRlIAJY 63CA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=GQh+Kyn4; 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 dd8si2517919ejc.344.2022.01.20.07.31.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Jan 2022 07:31:29 -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=GQh+Kyn4; 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 CC61C838CB; Thu, 20 Jan 2022 16:31: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="GQh+Kyn4"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3E5D7838CB; Thu, 20 Jan 2022 16:31:20 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) (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 EBEFB838DB for ; Thu, 20 Jan 2022 16:31:16 +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=masami.hiramatsu@linaro.org Received: by mail-pl1-x62f.google.com with SMTP id d7so5442287plr.12 for ; Thu, 20 Jan 2022 07:31:16 -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 :user-agent:mime-version:content-transfer-encoding; bh=CNxP4yuPQA/1DdN5JN2f2VwcHuCd9bwF9iKzqvnifYQ=; b=GQh+Kyn4bU+jU0L/D28WJW71KP9wtqOnhghndd0cD1xQI8opEeRqL/DUO33jGp/arD qbeQFiwaOUM8dSegx2aJYF9+a9/EBoReDV6RYxxFHp03H/MhRiYa29B1+kYTm+MvWuBd lfcRuvfXLWEFWItggi44KBocJEAd9PlVqH+RREeSZnq6mDMz0bmAqGhIGN0C74LNz8HS dftUomEo23nqtFl99FEUwge8O3PqIiupr+hbxcvtgMnczQKxSPAa/7vcaTkZquu+cZvx 0VN+uJdtwa3+rrb6TcPgr6IIkZwPAgHcScqKb6/dJkQ8za7qSCxY4wRuMYWrjC0hb+vm Wgcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=CNxP4yuPQA/1DdN5JN2f2VwcHuCd9bwF9iKzqvnifYQ=; b=NyTjZPBrxzEcNHk4lrx8rSGabl3m5bJKvVAMfK1+C4k2JEdUoVOxHk9A9XYreSbT05 tTOXeUdYoGIJonIY95lxbYZWXcOg0GokrgbnYsPxhSrdLr4jtAUg+KfhOGscBkZ8vvlX d6g0PTuyGG+VOEBshR5uQv9uvRPbU4Cpq7YBXF2NdotLQLh+9Cay93xtVditWi+sBR+f m5AfzxQffvCRxGn1TaU87fWZRTJ9KWnQs8FMFj4gMaOH/pJdtnSB15UVtW3EmUtZX+Ej eWFplxzf/KBaWjAaMazBS0y0l7eqv7tbXQCRPAFGO52f4aiEJRyo1KULjJJutPHDTRCK 8D2A== X-Gm-Message-State: AOAM530oJIHxRHKjbsq1Zf+bIINJridmeXv7cfb6fxfIfgTXyW7Qmmll qGTepca25AmSow58m+MrXw3sxTLgdqXCfQ== X-Received: by 2002:a17:902:bf41:b0:14a:bb95:6577 with SMTP id u1-20020a170902bf4100b0014abb956577mr21531355pls.9.1642692675146; Thu, 20 Jan 2022 07:31:15 -0800 (PST) Received: from localhost.localdomain (113x37x226x201.ap113.ftth.ucom.ne.jp. [113.37.226.201]) by smtp.gmail.com with ESMTPSA id t7sm3689839pfj.138.2022.01.20.07.31.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Jan 2022 07:31:14 -0800 (PST) From: Masami Hiramatsu To: u-boot@lists.denx.de Cc: Masami Hiramatsu , Patrick Delaunay , Patrice Chotard , Heinrich Schuchardt , Alexander Graf , AKASHI Takahiro , Simon Glass , Bin Meng , Ilias Apalodimas , Jose Marinho , Grant Likely , Tom Rini , Etienne Carriere , Sughosh Ganu , Paul Liu Subject: [RFC PATCH 11/14] FWU: Add FWU Multi Bank Update on SPI Flash Date: Fri, 21 Jan 2022 00:31:10 +0900 Message-Id: <164269267060.39378.17392247605833481024.stgit@localhost> X-Mailer: git-send-email 2.25.1 In-Reply-To: <164269255955.39378.260729958623102750.stgit@localhost> References: <164269255955.39378.260729958623102750.stgit@localhost> User-Agent: StGit/0.19 MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Signed-off-by: Masami Hiramatsu --- include/fwu.h | 13 ++ lib/fwu_updates/Kconfig | 34 ++++++ lib/fwu_updates/Makefile | 5 - lib/fwu_updates/fwu_mdata_sf.c | 241 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 lib/fwu_updates/fwu_mdata_sf.c diff --git a/include/fwu.h b/include/fwu.h index 7af94988b7..a013170321 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -64,9 +64,18 @@ int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_plat_get_update_index(u32 *update_idx); -int fwu_plat_get_blk_desc(struct blk_desc **desc); -int fwu_plat_get_alt_num(void *identifier); int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr); void fwu_plat_get_bootidx(void *boot_idx); +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK +int fwu_plat_get_blk_desc(struct blk_desc **desc); +int fwu_plat_get_alt_num(void *identifier); +#endif + +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE_SF +struct fwu_mdata_ops *fwu_sf_get_fwu_mdata_ops(void); +int fwu_plat_get_image_alt_num(efi_guid_t image_type_id, u32 update_bank, + int *alt_no); +#endif + #endif /* _FWU_H_ */ diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig index 0940a90747..8a369b9872 100644 --- a/lib/fwu_updates/Kconfig +++ b/lib/fwu_updates/Kconfig @@ -38,3 +38,37 @@ config FWU_REBOOT_AFTER_UPDATE Reboot the machine soon after installing a new firmware and start trial boot. You can disable this option for debugging or FWU development, but recommended to enable it. + +config FWU_MULTI_BANK_UPDATE_GPT_BLK + bool "Enable FWU Multi Bank Update for GPT on blockdev" + depends on FWU_MULTI_BANK_UPDATE + select EFI_PARTITION + help + Enable FWU Multi Bank Update for GPT on a block device. This + driver depends on GPT and the block device. FWU meatadata and + firmware will be stored on a block device with GPT. + +config FWU_MULTI_BANK_UPDATE_SF + bool "Enable FWU Multi Bank Update for SPI Flash" + depends on FWU_MULTI_BANK_UPDATE + help + Enable FWU Multi Bank Update for SPI flash driver. This + driver does not depend on GPT. Instead, the platform must + provide some APIs and define the offset of the primary and + the secondary metadata. + +config FWU_SF_PRIMARY_MDATA_OFFSET + hex "The offset of the primary metadata" + depends on FWU_MULTI_BANK_UPDATE_SF + help + The offset of the primary metadata on SPI Flash in + hexadecimal. + +config FWU_SF_SECONDARY_MDATA_OFFSET + hex "The offset of the secondary metadata" + depends on FWU_MULTI_BANK_UPDATE_SF + help + The offset of the secondary metadata on SPI Flash in + hexadecimal. + This must NOT be the same offset of the primary + metadata. diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile index 73099a30cb..80669344f2 100644 --- a/lib/fwu_updates/Makefile +++ b/lib/fwu_updates/Makefile @@ -6,6 +6,5 @@ obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_mdata.o obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o -ifdef CONFIG_EFI_PARTITION -obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_mdata_gpt_blk.o -endif +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK) += fwu_mdata_gpt_blk.o +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE_SF) += fwu_mdata_sf.o diff --git a/lib/fwu_updates/fwu_mdata_sf.c b/lib/fwu_updates/fwu_mdata_sf.c new file mode 100644 index 0000000000..9e3cae7b68 --- /dev/null +++ b/lib/fwu_updates/fwu_mdata_sf.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * For the FWU SPI flash driver, the platform must define below functions + * according to its dfu_alt_info. + */ +extern int fwu_plat_get_image_alt_num(efi_guid_t image_type_id, + u32 update_bank, int *alt_no); + +static struct spi_flash *fwu_spi_flash; + +static int __fwu_sf_get_flash(void) +{ + if (IS_ENABLED(CONFIG_DM_SPI_FLASH)) { + struct udevice *new; + int ret; + + ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, + &new); + if (ret) + return ret; + + fwu_spi_flash = dev_get_uclass_priv(new); + } else { + fwu_spi_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE); + if (!fwu_spi_flash) + return -EIO; + } + return 0; +} + +static int fwu_sf_get_flash(struct spi_flash **flash) +{ + int ret = 0; + + if (!fwu_spi_flash) + ret = __fwu_sf_get_flash(); + + *flash = fwu_spi_flash; + + return ret; +} + +static int sf_load_data(u32 offs, u32 size, void **data) +{ + struct spi_flash *flash; + int ret; + + ret = fwu_sf_get_flash(&flash); + if (ret < 0) + return ret; + + *data = memalign(ARCH_DMA_MINALIGN, size); + if (!*data) + return -ENOMEM; + + ret = spi_flash_read(flash, offs, size, *data); + if (ret < 0) { + free(*data); + *data = NULL; + } + + return ret; +} + +static int sf_save_data(u32 offs, u32 size, void *data) +{ + struct spi_flash *flash; + u32 sect_size, nsect; + void *buf; + int ret; + + ret = fwu_sf_get_flash(&flash); + if (ret < 0) + return ret; + + sect_size = flash->mtd.erasesize; + nsect = DIV_ROUND_UP(size, sect_size); + ret = spi_flash_erase(flash, offs, nsect * sect_size); + if (ret < 0) + return ret; + + buf = memalign(ARCH_DMA_MINALIGN, size); + if (!buf) + return -ENOMEM; + memcpy(buf, data, size); + + ret = spi_flash_write(flash, offs, size, buf); + + free(buf); + + return ret; +} + +static int fwu_sf_load_mdata(struct fwu_mdata **mdata, u32 offs) +{ + int ret; + + ret = sf_load_data(offs, sizeof(struct fwu_mdata), (void **)mdata); + + if (ret >= 0) { + ret = fwu_verify_mdata(*mdata, + offs == CONFIG_FWU_SF_PRIMARY_MDATA_OFFSET); + if (ret < 0) { + free(*mdata); + *mdata = NULL; + } + } + + return ret; +} + +static int fwu_sf_load_primary_mdata(struct fwu_mdata **mdata) +{ + return fwu_sf_load_mdata(mdata, CONFIG_FWU_SF_PRIMARY_MDATA_OFFSET); +} + +static int fwu_sf_load_secondary_mdata(struct fwu_mdata **mdata) +{ + return fwu_sf_load_mdata(mdata, CONFIG_FWU_SF_SECONDARY_MDATA_OFFSET); +} + +static int fwu_sf_save_primary_mdata(struct fwu_mdata *mdata) +{ + return sf_save_data(CONFIG_FWU_SF_PRIMARY_MDATA_OFFSET, + sizeof(struct fwu_mdata), mdata); +} + +static int fwu_sf_save_secondary_mdata(struct fwu_mdata *mdata) +{ + return sf_save_data(CONFIG_FWU_SF_SECONDARY_MDATA_OFFSET, + sizeof(struct fwu_mdata), mdata); +} + +static int fwu_sf_get_valid_mdata(struct fwu_mdata **mdata) +{ + if (fwu_sf_load_primary_mdata(mdata) == 0) + return 0; + + log_err("Failed to load/verify primary mdata. Try secondary.\n"); + + if (fwu_sf_load_secondary_mdata(mdata) == 0) + return 0; + + log_err("Failed to load/verify secondary mdata.\n"); + + return -1; +} + +static int fwu_sf_update_mdata(struct fwu_mdata *mdata) +{ + int ret; + + /* Update mdata crc32 field */ + mdata->crc32 = crc32(0, (void *)&mdata->version, + sizeof(*mdata) - sizeof(u32)); + + /* First write the primary mdata */ + ret = fwu_sf_save_primary_mdata(mdata); + if (ret < 0) { + log_err("Failed to update the primary mdata.\n"); + return ret; + } + + /* And now the replica */ + ret = fwu_sf_save_secondary_mdata(mdata); + if (ret < 0) { + log_err("Failed to update the secondary mdata.\n"); + return ret; + } + + return 0; +} + +static int fwu_sf_mdata_check(void) +{ + struct fwu_mdata *primary = NULL, *secondary = NULL; + int ret; + + ret = fwu_sf_load_primary_mdata(&primary); + if (ret < 0) + log_err("Failed to read the primary mdata: %d\n", ret); + + ret = fwu_sf_load_secondary_mdata(&secondary); + if (ret < 0) + log_err("Failed to read the secondary mdata: %d\n", ret); + + if (primary && secondary) { + if (memcmp(primary, secondary, sizeof(struct fwu_mdata))) { + log_err("The primary and the secondary mdata are different\n"); + ret = -1; + } + } else if (primary) { + ret = fwu_sf_save_secondary_mdata(primary); + if (ret < 0) + log_err("Restoring secondary mdata partition failed\n"); + } else if (secondary) { + ret = fwu_sf_save_primary_mdata(secondary); + if (ret < 0) + log_err("Restoring primary mdata partition failed\n"); + } + + free(primary); + free(secondary); + return ret; +} + +static int fwu_sf_get_mdata(struct fwu_mdata **mdata) +{ + return fwu_sf_get_valid_mdata(mdata); +} + +static struct fwu_mdata_ops fwu_sf_mdata_ops = { + .get_image_alt_num = fwu_plat_get_image_alt_num, + .mdata_check = fwu_sf_mdata_check, + .get_mdata = fwu_sf_get_mdata, + .update_mdata = fwu_sf_update_mdata, +}; + +struct fwu_mdata_ops *fwu_sf_get_fwu_mdata_ops(void) +{ + return &fwu_sf_mdata_ops; +}