From patchwork Thu Feb 17 15:12:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masami Hiramatsu X-Patchwork-Id: 543387 Delivered-To: patch@linaro.org Received: by 2002:ac0:e142:0:0:0:0:0 with SMTP id r2csp448823imn; Thu, 17 Feb 2022 07:12:54 -0800 (PST) X-Google-Smtp-Source: ABdhPJwSWl8gQhHZ9SPHaitRogKfUfvLCzuHo5bu7CqJYrmQdlZ/cbVBQN7myaEkqVJI/oK2vXcK X-Received: by 2002:a17:907:1de9:b0:6b9:e4f:25ec with SMTP id og41-20020a1709071de900b006b90e4f25ecmr2648860ejc.741.1645110773843; Thu, 17 Feb 2022 07:12:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1645110773; cv=none; d=google.com; s=arc-20160816; b=X0qqUalSqC8n1ad+URAKtTzjwmdzkZgiDlyuXTOc0VtNugY2hoquGAsu8INy/3/zEc n6LnMfJeA2GNaQQGr4jofsY+CUgwqiS+wA9hPAh88C6E7N23ybOtPk2nAIkhoF2ykjb7 zchvbqsGaqL0Wgfzw0JZaHhrHSGmQk5Wt8xvxuoU671lal5WvVwJ40rX7CHZ716+wVNB 7A4MPc1Xbj7O9HwbVlUlB3IkSZPz8pkpcv+nfIPMsoSoz7rHziL9/Midf+/BIF1C5CXU pKP4TWMS80FjkJsKku7AIhQBM+3fCNmtiQ1BIq2tzOs9Q6ZsHuRBnLSNOpY+eX9AxnLK IUCQ== 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=753VFqlnL6OJTLcFSg4Sj7NiDPbqNL706UE7WVrJntU=; b=CkDowPWSQBM5sQNSlrfpd83OERdairVLo5jWdQYeI0Fn+ARpV5U2BPhLRjphDpb9Y2 uSvXhpyMVJKUPhokytinMEMScxR0nA0Eg5OgC13eI+n5cMfaPUlXn+npdujEzSQt9CjG gGA7WHRi/ihmfbUEwQYVV9h3vCDM6x7G1F7zEaqGo1zbS6w0xnA0FjtQh48Q9AIHBDkj BjSoYSiEPqCteeeYkVtieKlbHBP2FJScThOOY7vcf6gFZ2GVObgDHMY7kW8/Wy6SGOEB aZTVdZTCpZDAPobjISlnV1o3mlq2QcinN7dZ7fJO7GSiSFTA2Wi0e8bOFEy6Xy3V/6Hs r6gg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=JOAFFp0T; 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 eq24si3390657edb.318.2022.02.17.07.12.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Feb 2022 07:12:53 -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=JOAFFp0T; 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 A645983BDF; Thu, 17 Feb 2022 16:12:44 +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="JOAFFp0T"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C7E6083BD4; Thu, 17 Feb 2022 16:12:31 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) (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 DA89283BD2 for ; Thu, 17 Feb 2022 16:12:13 +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-pg1-x52d.google.com with SMTP id 132so5289041pga.5 for ; Thu, 17 Feb 2022 07:12:13 -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=753VFqlnL6OJTLcFSg4Sj7NiDPbqNL706UE7WVrJntU=; b=JOAFFp0Ts3QHn/qQ/5dJuaVWvze3sVSKMy1Rmt4KKlxS0pbLKot4MhdxjDasSZg5c+ JTjb2R5yHjeTzDtfN/e4mZtmztjyatR08iUyDGBbzk7+JVmF0EP7R7FTS3tM/Vkw8aRr L5c0a4GYOJNQTe75PNQ+7Slkiiof8DeMhhiEZQ4jmV3DooovDp/FupTDd+cSDrYk9urK NCWdwmGBi4E73NtrHSuRUOFBcI60CBv3XxiQI6RKD149SjZWL+2rrnhKWYHeZzfzPJ2x fSD8291d6lkPPpP/LHKNQs4F65s9H3dnt8zVJtOD5CXs9xqP7Qtzz28tRbB72fAnQ2Nc lGPQ== 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=753VFqlnL6OJTLcFSg4Sj7NiDPbqNL706UE7WVrJntU=; b=a36hEipdZeD0iVrSvMKhsZv1E+WDcx/fOYFyFNoTtc7Do0sjUOv0tzmyBq9jJ9p2XU MLxG9jjYaO2OS3CbX2jwvelkns6oIJ1Q6VmCUL0LLwQ7HG9fzpyQIUClH6OESX2zHrMC RVyV1CIzEpQo788R0vrBxU+ISd1CNLvm0ndWXeWSCVeXBZTmYEL3mOQNh4V1XW90gMwx TrKUkmdegjbQESnLXJ2LY5T6O2xNgUEhPFhH6OwfV4yE/2Pc+PBXJhRvm8bzoK3XT9kq gHVO1lDA+Sk1IdHE0JOKMi/+0AuQfHMhRs9y902XfNEn7MribUz4AvE8qfARLsd7MbiP xJ/A== X-Gm-Message-State: AOAM530aKJmiZFEj96tk1f3cnKreJOF0fUzOkPhoTyYZNLuApp+CsKnS Bi9j5AWJcVmZ4TPVCJ/KkYUKKt+nSW01DQ== X-Received: by 2002:a05:6a00:140c:b0:4e1:530c:edc0 with SMTP id l12-20020a056a00140c00b004e1530cedc0mr3546873pfu.18.1645110731462; Thu, 17 Feb 2022 07:12:11 -0800 (PST) Received: from localhost.localdomain (113x37x226x201.ap113.ftth.ucom.ne.jp. [113.37.226.201]) by smtp.gmail.com with ESMTPSA id c3sm17039754pfd.129.2022.02.17.07.12.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Feb 2022 07:12:11 -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 v2 5/8] FWU: Add FWU metadata access driver for SPI flash Date: Fri, 18 Feb 2022 00:12:07 +0900 Message-Id: <164511072688.43219.11381169900703679729.stgit@localhost> X-Mailer: git-send-email 2.25.1 In-Reply-To: <164511067605.43219.15508992404634142079.stgit@localhost> References: <164511067605.43219.15508992404634142079.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.5 at phobos.denx.de X-Virus-Status: Clean For the platform which doesn't have GPT partitions for the firmware but on SPI flash, the FWU metadata is stored on SPI flash as raw image at specific offset. This driver gives the access methods for those metadata information on the SPI flash. Signed-off-by: Masami Hiramatsu --- drivers/fwu-mdata/Kconfig | 9 + drivers/fwu-mdata/Makefile | 1 drivers/fwu-mdata/fwu_mdata_sf.c | 294 ++++++++++++++++++++++++++++++++++++++ include/fwu.h | 2 4 files changed, 306 insertions(+) create mode 100644 drivers/fwu-mdata/fwu_mdata_sf.c diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig index d5edef19d6..9bed3e9c1e 100644 --- a/drivers/fwu-mdata/Kconfig +++ b/drivers/fwu-mdata/Kconfig @@ -14,3 +14,12 @@ config FWU_MDATA_GPT_BLK help Enable support for accessing FWU Metadata on GPT partitioned block devices. + +config FWU_MDATA_SF + bool "Enable FWU Multi Bank Update for SPI Flash" + depends on DM_FWU_MDATA + 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. diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile index 12a5b4fe04..f8db25ab69 100644 --- a/drivers/fwu-mdata/Makefile +++ b/drivers/fwu-mdata/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o +obj-$(CONFIG_FWU_MDATA_SF) += fwu_mdata_sf.o diff --git a/drivers/fwu-mdata/fwu_mdata_sf.c b/drivers/fwu-mdata/fwu_mdata_sf.c new file mode 100644 index 0000000000..010528b91a --- /dev/null +++ b/drivers/fwu-mdata/fwu_mdata_sf.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct fwu_mdata_sf_priv { + struct spi_flash *sf; + u32 pri_offset; + u32 sec_offset; +}; + +static int sf_load_data(struct spi_flash *sf, u32 offs, u32 size, void **data) +{ + int ret; + + *data = memalign(ARCH_DMA_MINALIGN, size); + if (!*data) + return -ENOMEM; + + ret = spi_flash_read(sf, offs, size, *data); + if (ret < 0) { + free(*data); + *data = NULL; + } + + return ret; +} + +static int sf_save_data(struct spi_flash *sf, u32 offs, u32 size, void *data) +{ + u32 sect_size, nsect; + void *buf; + int ret; + + sect_size = sf->mtd.erasesize; + nsect = DIV_ROUND_UP(size, sect_size); + ret = spi_flash_erase(sf, 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(sf, offs, size, buf); + + free(buf); + + return ret; +} + +static int fwu_sf_load_mdata(struct spi_flash *sf, struct fwu_mdata **mdata, u32 offs, bool primary) +{ + int ret; + + ret = sf_load_data(sf, offs, sizeof(struct fwu_mdata), (void **)mdata); + + if (ret >= 0) { + ret = fwu_verify_mdata(*mdata, primary); + if (ret < 0) { + free(*mdata); + *mdata = NULL; + } + } + + return ret; +} + +static int fwu_sf_load_primary_mdata(struct fwu_mdata_sf_priv *sf_priv, + struct fwu_mdata **mdata) +{ + return fwu_sf_load_mdata(sf_priv->sf, mdata, sf_priv->pri_offset, true); +} + +static int fwu_sf_load_secondary_mdata(struct fwu_mdata_sf_priv *sf_priv, + struct fwu_mdata **mdata) +{ + return fwu_sf_load_mdata(sf_priv->sf, mdata, sf_priv->sec_offset, false); +} + +static int fwu_sf_save_primary_mdata(struct fwu_mdata_sf_priv *sf_priv, + struct fwu_mdata *mdata) +{ + return sf_save_data(sf_priv->sf, sf_priv->pri_offset, + sizeof(struct fwu_mdata), mdata); +} + +static int fwu_sf_save_secondary_mdata(struct fwu_mdata_sf_priv *sf_priv, + struct fwu_mdata *mdata) +{ + return sf_save_data(sf_priv->sf, sf_priv->sec_offset, + sizeof(struct fwu_mdata), mdata); +} + +static int fwu_sf_get_valid_mdata(struct fwu_mdata_sf_priv *sf_priv, + struct fwu_mdata **mdata) +{ + if (fwu_sf_load_primary_mdata(sf_priv, mdata) == 0) + return 0; + + log_err("Failed to load/verify primary mdata. Try secondary.\n"); + + if (fwu_sf_load_secondary_mdata(sf_priv, mdata) == 0) + return 0; + + log_err("Failed to load/verify secondary mdata.\n"); + + return -1; +} + +static int fwu_sf_update_mdata(struct udevice *dev, struct fwu_mdata *mdata) +{ + struct fwu_mdata_sf_priv *sf_priv = dev_get_priv(dev); + 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(sf_priv, 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(sf_priv, mdata); + if (ret < 0) { + log_err("Failed to update the secondary mdata.\n"); + return ret; + } + + return 0; +} + +static int fwu_sf_mdata_check(struct udevice *dev) +{ + struct fwu_mdata *primary = NULL, *secondary = NULL; + struct fwu_mdata_sf_priv *sf_priv = dev_get_priv(dev); + int ret; + + ret = fwu_sf_load_primary_mdata(sf_priv, &primary); + if (ret < 0) + log_err("Failed to read the primary mdata: %d\n", ret); + + ret = fwu_sf_load_secondary_mdata(sf_priv, &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(sf_priv, primary); + if (ret < 0) + log_err("Restoring secondary mdata partition failed\n"); + } else if (secondary) { + ret = fwu_sf_save_primary_mdata(sf_priv, 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 udevice *dev, struct fwu_mdata **mdata) +{ + struct fwu_mdata_sf_priv *sf_priv = dev_get_priv(dev); + + return fwu_sf_get_valid_mdata(sf_priv, mdata); +} + +/* + * By default, this expects that dfu_alt_info is defined as the following order + * image0.bank0, image0.bank1, image1.bank0, ... + * Thus the alt_no is (the index of image) * #banks + update_bank. + */ +int __weak fwu_plat_get_image_alt_num(efi_guid_t image_type_id, + u32 update_bank, int *alt_no) +{ + struct fwu_mdata *mdata; + int i, ret; + + ret = fwu_get_mdata(&mdata); + if (ret < 0) + return ret; + + ret = -ENOENT; + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) + if (!guidcmp(&image_type_id, &mdata->img_entry[i].image_type_uuid)) { + *alt_no = i * CONFIG_FWU_NUM_BANKS + update_bank; + ret = 0; + break; + } + + free(mdata); + return ret; +} + +/* Since the dfu_alt_info is defined by the platform, ask platform about alt-number. */ +static int fwu_sf_get_image_alt_num(struct udevice *dev, efi_guid_t image_type_id, + u32 update_bank, int *alt_no) +{ + return fwu_plat_get_image_alt_num(image_type_id, update_bank, alt_no); +} + +/** + * fwu_mdata_sf_of_to_plat() - Translate from DT to fwu mdata device + */ +static int fwu_mdata_sf_of_to_plat(struct udevice *dev) +{ + struct fwu_mdata_sf_priv *sf_priv = dev_get_priv(dev); + const fdt32_t *phandle_p = NULL; + struct udevice *sf_dev; + int ret, size; + u32 phandle; + + /* Find the FWU mdata storage device */ + phandle_p = ofnode_get_property(dev_ofnode(dev), + "fwu-mdata-store", &size); + if (!phandle_p) { + log_err("fwu-mdata-store property not found\n"); + return -ENOENT; + } + + phandle = fdt32_to_cpu(*phandle_p); + + ret = device_get_global_by_ofnode( + ofnode_get_by_phandle(phandle), + &sf_dev); + if (ret) + return ret; + + sf_priv->sf = dev_get_uclass_priv(sf_dev); + + /* Get the offset of primary and seconday mdata */ + ret = ofnode_read_u32_index(dev_ofnode(dev), "mdata-offsets", 0, + &sf_priv->pri_offset); + if (ret) + return ret; + ret = ofnode_read_u32_index(dev_ofnode(dev), "mdata-offsets", 1, + &sf_priv->sec_offset); + if (ret) + return ret; + + return 0; +} + +static int fwu_mdata_sf_probe(struct udevice *dev) +{ + /* Ensure the metadata can be read. */ + return fwu_sf_mdata_check(dev); +} + +static struct fwu_mdata_ops fwu_sf_ops = { + .get_image_alt_num = fwu_sf_get_image_alt_num, + .mdata_check = fwu_sf_mdata_check, + .get_mdata = fwu_sf_get_mdata, + .update_mdata = fwu_sf_update_mdata, +}; + +static const struct udevice_id fwu_mdata_ids[] = { + { .compatible = "u-boot,fwu-mdata-sf" }, + { } +}; + +U_BOOT_DRIVER(fwu_mdata_sf) = { + .name = "fwu-mdata-sf", + .id = UCLASS_FWU_MDATA, + .of_match = fwu_mdata_ids, + .ops = &fwu_sf_ops, + .probe = fwu_mdata_sf_probe, + .of_to_plat = fwu_mdata_sf_of_to_plat, + .priv_auto = sizeof(struct fwu_mdata_sf_priv), +}; diff --git a/include/fwu.h b/include/fwu.h index 88dc4a4b9a..f5ac3f6d2e 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -66,5 +66,7 @@ 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_alt_num(struct udevice *dev, void *identifier); void fwu_plat_get_bootidx(void *boot_idx); +int fwu_plat_get_image_alt_num(efi_guid_t image_type_id, u32 update_bank, + int *alt_no); #endif /* _FWU_H_ */