All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support
@ 2022-08-17 12:43 Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 01/13] dt/bindings: Add bindings for GPT based FWU Metadata storage device Sughosh Ganu
                   ` (12 more replies)
  0 siblings, 13 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar


The patchset adds support for the FWU Multi Bank Update[1]
feature. Certain aspects of the Dependable Boot[2] specification have
also been implemented.

The FWU multi bank update feature is used for supporting multiple
sets(also called banks) of firmware image(s), allowing the platform to
boot from a different bank, in case it fails to boot from the active
bank. This functionality is supported by keeping the relevant
information in a structure called metadata, which provides information
on the images. Among other parameters, the metadata structure contains
information on the currect active bank that is being used to boot
image(s).

Functionality is being added to work with the UEFI capsule driver in
u-boot. The metadata is read to gather information on the update bank,
which is the bank to which the firmware images would be flashed to. On
a successful completion of the update of all components, the active
bank field in the metadata is updated, to reflect the bank from which
the platform will boot on the subsequent boots.

Currently, the feature is being enabled on the STM32MP157C-DK2 and
Synquacer boards. The DK2 board boots a FIP image from a uSD card
partitioned with the GPT partioning scheme, while the Synquacer board
boots a FIP image from a MTD partitioned SPI NOR flash device.

This feature also requires changes in a previous stage of
bootloader, which parses the metadata and selects the bank to boot the
image(s) from. Support has being added in tf-a(BL2 stage) for the
STM32MP157C-DK2 board to boot the active bank images. These changes 
have been merged to the upstream tf-a repository.

The patch for adding a python test for the feature has been developed,
and was sent in the version 5 of the patches[3]. However, the test
script depends on adding support for the feature on MTD SPI NOR
devices, and that is being done as part of the Synquacer
patches. Hence these set of patches do not have the test script for
the feature. That will be added through the patches for adding support
for the feauture on Synquacer platform.

[1] - https://developer.arm.com/documentation/den0118/a
[2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
[3] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html

Changes since V7:
* Rephrased the error message in fwu_update_active_index as per
  suggestion from Ilias.
* Reworked the logic in fwu_get_image_alt_num() as per the suggestion
  from Ilias.
* Moved the API's fwu_plat_get_update_index() and
  fwu_plat_get_alt_num() as weak functions in common code as suggested
  by Ilias.
* Introduce trial_counter_update() to increment and delete the
  TrialStateCtr variable.
* Introduce in_trial_state() to check if the platform is booting in
  Trial State.
* Introduce a new function fwu_to_efi_error() and check for all errors
  returned by the fwu API's through this function, as suggested by
  Ilias.
* Call fwu_trial_state_ctr_start() only when the OS is supposed to
  accept/reject the updated images.
* Modify the logic to check the setting of both -A and -R options
  being passed to the tool, as suggested by Ilias.
* Handle the various review comments from Heinrich.

Sughosh Ganu (13):
  dt/bindings: Add bindings for GPT based FWU Metadata storage device
  FWU: Add FWU metadata structure and driver for accessing metadata
  FWU: Add FWU metadata access driver for GPT partitioned block devices
  stm32mp1: dk2: Add a node for the FWU metadata device
  stm32mp1: dk2: Add image information for capsule updates
  FWU: Add helper functions for accessing FWU metadata
  FWU: STM32MP1: Add support to read boot index from backup register
  FWU: Add boot time checks as highlighted by the FWU specification
  FWU: Add support for the FWU Multi Bank Update feature
  FWU: cmd: Add a command to read FWU metadata
  mkeficapsule: Add support for generating empty capsules
  mkeficapsule: Add support for setting OEM flags in capsule header
  FWU: doc: Add documentation for the FWU feature

 arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
 arch/arm/mach-stm32mp/include/mach/stm32.h    |   5 +
 board/st/stm32mp1/stm32mp1.c                  |  36 ++
 cmd/Kconfig                                   |   7 +
 cmd/Makefile                                  |   1 +
 cmd/fwu_mdata.c                               |  80 +++
 common/board_r.c                              |   5 +
 doc/develop/uefi/fwu_updates.rst              | 165 +++++++
 doc/develop/uefi/index.rst                    |   1 +
 doc/develop/uefi/uefi.rst                     |   2 +
 .../firmware/fwu-mdata-gpt.yaml               |  32 ++
 doc/mkeficapsule.1                            |  33 +-
 drivers/Kconfig                               |   2 +
 drivers/Makefile                              |   1 +
 drivers/fwu-mdata/Kconfig                     |  16 +
 drivers/fwu-mdata/Makefile                    |   7 +
 drivers/fwu-mdata/fwu-mdata-uclass.c          | 463 ++++++++++++++++++
 drivers/fwu-mdata/fwu_mdata_gpt_blk.c         | 410 ++++++++++++++++
 include/configs/stm32mp15_common.h            |   4 +
 include/dm/uclass-id.h                        |   1 +
 include/fwu.h                                 |  69 +++
 include/fwu_mdata.h                           |  67 +++
 lib/Kconfig                                   |   6 +
 lib/Makefile                                  |   1 +
 lib/efi_loader/efi_capsule.c                  | 213 +++++++-
 lib/efi_loader/efi_setup.c                    |   3 +-
 lib/fwu_updates/Kconfig                       |  31 ++
 lib/fwu_updates/Makefile                      |   7 +
 lib/fwu_updates/fwu.c                         | 210 ++++++++
 lib/fwu_updates/fwu_gpt.c                     | 104 ++++
 tools/eficapsule.h                            |   8 +
 tools/mkeficapsule.c                          | 109 ++++-
 32 files changed, 2085 insertions(+), 21 deletions(-)
 create mode 100644 cmd/fwu_mdata.c
 create mode 100644 doc/develop/uefi/fwu_updates.rst
 create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml
 create mode 100644 drivers/fwu-mdata/Kconfig
 create mode 100644 drivers/fwu-mdata/Makefile
 create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
 create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c
 create mode 100644 include/fwu.h
 create mode 100644 include/fwu_mdata.h
 create mode 100644 lib/fwu_updates/Kconfig
 create mode 100644 lib/fwu_updates/Makefile
 create mode 100644 lib/fwu_updates/fwu.c
 create mode 100644 lib/fwu_updates/fwu_gpt.c

-- 
2.34.1



^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v8 01/13] dt/bindings: Add bindings for GPT based FWU Metadata storage device
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

Add bindings needed for accessing the FWU metadata partitions. These
include the compatible string which point to the access method and the
actual device which stores the FWU metadata.

The current patch adds basic bindings needed for accessing the
metadata structure on GPT partitioned block devices.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
Changes since V7: None

 .../firmware/fwu-mdata-gpt.yaml               | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml

diff --git a/doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml b/doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml
new file mode 100644
index 0000000000..0735191ff1
--- /dev/null
+++ b/doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/fwu-mdata-gpt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: FWU metadata on device with GPT partitioned layout
+
+maintainers:
+ - Sughosh Ganu <sughosh.ganu@linaro.org>
+
+properties:
+  compatible:
+    items:
+      - const: u-boot,fwu-mdata-gpt
+
+  fwu-mdata-store:
+    maxItems: 1
+    description: Phandle of the device which contains the FWU medatata partition.
+
+required:
+  - compatible
+  - fwu-mdata-store
+
+additionalProperties: false
+
+examples:
+  - |
+    fwu-mdata {
+        compatible = "u-boot,fwu-mdata-gpt";
+        fwu-mdata-store = <&sdmmc1>;
+    };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 01/13] dt/bindings: Add bindings for GPT based FWU Metadata storage device Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-18  1:13   ` Simon Glass
  2022-08-17 12:43 ` [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

In the FWU Multi Bank Update feature, the information about the
updatable images is stored as part of the metadata, which is stored on
a dedicated partition. Add the metadata structure, and a driver model
uclass which provides functions to access the metadata. These are
generic API's, and implementations can be added based on parameters
like how the metadata partition is accessed and what type of storage
device houses the metadata.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
---
Changes since V7:
* Rephrased the error message in fwu_update_active_index as per
  suggestion from Ilias.
* Reworked the logic in fwu_get_image_alt_num() as per the suggestion
  from Ilias.

 drivers/Kconfig                      |   2 +
 drivers/Makefile                     |   1 +
 drivers/fwu-mdata/Kconfig            |   7 +
 drivers/fwu-mdata/Makefile           |   6 +
 drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
 include/dm/uclass-id.h               |   1 +
 include/fwu.h                        |  49 +++
 include/fwu_mdata.h                  |  67 ++++
 8 files changed, 596 insertions(+)
 create mode 100644 drivers/fwu-mdata/Kconfig
 create mode 100644 drivers/fwu-mdata/Makefile
 create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
 create mode 100644 include/fwu.h
 create mode 100644 include/fwu_mdata.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 8b6fead351..75ac149d31 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -44,6 +44,8 @@ source "drivers/fuzz/Kconfig"
 
 source "drivers/fpga/Kconfig"
 
+source "drivers/fwu-mdata/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/hwspinlock/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index eba9940231..70bbc2f5e0 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -84,6 +84,7 @@ obj-y += cache/
 obj-$(CONFIG_CPU) += cpu/
 obj-y += crypto/
 obj-$(CONFIG_FASTBOOT) += fastboot/
+obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/
 obj-y += misc/
 obj-$(CONFIG_MMC) += mmc/
 obj-$(CONFIG_NVME) += nvme/
diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
new file mode 100644
index 0000000000..d6a21c8e19
--- /dev/null
+++ b/drivers/fwu-mdata/Kconfig
@@ -0,0 +1,7 @@
+config DM_FWU_MDATA
+	bool "Driver support for accessing FWU Metadata"
+	depends on DM
+	help
+	  Enable support for accessing FWU Metadata partitions. The
+	  FWU Metadata partitions reside on the same storage device
+	  which contains the other FWU updatable firmware images.
diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
new file mode 100644
index 0000000000..e53a8c9983
--- /dev/null
+++ b/drivers/fwu-mdata/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (c) 2022, Linaro Limited
+#
+
+obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c
new file mode 100644
index 0000000000..6bf7fa1b03
--- /dev/null
+++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#define LOG_CATEGORY UCLASS_FWU_MDATA
+
+#include <common.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <fwu.h>
+#include <fwu_mdata.h>
+#include <log.h>
+#include <malloc.h>
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <u-boot/crc.h>
+
+#define IMAGE_ACCEPT_SET	BIT(0)
+#define IMAGE_ACCEPT_CLEAR	BIT(1)
+
+static int fwu_get_dev_ops(struct udevice **dev,
+			   const struct fwu_mdata_ops **ops)
+{
+	int ret;
+
+	ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev);
+	if (ret) {
+		log_debug("Cannot find fwu device\n");
+		return ret;
+	}
+
+	if ((*ops = device_get_ops(*dev)) == NULL) {
+		log_debug("Cannot get fwu device ops\n");
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+/**
+ * fwu_verify_mdata() - Verify the FWU metadata
+ * @mdata: FWU metadata structure
+ * @pri_part: FWU metadata partition is primary or secondary
+ *
+ * Verify the FWU metadata by computing the CRC32 for the metadata
+ * structure and comparing it against the CRC32 value stored as part
+ * of the structure.
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part)
+{
+	u32 calc_crc32;
+	void *buf;
+
+	buf = &mdata->version;
+	calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
+
+	if (calc_crc32 != mdata->crc32) {
+		log_err("crc32 check failed for %s FWU metadata partition\n",
+			pri_part ? "primary" : "secondary");
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fwu_get_active_index() - Get active_index from the FWU metadata
+ * @active_idx: active_index value to be read
+ *
+ * Read the active_index field from the FWU metadata and place it in
+ * the variable pointed to be the function argument.
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_get_active_index(u32 *active_idx)
+{
+	int ret;
+	struct fwu_mdata *mdata = NULL;
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret < 0) {
+		log_err("Unable to get valid FWU metadata\n");
+		goto out;
+	}
+
+	/*
+	 * Found the FWU metadata partition, now read the active_index
+	 * value
+	 */
+	*active_idx = mdata->active_index;
+	if (*active_idx > CONFIG_FWU_NUM_BANKS - 1) {
+		log_err("Active index value read is incorrect\n");
+		ret = -EINVAL;
+	}
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+/**
+ * fwu_update_active_index() - Update active_index from the FWU metadata
+ * @active_idx: active_index value to be updated
+ *
+ * Update the active_index field in the FWU metadata
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_update_active_index(u32 active_idx)
+{
+	int ret;
+	struct fwu_mdata *mdata = NULL;
+
+	if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
+		log_err("Invalid active index value\n");
+		return -1;
+	}
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret < 0) {
+		log_err("Unable to get valid FWU metadata\n");
+		goto out;
+	}
+
+	/*
+	 * Update the active index and previous_active_index fields
+	 * in the FWU metadata
+	 */
+	mdata->previous_active_index = mdata->active_index;
+	mdata->active_index = active_idx;
+
+	/*
+	 * Now write this updated FWU metadata to both the
+	 * FWU metadata partitions
+	 */
+	ret = fwu_update_mdata(mdata);
+	if (ret < 0) {
+		log_err("Failed to update FWU metadata partitions\n");
+		ret = -EIO;
+	}
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+/**
+ * fwu_get_image_alt_num() - Get the dfu alt number to be used for capsule update
+ * @image_type_id: pointer to the image GUID as passed in the capsule
+ * @update_bank: Bank to which the update is to be made
+ * @alt_num: The alt_num for the image
+ *
+ * Based on the GUID value passed in the capsule, along with the bank to which the
+ * image needs to be updated, get the dfu alt number which will be used for the
+ * capsule update
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
+			  int *alt_num)
+{
+	int ret, i;
+	efi_guid_t *image_guid;
+	struct udevice *dev = NULL;
+	struct fwu_mdata *mdata = NULL;
+	struct fwu_image_entry *img_entry;
+	const struct fwu_mdata_ops *ops = NULL;
+	struct fwu_image_bank_info *img_bank_info;
+
+	ret = fwu_get_dev_ops(&dev, &ops);
+	if (ret)
+		return ret;
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret) {
+		log_err("Unable to get valid FWU metadata\n");
+		goto out;
+	}
+
+	ret = -EINVAL;
+	/*
+	 * The FWU metadata has been read. Now get the image_uuid for the
+	 * image with the update_bank.
+	 */
+	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
+		if (!guidcmp(image_type_id,
+			     &mdata->img_entry[i].image_type_uuid)) {
+			img_entry = &mdata->img_entry[i];
+			img_bank_info = &img_entry->img_bank_info[update_bank];
+			image_guid = &img_bank_info->image_uuid;
+			ret = fwu_plat_get_alt_num(dev, image_guid, alt_num);
+			if (ret) {
+				log_err("alt_num not found for partition with GUID %pUs\n",
+					image_guid);
+			} else {
+				log_debug("alt_num %d for partition %pUs\n",
+					  *alt_num, image_guid);
+			}
+
+			goto out;
+		}
+	}
+
+	log_err("Partition with the image type %pUs not found\n",
+		image_type_id);
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+/**
+ * fwu_mdata_check() - Check if the FWU metadata is valid
+ *
+ * Validate both copies of the FWU metadata. If one of the copies
+ * has gone bad, restore it from the other bad copy.
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_mdata_check(void)
+{
+	int ret;
+	struct udevice *dev = NULL;
+	const struct fwu_mdata_ops *ops = NULL;
+
+	ret = fwu_get_dev_ops(&dev, &ops);
+	if (ret)
+		return ret;
+
+	if (!ops->mdata_check) {
+		log_err("mdata_check() method not defined\n");
+		return -ENOSYS;
+	}
+
+	return ops->mdata_check(dev);
+}
+
+/**
+ * fwu_revert_boot_index() - Revert the active index in the FWU metadata
+ *
+ * Revert the active_index value in the FWU metadata, by swapping the values
+ * of active_index and previous_active_index in both copies of the
+ * FWU metadata.
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_revert_boot_index(void)
+{
+	int ret;
+	u32 cur_active_index;
+	struct fwu_mdata *mdata = NULL;
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret < 0) {
+		log_err("Unable to get valid FWU metadata\n");
+		goto out;
+	}
+
+	/*
+	 * Swap the active index and previous_active_index fields
+	 * in the FWU metadata
+	 */
+	cur_active_index = mdata->active_index;
+	mdata->active_index = mdata->previous_active_index;
+	mdata->previous_active_index = cur_active_index;
+
+	/*
+	 * Now write this updated FWU metadata to both the
+	 * FWU metadata partitions
+	 */
+	ret = fwu_update_mdata(mdata);
+	if (ret < 0) {
+		log_err("Failed to update FWU metadata partitions\n");
+		ret = -EIO;
+	}
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+/**
+ * fwu_set_clear_image_accept() - Set or Clear the Acceptance bit for the image
+ * @img_type_id: GUID of the image type for which the accepted bit is to be
+ *               set or cleared
+ * @bank: Bank of which the image's Accept bit is to be set or cleared
+ * @action: Action which specifies whether image's Accept bit is to be set or
+ *          cleared
+ *
+ * Set/Clear the accepted bit for the image specified by the img_guid parameter.
+ * This indicates acceptance or rejection of image for subsequent boots by some
+ * governing component like OS(or firmware).
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+static int fwu_set_clear_image_accept(efi_guid_t *img_type_id,
+				      u32 bank, u8 action)
+{
+	int ret, i;
+	struct fwu_mdata *mdata = NULL;
+	struct fwu_image_entry *img_entry;
+	struct fwu_image_bank_info *img_bank_info;
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret < 0) {
+		log_err("Unable to get valid FWU metadata\n");
+		goto out;
+	}
+
+	img_entry = &mdata->img_entry[0];
+	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
+		if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) {
+			img_bank_info = &img_entry[i].img_bank_info[bank];
+			if (action == IMAGE_ACCEPT_SET)
+				img_bank_info->accepted |= FWU_IMAGE_ACCEPTED;
+			else
+				img_bank_info->accepted = 0;
+
+			ret = fwu_update_mdata(mdata);
+			goto out;
+		}
+	}
+
+	/* Image not found */
+	ret = -EINVAL;
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+/**
+ * fwu_accept_image() - Set the Acceptance bit for the image
+ * @img_type_id: GUID of the image type for which the accepted bit is to be
+ *               cleared
+ * @bank: Bank of which the image's Accept bit is to be set
+ *
+ * Set the accepted bit for the image specified by the img_guid parameter. This
+ * indicates acceptance of image for subsequent boots by some governing component
+ * like OS(or firmware).
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
+{
+	return fwu_set_clear_image_accept(img_type_id, bank,
+					  IMAGE_ACCEPT_SET);
+}
+
+/**
+ * fwu_clear_accept_image() - Clear the Acceptance bit for the image
+ * @img_type_id: GUID of the image type for which the accepted bit is to be
+ *               cleared
+ * @bank: Bank of which the image's Accept bit is to be cleared
+ *
+ * Clear the accepted bit for the image type specified by the img_type_id parameter.
+ * This function is called after the image has been updated. The accepted bit is
+ * cleared to be set subsequently after passing the image acceptance criteria, by
+ * either the OS(or firmware)
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
+{
+	return fwu_set_clear_image_accept(img_type_id, bank,
+					  IMAGE_ACCEPT_CLEAR);
+}
+
+/**
+ * fwu_get_mdata() - Get a FWU metadata copy
+ * @mdata: Copy of the FWU metadata
+ *
+ * Get a valid copy of the FWU metadata.
+ *
+ * Note: This function is to be called first when modifying any fields
+ * in the metadata. The sequence of calls to modify any field in the
+ * metadata would  be 1) fwu_get_mdata 2) Modify metadata, followed by
+ * 3) fwu_update_mdata
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_get_mdata(struct fwu_mdata **mdata)
+{
+	int ret;
+	struct udevice *dev = NULL;
+	const struct fwu_mdata_ops *ops = NULL;
+
+	ret = fwu_get_dev_ops(&dev, &ops);
+	if (ret)
+		return ret;
+
+	if (!ops->get_mdata) {
+		log_err("get_mdata() method not defined\n");
+		return -ENOSYS;
+	}
+
+	return ops->get_mdata(dev, mdata);
+}
+
+/**
+ * fwu_update_mdata() - Update the FWU metadata
+ * @mdata: Copy of the FWU metadata
+ *
+ * Update the FWU metadata structure by writing to the
+ * FWU metadata partitions.
+ *
+ * Note: This function is not to be called directly to update the
+ * metadata fields. The sequence of function calls should be
+ * 1) fwu_get_mdata() 2) Modify the medata fields 3) fwu_update_mdata()
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_update_mdata(struct fwu_mdata *mdata)
+{
+	int ret;
+	void *buf;
+	struct udevice *dev = NULL;
+	const struct fwu_mdata_ops *ops = NULL;
+
+	ret = fwu_get_dev_ops(&dev, &ops);
+	if (ret)
+		return ret;
+
+	if (!ops->update_mdata) {
+		log_err("get_mdata() method not defined\n");
+		return -ENOSYS;
+	}
+
+	/*
+	 * Calculate the crc32 for the updated FWU metadata
+	 * and put the updated value in the FWU metadata crc32
+	 * field
+	 */
+	buf = &mdata->version;
+	mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
+
+	return ops->update_mdata(dev, mdata);
+}
+
+UCLASS_DRIVER(fwu_mdata) = {
+	.id		= UCLASS_FWU_MDATA,
+	.name		= "fwu-mdata",
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43871..598a8c10a0 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -58,6 +58,7 @@ enum uclass_id {
 	UCLASS_FIRMWARE,	/* Firmware */
 	UCLASS_FUZZING_ENGINE,	/* Fuzzing engine */
 	UCLASS_FS_FIRMWARE_LOADER,		/* Generic loader */
+	UCLASS_FWU_MDATA,	/* FWU Metadata Access */
 	UCLASS_GPIO,		/* Bank of general-purpose I/O pins */
 	UCLASS_HASH,		/* Hash device */
 	UCLASS_HWSPINLOCK,	/* Hardware semaphores */
diff --git a/include/fwu.h b/include/fwu.h
new file mode 100644
index 0000000000..e03cfff800
--- /dev/null
+++ b/include/fwu.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#if !defined _FWU_H_
+#define _FWU_H_
+
+#include <blk.h>
+#include <efi.h>
+
+#include <linux/types.h>
+
+struct fwu_mdata;
+struct udevice;
+
+/**
+ * @mdata_check: check the validity of the FWU metadata partitions
+ * @get_mdata() - Get a FWU metadata copy
+ * @update_mdata() - Update the FWU metadata copy
+ */
+struct fwu_mdata_ops {
+	int (*mdata_check)(struct udevice *dev);
+
+	int (*get_mdata)(struct udevice *dev, struct fwu_mdata **mdata);
+
+	int (*update_mdata)(struct udevice *dev, struct fwu_mdata *mdata);
+};
+
+#define FWU_MDATA_VERSION	0x1
+
+#define FWU_MDATA_GUID \
+	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
+		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
+
+int fwu_get_mdata(struct fwu_mdata **mdata);
+int fwu_update_mdata(struct fwu_mdata *mdata);
+int fwu_get_active_index(u32 *active_idx);
+int fwu_update_active_index(u32 active_idx);
+int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
+			  int *alt_num);
+int fwu_mdata_check(void);
+int fwu_revert_boot_index(void);
+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_alt_num(struct udevice *dev, efi_guid_t *image_guid,
+			 int *alt_num);
+#endif /* _FWU_H_ */
diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
new file mode 100644
index 0000000000..72e3edab43
--- /dev/null
+++ b/include/fwu_mdata.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#if !defined _FWU_MDATA_H_
+#define _FWU_MDATA_H_
+
+#include <efi.h>
+
+/**
+ * struct fwu_image_bank_info - firmware image information
+ * @image_uuid: Guid value of the image in this bank
+ * @accepted: Acceptance status of the image
+ * @reserved: Reserved
+ *
+ * The structure contains image specific fields which are
+ * used to identify the image and to specify the image's
+ * acceptance status
+ */
+struct fwu_image_bank_info {
+	efi_guid_t  image_uuid;
+	uint32_t accepted;
+	uint32_t reserved;
+} __attribute__((__packed__));
+
+/**
+ * struct fwu_image_entry - information for a particular type of image
+ * @image_type_uuid: Guid value for identifying the image type
+ * @location_uuid: Guid of the storage volume where the image is located
+ * @img_bank_info: Array containing properties of images
+ *
+ * This structure contains information on various types of updatable
+ * firmware images. Each image type then contains an array of image
+ * information per bank.
+ */
+struct fwu_image_entry {
+	efi_guid_t image_type_uuid;
+	efi_guid_t location_uuid;
+	struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS];
+} __attribute__((__packed__));
+
+/**
+ * struct fwu_mdata - FWU metadata structure for multi-bank updates
+ * @crc32: crc32 value for the FWU metadata
+ * @version: FWU metadata version
+ * @active_index: Index of the bank currently used for booting images
+ * @previous_active_inde: Index of the bank used before the current bank
+ *                        being used for booting
+ * @img_entry: Array of information on various firmware images that can
+ *             be updated
+ *
+ * This structure is used to store all the needed information for performing
+ * multi bank updates on the platform. This contains info on the bank being
+ * used to boot along with the information needed for identification of
+ * individual images
+ */
+struct fwu_mdata {
+	uint32_t crc32;
+	uint32_t version;
+	uint32_t active_index;
+	uint32_t previous_active_index;
+
+	struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
+} __attribute__((__packed__));
+
+#endif /* _FWU_MDATA_H_ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 01/13] dt/bindings: Add bindings for GPT based FWU Metadata storage device Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-18  3:21   ` Simon Glass
  2022-08-17 12:43 ` [PATCH v8 04/13] stm32mp1: dk2: Add a node for the FWU metadata device Sughosh Ganu
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

In the FWU Multi Bank Update feature, the information about the
updatable images is stored as part of the metadata, on a separate
partition. Add a driver for reading from and writing to the metadata
when the updatable images and the metadata are stored on a block
device which is formated with GPT based partition scheme.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
---
Changes since V7: None

 drivers/fwu-mdata/Kconfig             |   9 +
 drivers/fwu-mdata/Makefile            |   1 +
 drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410 ++++++++++++++++++++++++++
 include/fwu.h                         |   5 +
 4 files changed, 425 insertions(+)
 create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c

diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
index d6a21c8e19..d5edef19d6 100644
--- a/drivers/fwu-mdata/Kconfig
+++ b/drivers/fwu-mdata/Kconfig
@@ -5,3 +5,12 @@ config DM_FWU_MDATA
 	  Enable support for accessing FWU Metadata partitions. The
 	  FWU Metadata partitions reside on the same storage device
 	  which contains the other FWU updatable firmware images.
+
+config FWU_MDATA_GPT_BLK
+	bool "FWU Metadata access for GPT partitioned Block devices"
+	select PARTITION_TYPE_GUID
+	select PARTITION_UUIDS
+	depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION
+	help
+	  Enable support for accessing FWU Metadata on GPT partitioned
+	  block devices.
diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
index e53a8c9983..313049f67a 100644
--- a/drivers/fwu-mdata/Makefile
+++ b/drivers/fwu-mdata/Makefile
@@ -4,3 +4,4 @@
 #
 
 obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
+obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o
diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
new file mode 100644
index 0000000000..f694c4369b
--- /dev/null
+++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#define LOG_CATEGORY UCLASS_FWU_MDATA
+
+#include <blk.h>
+#include <dm.h>
+#include <efi_loader.h>
+#include <fwu.h>
+#include <fwu_mdata.h>
+#include <log.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <part.h>
+#include <part_efi.h>
+
+#include <dm/device-internal.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <u-boot/crc.h>
+
+#define PRIMARY_PART		BIT(0)
+#define SECONDARY_PART		BIT(1)
+#define BOTH_PARTS		(PRIMARY_PART | SECONDARY_PART)
+
+#define MDATA_READ		BIT(0)
+#define MDATA_WRITE		BIT(1)
+
+static int gpt_get_mdata_partitions(struct blk_desc *desc,
+				    u16 *primary_mpart,
+				    u16 *secondary_mpart)
+{
+	int i, ret;
+	u32 mdata_parts;
+	efi_guid_t part_type_guid;
+	struct disk_partition info;
+	const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID;
+
+	mdata_parts = 0;
+	for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
+		if (part_get_info(desc, i, &info))
+			continue;
+		uuid_str_to_bin(info.type_guid, part_type_guid.b,
+				UUID_STR_FORMAT_GUID);
+
+		if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) {
+			++mdata_parts;
+			if (!*primary_mpart)
+				*primary_mpart = i;
+			else
+				*secondary_mpart = i;
+		}
+	}
+
+	if (mdata_parts != 2) {
+		log_err("Expect two copies of the FWU metadata instead of %d\n",
+			mdata_parts);
+		ret = -EINVAL;
+	} else {
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int gpt_get_mdata_disk_part(struct blk_desc *desc,
+				   struct disk_partition *info,
+				   u32 part_num)
+{
+	int ret;
+	char *mdata_guid_str = "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23";
+
+	ret = part_get_info(desc, part_num, info);
+	if (ret < 0) {
+		log_err("Unable to get the partition info for the FWU metadata part %d",
+			part_num);
+		return -1;
+	}
+
+	/* Check that it is indeed the FWU metadata partition */
+	if (!strncmp(info->type_guid, mdata_guid_str, UUID_STR_LEN)) {
+		/* Found the FWU metadata partition */
+		return 0;
+	}
+
+	return -1;
+}
+
+static int gpt_read_write_mdata(struct blk_desc *desc,
+				struct fwu_mdata *mdata,
+				u8 access, u32 part_num)
+{
+	int ret;
+	u32 len, blk_start, blkcnt;
+	struct disk_partition info;
+
+	ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1,
+				     desc->blksz);
+
+	ret = gpt_get_mdata_disk_part(desc, &info, part_num);
+	if (ret < 0) {
+		printf("Unable to get the FWU metadata partition\n");
+		return -ENODEV;
+	}
+
+	len = sizeof(*mdata);
+	blkcnt = BLOCK_CNT(len, desc);
+	if (blkcnt > info.size) {
+		log_err("Block count exceeds FWU metadata partition size\n");
+		return -ERANGE;
+	}
+
+	blk_start = info.start;
+	if (access == MDATA_READ) {
+		if (blk_dread(desc, blk_start, blkcnt, mdata_aligned) != blkcnt) {
+			log_err("Error reading FWU metadata from the device\n");
+			return -EIO;
+		}
+		memcpy(mdata, mdata_aligned, sizeof(struct fwu_mdata));
+	} else {
+		if (blk_dwrite(desc, blk_start, blkcnt, mdata) != blkcnt) {
+			log_err("Error writing FWU metadata to the device\n");
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int gpt_read_mdata(struct blk_desc *desc,
+			  struct fwu_mdata *mdata, u32 part_num)
+{
+	return gpt_read_write_mdata(desc, mdata, MDATA_READ, part_num);
+}
+
+static int gpt_write_mdata_partition(struct blk_desc *desc,
+					struct fwu_mdata *mdata,
+					u32 part_num)
+{
+	return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, part_num);
+}
+
+static int fwu_gpt_update_mdata(struct udevice *dev, struct fwu_mdata *mdata)
+{
+	int ret;
+	struct blk_desc *desc;
+	u16 primary_mpart = 0, secondary_mpart = 0;
+	struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+
+	desc = dev_get_uclass_plat(priv->blk_dev);
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	ret = gpt_get_mdata_partitions(desc, &primary_mpart,
+				       &secondary_mpart);
+
+	if (ret < 0) {
+		log_err("Error getting the FWU metadata partitions\n");
+		return -ENODEV;
+	}
+
+	/* First write the primary partition*/
+	ret = gpt_write_mdata_partition(desc, mdata, primary_mpart);
+	if (ret < 0) {
+		log_err("Updating primary FWU metadata partition failed\n");
+		return ret;
+	}
+
+	/* And now the replica */
+	ret = gpt_write_mdata_partition(desc, mdata, secondary_mpart);
+	if (ret < 0) {
+		log_err("Updating secondary FWU metadata partition failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata)
+{
+	int ret;
+	u16 primary_mpart = 0, secondary_mpart = 0;
+
+	ret = gpt_get_mdata_partitions(desc, &primary_mpart,
+				       &secondary_mpart);
+
+	if (ret < 0) {
+		log_err("Error getting the FWU metadata partitions\n");
+		return -ENODEV;
+	}
+
+	*mdata = malloc(sizeof(struct fwu_mdata));
+	if (!*mdata) {
+		log_err("Unable to allocate memory for reading FWU metadata\n");
+		return -ENOMEM;
+	}
+
+	ret = gpt_read_mdata(desc, *mdata, primary_mpart);
+	if (ret < 0) {
+		log_err("Failed to read the FWU metadata from the device\n");
+		return -EIO;
+	}
+
+	ret = fwu_verify_mdata(*mdata, 1);
+	if (!ret)
+		return 0;
+
+	/*
+	 * Verification of the primary FWU metadata copy failed.
+	 * Try to read the replica.
+	 */
+	memset(*mdata, 0, sizeof(struct fwu_mdata));
+	ret = gpt_read_mdata(desc, *mdata, secondary_mpart);
+	if (ret < 0) {
+		log_err("Failed to read the FWU metadata from the device\n");
+		return -EIO;
+	}
+
+	ret = fwu_verify_mdata(*mdata, 0);
+	if (!ret)
+		return 0;
+
+	/* Both the FWU metadata copies are corrupted. */
+	return -1;
+}
+
+static int gpt_check_mdata_validity(struct udevice *dev)
+{
+	int ret;
+	struct blk_desc *desc;
+	struct fwu_mdata pri_mdata;
+	struct fwu_mdata secondary_mdata;
+	u16 primary_mpart = 0, secondary_mpart = 0;
+	u16 valid_partitions, invalid_partitions;
+	struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+
+	desc = dev_get_uclass_plat(priv->blk_dev);
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Two FWU metadata partitions are expected.
+	 * If we don't have two, user needs to create
+	 * them first
+	 */
+	valid_partitions = 0;
+	ret = gpt_get_mdata_partitions(desc, &primary_mpart,
+				       &secondary_mpart);
+
+	if (ret < 0) {
+		log_err("Error getting the FWU metadata partitions\n");
+		return -ENODEV;
+	}
+
+	ret = gpt_read_mdata(desc, &pri_mdata, primary_mpart);
+	if (ret < 0) {
+		log_err("Failed to read the FWU metadata from the device\n");
+		goto secondary_read;
+	}
+
+	ret = fwu_verify_mdata(&pri_mdata, 1);
+	if (!ret)
+		valid_partitions |= PRIMARY_PART;
+
+secondary_read:
+	/* Now check the secondary partition */
+	ret = gpt_read_mdata(desc, &secondary_mdata, secondary_mpart);
+	if (ret < 0) {
+		log_err("Failed to read the FWU metadata from the device\n");
+		goto mdata_restore;
+	}
+
+	ret = fwu_verify_mdata(&secondary_mdata, 0);
+	if (!ret)
+		valid_partitions |= SECONDARY_PART;
+
+mdata_restore:
+	if (valid_partitions == (PRIMARY_PART | SECONDARY_PART)) {
+		ret = -1;
+		/*
+		 * Before returning, check that both the
+		 * FWU metadata copies are the same. If not,
+		 * the FWU metadata copies need to be
+		 * re-populated.
+		 */
+		if (!memcmp(&pri_mdata, &secondary_mdata,
+			    sizeof(struct fwu_mdata))) {
+			ret = 0;
+		} else {
+			log_err("Both FWU metadata copies are valid but do not match. Please check!\n");
+		}
+		goto out;
+	}
+
+	ret = -1;
+	if (!(valid_partitions & BOTH_PARTS))
+		goto out;
+
+	invalid_partitions = valid_partitions ^ BOTH_PARTS;
+	ret = gpt_write_mdata_partition(desc,
+					(invalid_partitions == PRIMARY_PART) ?
+					&secondary_mdata : &pri_mdata,
+					(invalid_partitions == PRIMARY_PART) ?
+					primary_mpart : secondary_mpart);
+
+	if (ret < 0)
+		log_err("Restoring %s FWU metadata partition failed\n",
+			(invalid_partitions == PRIMARY_PART) ?
+			"primary" : "secondary");
+
+out:
+	return ret;
+}
+
+static int fwu_gpt_mdata_check(struct udevice *dev)
+{
+	/*
+	 * Check if both the copies of the FWU metadata are
+	 * valid. If one has gone bad, restore it from the
+	 * other good copy.
+	 */
+	return gpt_check_mdata_validity(dev);
+}
+
+static int fwu_gpt_get_mdata(struct udevice *dev, struct fwu_mdata **mdata)
+{
+	struct blk_desc *desc;
+	struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+
+	desc = dev_get_uclass_plat(priv->blk_dev);
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return gpt_get_mdata(desc, mdata);
+}
+
+static int fwu_get_mdata_device(struct udevice *dev, struct udevice **mdata_dev)
+{
+	u32 phandle;
+	int ret, size;
+	struct udevice *parent, *child;
+	const fdt32_t *phandle_p = NULL;
+
+	phandle_p = dev_read_prop(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),
+					  &parent);
+	if (ret)
+		return ret;
+
+	ret = -ENODEV;
+	for (device_find_first_child(parent, &child); child;
+	     device_find_next_child(&child)) {
+		if (device_get_uclass_id(child) == UCLASS_BLK) {
+			*mdata_dev = child;
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
+{
+	int ret;
+	struct udevice *mdata_dev = NULL;
+	struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+
+	ret = fwu_get_mdata_device(dev, &mdata_dev);
+	if (ret)
+		return ret;
+
+	priv->blk_dev = mdata_dev;
+
+	return 0;
+}
+
+static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
+	.mdata_check = fwu_gpt_mdata_check,
+	.get_mdata = fwu_gpt_get_mdata,
+	.update_mdata = fwu_gpt_update_mdata,
+};
+
+static const struct udevice_id fwu_mdata_ids[] = {
+	{ .compatible = "u-boot,fwu-mdata-gpt" },
+	{ }
+};
+
+U_BOOT_DRIVER(fwu_mdata_gpt_blk) = {
+	.name		= "fwu-mdata-gpt-blk",
+	.id		= UCLASS_FWU_MDATA,
+	.of_match	= fwu_mdata_ids,
+	.ops		= &fwu_gpt_blk_ops,
+	.probe		= fwu_mdata_gpt_blk_probe,
+	.priv_auto	= sizeof(struct fwu_mdata_gpt_blk_priv),
+};
diff --git a/include/fwu.h b/include/fwu.h
index e03cfff800..8259c75d12 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -14,6 +14,10 @@
 struct fwu_mdata;
 struct udevice;
 
+struct fwu_mdata_gpt_blk_priv {
+	struct udevice *blk_dev;
+};
+
 /**
  * @mdata_check: check the validity of the FWU metadata partitions
  * @get_mdata() - Get a FWU metadata copy
@@ -39,6 +43,7 @@ int fwu_get_active_index(u32 *active_idx);
 int fwu_update_active_index(u32 active_idx);
 int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
 			  int *alt_num);
+int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part);
 int fwu_mdata_check(void);
 int fwu_revert_boot_index(void);
 int fwu_accept_image(efi_guid_t *img_type_id, u32 bank);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 04/13] stm32mp1: dk2: Add a node for the FWU metadata device
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (2 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates Sughosh Ganu
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

The FWU metadata structure is accessed through the driver model
interface. On the stm32mp157c-dk2 board, the FWU metadata is stored on
the uSD card. Add the fwu-mdata node on the u-boot specifc dtsi file
for accessing the metadata structure.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since V7: None

 arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
index 06ef3a4095..24f86209db 100644
--- a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
@@ -4,3 +4,10 @@
  */
 
 #include "stm32mp157a-dk1-u-boot.dtsi"
+
+/ {
+	fwu-mdata {
+		compatible = "u-boot,fwu-mdata-gpt";
+		fwu-mdata-store = <&sdmmc1>;
+	};
+};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (3 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 04/13] stm32mp1: dk2: Add a node for the FWU metadata device Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-18  8:05   ` Yann Gautier
  2022-08-17 12:43 ` [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata Sughosh Ganu
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

Enabling capsule update functionality on the platform requires
populating information on the images that are to be updated using the
functionality. Do so for the DK2 board.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since V7: None

 board/st/stm32mp1/stm32mp1.c       | 23 +++++++++++++++++++++++
 include/configs/stm32mp15_common.h |  4 ++++
 2 files changed, 27 insertions(+)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 9496890d16..0fda8f150d 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -11,6 +11,7 @@
 #include <clk.h>
 #include <config.h>
 #include <dm.h>
+#include <efi_loader.h>
 #include <env.h>
 #include <env_internal.h>
 #include <fdt_simplefb.h>
@@ -87,6 +88,16 @@
 #define USB_START_LOW_THRESHOLD_UV	1230000
 #define USB_START_HIGH_THRESHOLD_UV	2150000
 
+#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
+struct efi_fw_image fw_images[1];
+
+struct efi_capsule_update_info update_info = {
+	.images = fw_images,
+};
+
+u8 num_image_type_guids = ARRAY_SIZE(fw_images);
+#endif /* EFI_HAVE_CAPSULE_SUPPORT */
+
 int board_early_init_f(void)
 {
 	/* nothing to do, only used in SPL */
@@ -670,6 +681,18 @@ int board_init(void)
 
 	setup_led(LEDST_ON);
 
+#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
+	if (board_is_stm32mp15x_dk2()) {
+		efi_guid_t image_type_guid = STM32MP15_DK2_FIP_IMAGE_GUID;
+		guidcpy(&fw_images[0].image_type_id, &image_type_guid);
+		fw_images[0].fw_name = u"STM32MP15-DK2-FIP";
+		/*
+		 * For FWU multi bank update, the image
+		 * index will be computed at runtime
+		 */
+		fw_images[0].image_index = 0;
+	}
+#endif
 	return 0;
 }
 
diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h
index c5412ffeb3..6ab10d8ce5 100644
--- a/include/configs/stm32mp15_common.h
+++ b/include/configs/stm32mp15_common.h
@@ -34,6 +34,10 @@
 #define CONFIG_SERVERIP                 192.168.1.1
 #endif
 
+#define STM32MP15_DK2_FIP_IMAGE_GUID \
+	EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \
+		 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5)
+
 /*****************************************************************************/
 #ifdef CONFIG_DISTRO_DEFAULTS
 /*****************************************************************************/
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (4 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 17:00   ` Jassi Brar
  2022-08-18 17:50   ` Simon Glass
  2022-08-17 12:43 ` [PATCH v8 07/13] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
                   ` (6 subsequent siblings)
  12 siblings, 2 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

Add weak functions for getting the update index value and dfu
alternate number needed for FWU Multi Bank update
functionality.

The current implementation for getting the update index value is for
platforms with 2 banks. If a platform supports more than 2 banks, it
can implement it's own function. The function to get the dfu alternate
number has been added for platforms with GPT partitioned storage
devices. Platforms with other storage partition scheme need to
implement their own function.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
---
Changes since V7:
* Moved the API's fwu_plat_get_update_index() and
  fwu_plat_get_alt_num() as weak functions in common code as suggested
  by Ilias.

 include/fwu.h             |   1 +
 lib/fwu_updates/Makefile  |   7 +++
 lib/fwu_updates/fwu.c     |  22 ++++++++
 lib/fwu_updates/fwu_gpt.c | 104 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+)
 create mode 100644 lib/fwu_updates/Makefile
 create mode 100644 lib/fwu_updates/fwu.c
 create mode 100644 lib/fwu_updates/fwu_gpt.c

diff --git a/include/fwu.h b/include/fwu.h
index 8259c75d12..f14175cc9a 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -51,4 +51,5 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank);
 
 int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
 			 int *alt_num);
+int fwu_plat_get_update_index(u32 *update_idx);
 #endif /* _FWU_H_ */
diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile
new file mode 100644
index 0000000000..1993088e5b
--- /dev/null
+++ b/lib/fwu_updates/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (c) 2022, Linaro Limited
+#
+
+obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o
+obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
new file mode 100644
index 0000000000..9808036eec
--- /dev/null
+++ b/lib/fwu_updates/fwu.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <fwu.h>
+#include <fwu_mdata.h>
+
+__weak int fwu_plat_get_update_index(u32 *update_idx)
+{
+	int ret;
+	u32 active_idx;
+
+	ret = fwu_get_active_index(&active_idx);
+
+	if (ret < 0)
+		return -1;
+
+	*update_idx = active_idx ^= 0x1;
+
+	return ret;
+}
diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c
new file mode 100644
index 0000000000..b7ccca3645
--- /dev/null
+++ b/lib/fwu_updates/fwu_gpt.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <blk.h>
+#include <dfu.h>
+#include <efi.h>
+#include <efi_loader.h>
+#include <fwu.h>
+#include <log.h>
+#include <part.h>
+
+#include <linux/errno.h>
+
+static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t *image_guid)
+{
+	int i;
+	struct disk_partition info;
+	efi_guid_t unique_part_guid;
+
+	for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
+		if (part_get_info(desc, i, &info))
+			continue;
+		uuid_str_to_bin(info.uuid, unique_part_guid.b,
+				UUID_STR_FORMAT_GUID);
+
+		if (!guidcmp(&unique_part_guid, image_guid))
+			return i;
+	}
+
+	log_err("No partition found with image_guid %pUs\n", image_guid);
+	return -ENOENT;
+}
+
+static int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t *image_guid,
+			       int *alt_num, unsigned char dfu_dev)
+{
+	int ret = -1;
+	int i, part, dev_num;
+	int nalt;
+	struct dfu_entity *dfu;
+
+	dev_num = desc->devnum;
+	part = get_gpt_dfu_identifier(desc, image_guid);
+	if (part < 0)
+		return -ENOENT;
+
+	dfu_init_env_entities(NULL, NULL);
+
+	nalt = 0;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		nalt++;
+	}
+
+	if (!nalt) {
+		log_warning("No entities in dfu_alt_info\n");
+		dfu_free_entities();
+		return -ENOENT;
+	}
+
+	for (i = 0; i < nalt; i++) {
+		dfu = dfu_get_entity(i);
+
+		if (!dfu)
+			continue;
+
+		/*
+		 * Currently, Multi Bank update
+		 * feature is being supported
+		 * only on GPT partitioned
+		 * MMC/SD devices.
+		 */
+		if (dfu->dev_type != dfu_dev)
+			continue;
+
+		if (dfu->layout == DFU_RAW_ADDR &&
+		    dfu->data.mmc.dev_num == dev_num &&
+		    dfu->data.mmc.part == part) {
+			*alt_num = dfu->alt;
+			ret = 0;
+			break;
+		}
+	}
+
+	dfu_free_entities();
+
+	return ret;
+}
+
+__weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
+				int *alt_num)
+{
+	struct blk_desc *desc;
+	struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
+
+	desc = dev_get_uclass_plat(priv->blk_dev);
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return fwu_gpt_get_alt_num(desc, image_guid, alt_num, DFU_DEV_MMC);
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 07/13] FWU: STM32MP1: Add support to read boot index from backup register
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (5 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

The FWU Multi Bank Update feature allows the platform to boot the
firmware images from one of the partitions(banks). The first stage
bootloader(fsbl) passes the value of the boot index, i.e. the bank
from which the firmware images were booted from to U-Boot. On the
STM32MP157C-DK2 board, this value is passed through one of the SoC's
backup register. Add a function to read the boot index value from the
backup register.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since V7: None

 arch/arm/mach-stm32mp/include/mach/stm32.h |  5 +++++
 board/st/stm32mp1/stm32mp1.c               | 13 +++++++++++++
 include/fwu.h                              |  1 +
 3 files changed, 19 insertions(+)

diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index c70375a723..c85ae6a34e 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -112,11 +112,16 @@ enum boot_device {
 #ifdef CONFIG_STM32MP15x
 #define TAMP_BACKUP_MAGIC_NUMBER	TAMP_BACKUP_REGISTER(4)
 #define TAMP_BACKUP_BRANCH_ADDRESS	TAMP_BACKUP_REGISTER(5)
+#define TAMP_FWU_BOOT_INFO_REG		TAMP_BACKUP_REGISTER(10)
 #define TAMP_COPRO_RSC_TBL_ADDRESS	TAMP_BACKUP_REGISTER(17)
 #define TAMP_COPRO_STATE		TAMP_BACKUP_REGISTER(18)
 #define TAMP_BOOT_CONTEXT		TAMP_BACKUP_REGISTER(20)
 #define TAMP_BOOTCOUNT			TAMP_BACKUP_REGISTER(21)
 
+#define TAMP_FWU_BOOT_IDX_MASK		GENMASK(3, 0)
+
+#define TAMP_FWU_BOOT_IDX_OFFSET	0
+
 #define TAMP_COPRO_STATE_OFF		0
 #define TAMP_COPRO_STATE_INIT		1
 #define TAMP_COPRO_STATE_CRUN		2
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 0fda8f150d..0a63703312 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -966,3 +966,16 @@ static void board_copro_image_process(ulong fw_image, size_t fw_size)
 }
 
 U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process);
+
+#if defined(CONFIG_FWU_MULTI_BANK_UPDATE)
+
+#include <fwu.h>
+
+void fwu_plat_get_bootidx(void *boot_idx)
+{
+	u32 *bootidx = boot_idx;
+
+	*bootidx = (readl(TAMP_FWU_BOOT_INFO_REG) >>
+		    TAMP_FWU_BOOT_IDX_OFFSET) & TAMP_FWU_BOOT_IDX_MASK;
+}
+#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
diff --git a/include/fwu.h b/include/fwu.h
index f14175cc9a..cfc9aafc7d 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -49,6 +49,7 @@ int fwu_revert_boot_index(void);
 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);
 
+void fwu_plat_get_bootidx(void *boot_idx);
 int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
 			 int *alt_num);
 int fwu_plat_get_update_index(u32 *update_idx);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (6 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 07/13] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-18  3:21   ` Simon Glass
  2022-08-17 12:43 ` [PATCH v8 09/13] FWU: Add support for the FWU Multi Bank Update feature Sughosh Ganu
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

The FWU Multi Bank Update specification requires the Update Agent to
carry out certain checks at the time of platform boot. The Update
Agent is the component which is responsible for updating the firmware
components and maintaining and keeping the metadata in sync.

The spec requires that the Update Agent perform the following checks
at the time of boot
* Sanity check of both the metadata copies maintained by the platform.
* Get the boot index passed to U-Boot by the prior stage bootloader
  and use this value for metadata bookkeeping.
* Check if the system is booting in Trial State. If the system boots
  in the Trial State for more than a specified number of boot counts,
  change the Active Bank to be booting the platform from.

Add these checks in the board initialisation sequence, invoked after
relocation.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V7:
* Introduce trial_counter_update() to increment and delete the
  TrialStateCtr variable.
* Introduce in_trial_state() to check if the platform is booting in
  Trial State.

 common/board_r.c      |   5 ++
 include/fwu.h         |   3 +
 lib/fwu_updates/fwu.c | 175 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 183 insertions(+)

diff --git a/common/board_r.c b/common/board_r.c
index 56eb60fa27..425644dda7 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -18,6 +18,7 @@
 #ifdef CONFIG_MTD_NOR_FLASH
 #include <flash.h>
 #endif
+#include <fwu.h>
 #include <hang.h>
 #include <image.h>
 #include <irq_func.h>
@@ -788,6 +789,10 @@ static init_fnc_t init_sequence_r[] = {
 #if defined(CONFIG_PRAM)
 	initr_mem,
 #endif
+
+#ifdef CONFIG_FWU_MULTI_BANK_UPDATE
+	fwu_boottime_checks,
+#endif
 	run_main_loop,
 };
 
diff --git a/include/fwu.h b/include/fwu.h
index cfc9aafc7d..d863b23a5a 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -37,6 +37,9 @@ struct fwu_mdata_ops {
 	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
 		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
 
+u8 fwu_update_checks_pass(void);
+int fwu_boottime_checks(void);
+
 int fwu_get_mdata(struct fwu_mdata **mdata);
 int fwu_update_mdata(struct fwu_mdata *mdata);
 int fwu_get_active_index(u32 *active_idx);
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 9808036eec..4871e0ccd6 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -3,8 +3,20 @@
  * Copyright (c) 2022, Linaro Limited
  */
 
+
+#include <dm.h>
+#include <efi.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
 #include <fwu.h>
 #include <fwu_mdata.h>
+#include <malloc.h>
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+static u8 trial_state;
+static u8 boottime_check;
 
 __weak int fwu_plat_get_update_index(u32 *update_idx)
 {
@@ -20,3 +32,166 @@ __weak int fwu_plat_get_update_index(u32 *update_idx)
 
 	return ret;
 }
+
+static int trial_counter_update(u16 *trial_state_ctr)
+{
+	bool delete;
+	u32 var_attr;
+	efi_status_t status;
+	efi_uintn_t var_size;
+
+	delete = !trial_state_ctr ? true : false;
+	var_size = !trial_state_ctr ? 0 : (efi_uintn_t)sizeof(*trial_state_ctr);
+	var_attr = !trial_state_ctr ? 0 : EFI_VARIABLE_NON_VOLATILE |
+		EFI_VARIABLE_BOOTSERVICE_ACCESS;
+	status = efi_set_variable_int(u"TrialStateCtr",
+				      &efi_global_variable_guid,
+				      var_attr,
+				      var_size, trial_state_ctr, false);
+
+	if ((delete && (status != EFI_NOT_FOUND &&
+			status != EFI_SUCCESS)) ||
+	    (!delete && status != EFI_SUCCESS))
+		return -1;
+
+	return 0;
+}
+
+static int in_trial_state(struct fwu_mdata *mdata)
+{
+	u32 i, active_bank;
+	struct fwu_image_entry *img_entry;
+	struct fwu_image_bank_info *img_bank_info;
+
+	active_bank = mdata->active_index;
+	img_entry = &mdata->img_entry[0];
+	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
+		img_bank_info = &img_entry[i].img_bank_info[active_bank];
+		if (!img_bank_info->accepted) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int fwu_trial_state_check(void)
+{
+	int ret;
+	efi_status_t status;
+	efi_uintn_t var_size;
+	u16 trial_state_ctr;
+	u32 var_attributes, active_idx;
+	struct fwu_mdata *mdata = NULL;
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret)
+		return ret;
+
+	if ((trial_state = in_trial_state(mdata))) {
+		var_size = (efi_uintn_t)sizeof(trial_state_ctr);
+		log_info("System booting in Trial State\n");
+		var_attributes = EFI_VARIABLE_NON_VOLATILE |
+			EFI_VARIABLE_BOOTSERVICE_ACCESS;
+		status = efi_get_variable_int(u"TrialStateCtr",
+					      &efi_global_variable_guid,
+					      &var_attributes,
+					      &var_size, &trial_state_ctr,
+					      NULL);
+		if (status != EFI_SUCCESS) {
+			log_err("Unable to read TrialStateCtr variable\n");
+			ret = -1;
+			goto out;
+		}
+
+		++trial_state_ctr;
+		if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) {
+			log_info("Trial State count exceeded. Revert back to previous_active_index\n");
+			active_idx = mdata->active_index;
+			ret = fwu_revert_boot_index();
+			if (ret) {
+				log_err("Unable to revert active_index\n");
+				goto out;
+			}
+
+			/* Delete the TrialStateCtr variable */
+			ret = trial_counter_update(NULL);
+			if (ret) {
+				log_err("Unable to delete TrialStateCtr variable\n");
+				goto out;
+			}
+		} else {
+			ret = trial_counter_update(&trial_state_ctr);
+			if (ret) {
+				log_err("Unable to increment TrialStateCtr variable\n");
+				goto out;
+			}
+		}
+	} else {
+		/* Delete the variable */
+		ret = trial_counter_update(NULL);
+		if (ret) {
+			log_err("Unable to delete TrialStateCtr variable\n");
+		}
+	}
+
+out:
+	free(mdata);
+	return ret;
+}
+
+u8 fwu_update_checks_pass(void)
+{
+	return !trial_state && boottime_check;
+}
+
+int fwu_boottime_checks(void)
+{
+	int ret;
+	u32 boot_idx, active_idx;
+
+	ret = fwu_mdata_check();
+	if (ret) {
+		return 0;
+	}
+
+	/*
+	 * Get the Boot Index, i.e. the bank from
+	 * which the platform has booted. This value
+	 * gets passed from the ealier stage bootloader
+	 * which booted u-boot, e.g. tf-a. If the
+	 * boot index is not the same as the
+	 * active_index read from the FWU metadata,
+	 * update the active_index.
+	 */
+	fwu_plat_get_bootidx(&boot_idx);
+	if (boot_idx >= CONFIG_FWU_NUM_BANKS) {
+		log_err("Received incorrect value of boot_index\n");
+		return 0;
+	}
+
+	ret = fwu_get_active_index(&active_idx);
+	if (ret) {
+		log_err("Unable to read active_index\n");
+		return 0;
+	}
+
+	if (boot_idx != active_idx) {
+		log_info("Boot idx %u is not matching active idx %u, changing active_idx\n",
+			 boot_idx, active_idx);
+		ret = fwu_update_active_index(boot_idx);
+		if (!ret)
+			boottime_check = 1;
+
+		return 0;
+	}
+
+	if (efi_init_obj_list() != EFI_SUCCESS)
+		return 0;
+
+	ret = fwu_trial_state_check();
+	if (!ret)
+		boottime_check = 1;
+
+	return 0;
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 09/13] FWU: Add support for the FWU Multi Bank Update feature
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (7 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

The FWU Multi Bank Update feature supports updation of firmware images
to one of multiple sets(also called banks) of images. The firmware
images are clubbed together in banks, with the system booting images
from the active bank. Information on the images such as which bank
they belong to is stored as part of the metadata structure, which is
stored on the same storage media as the firmware images on a dedicated
partition.

At the time of update, the metadata is read to identify the bank to
which the images need to be flashed(update bank). On a successful
update, the metadata is modified to set the updated bank as active
bank to subsequently boot from.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V7:
* Introduce a new function fwu_to_efi_error() and check for all errors
  returned by the fwu API's through this function, as suggested by
  Ilias.
* Call fwu_trial_state_ctr_start() only when the OS is supposed to
  accept/reject the updated images.

 include/fwu.h                |  10 ++
 lib/Kconfig                  |   6 +
 lib/Makefile                 |   1 +
 lib/efi_loader/efi_capsule.c | 213 ++++++++++++++++++++++++++++++++++-
 lib/efi_loader/efi_setup.c   |   3 +-
 lib/fwu_updates/Kconfig      |  31 +++++
 lib/fwu_updates/fwu.c        |  13 +++
 7 files changed, 271 insertions(+), 6 deletions(-)
 create mode 100644 lib/fwu_updates/Kconfig

diff --git a/include/fwu.h b/include/fwu.h
index d863b23a5a..a42fb31bd1 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -32,13 +32,23 @@ struct fwu_mdata_ops {
 };
 
 #define FWU_MDATA_VERSION	0x1
+#define FWU_IMAGE_ACCEPTED	0x1
 
 #define FWU_MDATA_GUID \
 	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
 		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
 
+#define FWU_OS_REQUEST_FW_REVERT_GUID \
+	EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
+		 0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
+
+#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
+	EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
+		 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
+
 u8 fwu_update_checks_pass(void);
 int fwu_boottime_checks(void);
+int fwu_trial_state_ctr_start(void);
 
 int fwu_get_mdata(struct fwu_mdata **mdata);
 int fwu_update_mdata(struct fwu_mdata *mdata);
diff --git a/lib/Kconfig b/lib/Kconfig
index 6121c80dc8..6abe1d0a86 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -978,3 +978,9 @@ config LMB_RESERVED_REGIONS
 	  memory blocks.
 
 endmenu
+
+menu "FWU Multi Bank Updates"
+
+source lib/fwu_updates/Kconfig
+
+endmenu
diff --git a/lib/Makefile b/lib/Makefile
index e3deb15287..f2cfd1e428 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_EFI) += efi/
 obj-$(CONFIG_EFI_LOADER) += efi_driver/
 obj-$(CONFIG_EFI_LOADER) += efi_loader/
 obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += efi_selftest/
+obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_updates/
 obj-$(CONFIG_LZMA) += lzma/
 obj-$(CONFIG_BZIP2) += bzip2/
 obj-$(CONFIG_FIT) += libfdt/
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index a6b98f066a..44c56443dc 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -14,6 +14,7 @@
 #include <env.h>
 #include <fdtdec.h>
 #include <fs.h>
+#include <fwu.h>
 #include <hang.h>
 #include <malloc.h>
 #include <mapmem.h>
@@ -32,6 +33,17 @@ 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;
+const efi_guid_t fwu_guid_os_request_fw_revert =
+		FWU_OS_REQUEST_FW_REVERT_GUID;
+const efi_guid_t fwu_guid_os_request_fw_accept =
+		FWU_OS_REQUEST_FW_ACCEPT_GUID;
+
+#define FW_ACCEPT_OS	(u32)0x8000
+
+__maybe_unused static u32 update_index;
+__maybe_unused static bool capsule_update;
+__maybe_unused static bool fw_accept_os;
+static bool image_index_check = true;
 
 #ifdef CONFIG_EFI_CAPSULE_ON_DISK
 /* for file system access */
@@ -205,7 +217,8 @@ efi_fmp_find(efi_guid_t *image_type, u8 image_index, u64 instance,
 			log_debug("+++ desc[%d] index: %d, name: %ls\n",
 				  j, desc->image_index, desc->image_id_name);
 			if (!guidcmp(&desc->image_type_id, image_type) &&
-			    (desc->image_index == image_index) &&
+			    (!image_index_check ||
+			     desc->image_index == image_index) &&
 			    (!instance ||
 			     !desc->hardware_instance ||
 			      desc->hardware_instance == instance))
@@ -388,6 +401,83 @@ efi_status_t efi_capsule_authenticate(const void *capsule, efi_uintn_t capsule_s
 }
 #endif /* CONFIG_EFI_CAPSULE_AUTHENTICATE */
 
+static bool fwu_empty_capsule(struct efi_capsule_header *capsule)
+{
+	return !guidcmp(&capsule->capsule_guid,
+			&fwu_guid_os_request_fw_revert) ||
+		!guidcmp(&capsule->capsule_guid,
+			 &fwu_guid_os_request_fw_accept);
+}
+
+static efi_status_t fwu_to_efi_error(int err)
+{
+	efi_status_t ret;
+
+	switch(err) {
+	case 0:
+		ret = EFI_SUCCESS;
+		break;
+	case -ENODEV:
+	case -ERANGE:
+	case -EIO:
+		ret = EFI_DEVICE_ERROR;
+		break;
+	case -EINVAL:
+		ret = EFI_INVALID_PARAMETER;
+		break;
+	default:
+		ret = EFI_OUT_OF_RESOURCES;
+	}
+
+	return ret;
+}
+
+static efi_status_t fwu_empty_capsule_process(
+	struct efi_capsule_header *capsule)
+{
+	int status;
+	u32 active_idx;
+	efi_status_t ret;
+	efi_guid_t *image_guid;
+
+	if (!guidcmp(&capsule->capsule_guid,
+		     &fwu_guid_os_request_fw_revert)) {
+		/*
+		 * One of the previously updated image has
+		 * failed the OS acceptance test. OS has
+		 * requested to revert back to the earlier
+		 * boot index
+		 */
+		status = fwu_revert_boot_index();
+		ret = fwu_to_efi_error(status);
+		if (ret == EFI_SUCCESS)
+			log_info("Reverted the FWU active_index. Recommend rebooting the system\n");
+		else
+			log_err("Failed to revert the FWU boot index\n");
+	} else {
+		/*
+		 * Image accepted by the OS. Set the acceptance
+		 * status for the image.
+		 */
+		image_guid = (void *)(char *)capsule +
+			capsule->header_size;
+
+		status = fwu_get_active_index(&active_idx);
+		ret = fwu_to_efi_error(status);
+		if (ret != EFI_SUCCESS) {
+			log_err("Unable to get the active_index from the FWU metadata\n");
+			return ret;
+		}
+
+		status = fwu_accept_image(image_guid, active_idx);
+		ret = fwu_to_efi_error(status);
+		if (ret != EFI_SUCCESS)
+			log_err("Unable to set the Accept bit for the image %pUs\n",
+				image_guid);
+	}
+
+	return ret;
+}
 
 /**
  * efi_capsule_update_firmware - update firmware from capsule
@@ -407,10 +497,42 @@ static efi_status_t efi_capsule_update_firmware(
 	void *image_binary, *vendor_code;
 	efi_handle_t *handles;
 	efi_uintn_t no_handles;
-	int item;
+	int item, alt_no;
 	struct efi_firmware_management_protocol *fmp;
 	u16 *abort_reason;
+	efi_guid_t image_type_id;
 	efi_status_t ret = EFI_SUCCESS;
+	int status;
+	u8 image_index;
+
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		if (!fwu_empty_capsule(capsule_data) &&
+		    !fwu_update_checks_pass()) {
+			log_err("FWU checks failed. Cannot start update\n");
+			return EFI_INVALID_PARAMETER;
+		}
+
+		if (fwu_empty_capsule(capsule_data)) {
+			capsule_update = false;
+			return fwu_empty_capsule_process(capsule_data);
+		} else {
+			capsule_update = true;
+		}
+
+		/* Obtain the update_index from the platform */
+		status = fwu_plat_get_update_index(&update_index);
+		if (status < 0) {
+			log_err("Failed to get the FWU update_index value\n");
+			return EFI_DEVICE_ERROR;
+		}
+
+		fw_accept_os = capsule_data->flags & FW_ACCEPT_OS ? 0x1 : 0x0;
+		/*
+		 * For Multi Bank updates, the image index is determined at
+		 * runtime based on the value of the update bank.
+		 */
+		image_index_check = false;
+	}
 
 	/* sanity check */
 	if (capsule_data->header_size < sizeof(*capsule) ||
@@ -485,8 +607,31 @@ static efi_status_t efi_capsule_update_firmware(
 				goto out;
 		}
 
+		if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+			/*
+			 * Based on the value of update_image_type_id,
+			 * derive the alt number value. This will be
+			 * passed as update_image_index to the
+			 * set_image function.
+			 */
+			image_type_id = image->update_image_type_id;
+			status = fwu_get_image_alt_num(&image_type_id,
+						       update_index,
+						       &alt_no);
+			ret = fwu_to_efi_error(status);
+			if (ret != EFI_SUCCESS) {
+				log_err("Unable to get the alt no for the image type %pUs\n",
+					&image_type_id);
+				goto out;
+			}
+			log_debug("alt_no %u for Image Type Id %pUs\n",
+				  alt_no, &image_type_id);
+			image_index = alt_no + 1;
+		} else {
+			image_index = image->update_image_index;
+		}
 		abort_reason = NULL;
-		ret = EFI_CALL(fmp->set_image(fmp, image->update_image_index,
+		ret = EFI_CALL(fmp->set_image(fmp, image_index,
 					      image_binary,
 					      image_binary_size,
 					      vendor_code, NULL,
@@ -497,6 +642,33 @@ static efi_status_t efi_capsule_update_firmware(
 			efi_free_pool(abort_reason);
 			goto out;
 		}
+
+		if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+			if (!fw_accept_os) {
+				/*
+				 * The OS will not be accepting the firmware
+				 * images. Set the accept bit of all the
+				 * images contained in this capsule.
+				 */
+				status = fwu_accept_image(&image_type_id,
+							  update_index);
+			} else {
+				status = fwu_clear_accept_image(&image_type_id,
+								update_index);
+			}
+			ret = fwu_to_efi_error(status);
+			if (ret != EFI_SUCCESS) {
+				log_err("Unable to %s the accept bit for the image %pUs\n",
+					fw_accept_os ? "clear" : "set",
+					&image_type_id);
+				goto out;
+			}
+
+			log_debug("%s the accepted bit for Image %pUs\n",
+				  fw_accept_os ? "Cleared" : "Set",
+				  &image_type_id);
+		}
+
 	}
 
 out:
@@ -1102,8 +1274,10 @@ efi_status_t efi_launch_capsules(void)
 {
 	struct efi_capsule_header *capsule = NULL;
 	u16 **files;
+	int status;
 	unsigned int nfiles, index, i;
 	efi_status_t ret;
+	bool update_status = true;
 
 	if (check_run_capsules() != EFI_SUCCESS)
 		return EFI_SUCCESS;
@@ -1131,12 +1305,14 @@ efi_status_t efi_launch_capsules(void)
 		ret = efi_capsule_read_file(files[i], &capsule);
 		if (ret == EFI_SUCCESS) {
 			ret = efi_capsule_update_firmware(capsule);
-			if (ret != EFI_SUCCESS)
+			if (ret != EFI_SUCCESS) {
 				log_err("Applying capsule %ls failed.\n",
 					files[i]);
-			else
+				update_status = false;
+			} else {
 				log_info("Applying capsule %ls succeeded.\n",
 					 files[i]);
+			}
 
 			/* create CapsuleXXXX */
 			set_capsule_result(index, capsule, ret);
@@ -1144,6 +1320,7 @@ efi_status_t efi_launch_capsules(void)
 			free(capsule);
 		} else {
 			log_err("Reading capsule %ls failed\n", files[i]);
+			update_status = false;
 		}
 		/* delete a capsule either in case of success or failure */
 		ret = efi_capsule_delete_file(files[i]);
@@ -1151,7 +1328,33 @@ efi_status_t efi_launch_capsules(void)
 			log_err("Deleting capsule %ls failed\n",
 				files[i]);
 	}
+
 	efi_capsule_scan_done();
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		if (update_status == true && capsule_update == true) {
+			/*
+			 * All the capsules have been updated successfully,
+			 * update the FWU metadata.
+			 */
+			log_debug("Update Complete. Now updating active_index to %u\n",
+				  update_index);
+			status = fwu_update_active_index(update_index);
+			ret = fwu_to_efi_error(status);
+			if (ret != EFI_SUCCESS) {
+				log_err("Failed to update FWU metadata index values\n");
+			} else {
+				log_debug("Successfully updated the active_index\n");
+				ret = EFI_SUCCESS;
+				if (fw_accept_os) {
+					status = fwu_trial_state_ctr_start();
+					if (status < 0)
+						ret = EFI_DEVICE_ERROR;
+				}
+			}
+		} else if (capsule_update == true && update_status == false) {
+			log_err("All capsules were not updated. Not updating FWU metadata\n");
+		}
+	}
 
 	for (i = 0; i < nfiles; i++)
 		free(files[i]);
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 751beda590..4725b25626 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -350,7 +350,8 @@ efi_status_t efi_init_obj_list(void)
 		goto out;
 
 	/* Execute capsules after reboot */
-	if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) &&
+	if (!IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE) &&
+	    IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) &&
 	    !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY))
 		ret = efi_launch_capsules();
 out:
diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig
new file mode 100644
index 0000000000..6de28e0c9c
--- /dev/null
+++ b/lib/fwu_updates/Kconfig
@@ -0,0 +1,31 @@
+config FWU_MULTI_BANK_UPDATE
+	bool "Enable FWU Multi Bank Update Feature"
+	depends on EFI_HAVE_CAPSULE_SUPPORT
+	select PARTITION_TYPE_GUID
+	select EFI_SETUP_EARLY
+	help
+	  Feature for updating firmware images on platforms having
+	  multiple banks(copies) of the firmware images. One of the
+	  bank is selected for updating all the firmware components
+
+config FWU_NUM_BANKS
+	int "Number of Banks defined by the platform"
+	depends on FWU_MULTI_BANK_UPDATE
+	help
+	  Define the number of banks of firmware images on a platform
+
+config FWU_NUM_IMAGES_PER_BANK
+	int "Number of firmware images per bank"
+	depends on FWU_MULTI_BANK_UPDATE
+	help
+	  Define the number of firmware images per bank. This value
+	  should be the same for all the banks.
+
+config FWU_TRIAL_STATE_CNT
+	int "Number of times system boots in Trial State"
+	depends on FWU_MULTI_BANK_UPDATE
+	default 3
+	help
+	  With FWU Multi Bank Update feature enabled, number of times
+	  the platform is allowed to boot in Trial State after an
+	  update.
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 4871e0ccd6..82284afc88 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -145,6 +145,19 @@ u8 fwu_update_checks_pass(void)
 	return !trial_state && boottime_check;
 }
 
+int fwu_trial_state_ctr_start(void)
+{
+	int ret;
+	u16 trial_state_ctr;
+
+	trial_state_ctr = 0;
+	ret = trial_counter_update(&trial_state_ctr);
+	if (ret)
+		log_err("Unable to initialise TrialStateCtr\n");
+
+	return ret;
+}
+
 int fwu_boottime_checks(void)
 {
 	int ret;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (8 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 09/13] FWU: Add support for the FWU Multi Bank Update feature Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-18  3:21   ` Simon Glass
  2022-08-17 12:43 ` [PATCH v8 11/13] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

Add a command to read the metadata as specified in the FWU
specification and print the fields of the metadata.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since V7: None

 cmd/Kconfig     |  7 +++++
 cmd/Makefile    |  1 +
 cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 cmd/fwu_mdata.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 211ebe9c87..95e762d21c 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -161,6 +161,13 @@ config CMD_CPU
 	  internal name) and clock frequency. Other information may be
 	  available depending on the CPU driver.
 
+config CMD_FWU_METADATA
+	bool "fwu metadata read"
+	depends on FWU_MULTI_BANK_UPDATE
+	default y
+	help
+	  Command to read the metadata and dump it's contents
+
 config CMD_LICENSE
 	bool "license"
 	select BUILD_BIN2C
diff --git a/cmd/Makefile b/cmd/Makefile
index 6e87522b62..ff6e160f4a 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_CMD_FPGA) += fpga.o
 obj-$(CONFIG_CMD_FPGAD) += fpgad.o
 obj-$(CONFIG_CMD_FS_GENERIC) += fs.o
 obj-$(CONFIG_CMD_FUSE) += fuse.o
+obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o
 obj-$(CONFIG_CMD_GETTIME) += gettime.o
 obj-$(CONFIG_CMD_GPIO) += gpio.o
 obj-$(CONFIG_CMD_HVC) += smccc.o
diff --git a/cmd/fwu_mdata.c b/cmd/fwu_mdata.c
new file mode 100644
index 0000000000..ee9d035374
--- /dev/null
+++ b/cmd/fwu_mdata.c
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <command.h>
+#include <dm.h>
+#include <fwu.h>
+#include <fwu_mdata.h>
+#include <log.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <linux/types.h>
+
+static void print_mdata(struct fwu_mdata *mdata)
+{
+	int i, j;
+	struct fwu_image_entry *img_entry;
+	struct fwu_image_bank_info *img_info;
+
+	printf("\tFWU Metadata\n");
+	printf("crc32: %#x\n", mdata->crc32);
+	printf("version: %#x\n", mdata->version);
+	printf("active_index: %#x\n", mdata->active_index);
+	printf("previous_active_index: %#x\n", mdata->previous_active_index);
+
+	printf("\tImage Info\n");
+	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
+		img_entry = &mdata->img_entry[i];
+		printf("\nImage Type Guid: %pUL\n",
+		       &img_entry->image_type_uuid);
+		printf("Location Guid: %pUL\n", &img_entry->location_uuid);
+		for (j = 0; j < CONFIG_FWU_NUM_BANKS; j++) {
+			img_info = &img_entry->img_bank_info[j];
+			printf("Image Guid:  %pUL\n", &img_info->image_uuid);
+			printf("Image Acceptance: %s\n",
+			       img_info->accepted == 0x1 ? "yes" : "no");
+		}
+	}
+}
+
+int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag,
+		     int argc, char * const argv[])
+{
+	struct udevice *dev;
+	int ret = CMD_RET_SUCCESS, res;
+	struct fwu_mdata *mdata = NULL;
+
+	if (uclass_get_device(UCLASS_FWU_MDATA, 0, &dev) || !dev) {
+		log_err("Unable to get FWU metadata device\n");
+		return CMD_RET_FAILURE;
+	}
+
+	res = fwu_mdata_check();
+	if (res < 0) {
+		log_err("FWU Metadata check failed\n");
+		ret = CMD_RET_FAILURE;
+		goto out;
+	}
+
+	res = fwu_get_mdata(&mdata);
+	if (res < 0) {
+		log_err("Unable to get valid FWU metadata\n");
+		ret = CMD_RET_FAILURE;
+		goto out;
+	}
+
+	print_mdata(mdata);
+
+out:
+	free(mdata);
+	return ret;
+}
+
+U_BOOT_CMD(
+	fwu_mdata_read,	1,	1,	do_fwu_mdata_read,
+	"Read and print FWU metadata",
+	""
+);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 11/13] mkeficapsule: Add support for generating empty capsules
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (9 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 12/13] mkeficapsule: Add support for setting OEM flags in capsule header Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
  12 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

The Dependable Boot specification[1] describes the structure of the
firmware accept and revert capsules. These are empty capsules which
are used for signalling the acceptance or rejection of the updated
firmware by the OS. Add support for generating these empty capsules.

[1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V7:
* Modify the logic to check the setting of both -A and -R options
  being passed to the tool, as suggested by Ilias.

 doc/mkeficapsule.1   | 29 +++++++++----
 tools/eficapsule.h   |  8 ++++
 tools/mkeficapsule.c | 96 ++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 119 insertions(+), 14 deletions(-)

diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
index 09bdc24295..77ca061efd 100644
--- a/doc/mkeficapsule.1
+++ b/doc/mkeficapsule.1
@@ -8,7 +8,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot
 
 .SH SYNOPSIS
 .B mkeficapsule
-.RI [ options "] " image-blob " " capsule-file
+.RI [ options ] " " [ image-blob ] " " capsule-file
 
 .SH "DESCRIPTION"
 .B mkeficapsule
@@ -23,8 +23,13 @@ Optionally, a capsule file can be signed with a given private key.
 In this case, the update will be authenticated by verifying the signature
 before applying.
 
+Additionally, an empty capsule file can be generated for acceptance or
+rejection of firmware images by a governing component like an Operating
+System. The empty capsules do not require an image-blob input file.
+
+
 .B mkeficapsule
-takes any type of image files, including:
+takes any type of image files when generating non empty capsules, including:
 .TP
 .I raw image
 format is a single binary blob of any type of firmware.
@@ -36,18 +41,16 @@ multiple binary blobs in a single capsule file.
 This type of image file can be generated by
 .BR mkimage .
 
-.PP
-If you want to use other types than above two, you should explicitly
-specify a guid for the FMP driver.
-
 .SH "OPTIONS"
+
 .TP
 .BI "-g\fR,\fB --guid " guid-string
 Specify guid for image blob type. The format is:
     xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 
 The first three elements are in little endian, while the rest
-is in big endian.
+is in big endian. The option must be specified for all non empty and
+image acceptance capsules
 
 .TP
 .BI "-i\fR,\fB --index " index
@@ -57,6 +60,18 @@ Specify an image index
 .BI "-I\fR,\fB --instance " instance
 Specify a hardware instance
 
+.PP
+For generation of firmware accept empty capsule
+.BR --guid
+is mandatory
+.TP
+.BI "-A\fR,\fB --fw-accept "
+Generate a firmware acceptance empty capsule
+
+.TP
+.BI "-R\fR,\fB --fw-revert "
+Generate a firmware revert empty capsule
+
 .TP
 .BR -h ", " --help
 Print a help message
diff --git a/tools/eficapsule.h b/tools/eficapsule.h
index d63b831443..072a4b5598 100644
--- a/tools/eficapsule.h
+++ b/tools/eficapsule.h
@@ -41,6 +41,14 @@ typedef struct {
 	EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \
 		 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7)
 
+#define FW_ACCEPT_OS_GUID \
+	EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
+		 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
+
+#define FW_REVERT_OS_GUID \
+	EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
+		 0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
+
 /* flags */
 #define CAPSULE_FLAGS_PERSIST_ACROSS_RESET      0x00010000
 
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 5f74d23b9e..25bfb39e5b 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -29,7 +29,13 @@ static const char *tool_name = "mkeficapsule";
 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 
-static const char *opts_short = "g:i:I:v:p:c:m:dh";
+static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
+
+enum {
+	CAPSULE_NORMAL_BLOB = 0,
+	CAPSULE_ACCEPT,
+	CAPSULE_REVERT,
+} capsule_type;
 
 static struct option options[] = {
 	{"guid", required_argument, NULL, 'g'},
@@ -39,6 +45,8 @@ static struct option options[] = {
 	{"certificate", required_argument, NULL, 'c'},
 	{"monotonic-count", required_argument, NULL, 'm'},
 	{"dump-sig", no_argument, NULL, 'd'},
+	{"fw-accept", no_argument, NULL, 'A'},
+	{"fw-revert", no_argument, NULL, 'R'},
 	{"help", no_argument, NULL, 'h'},
 	{NULL, 0, NULL, 0},
 };
@@ -55,6 +63,8 @@ static void print_usage(void)
 		"\t-c, --certificate <cert file>     signer's certificate file\n"
 		"\t-m, --monotonic-count <count>     monotonic count\n"
 		"\t-d, --dump_sig              dump signature (*.p7)\n"
+		"\t-A, --fw-accept  firmware accept capsule, requires GUID, no image blob\n"
+		"\t-R, --fw-revert  firmware revert capsule, takes no GUID, no image blob\n"
 		"\t-h, --help                  print a help message\n",
 		tool_name);
 }
@@ -564,6 +574,49 @@ void convert_uuid_to_guid(unsigned char *buf)
 	buf[7] = c;
 }
 
+static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept)
+{
+	struct efi_capsule_header header = { 0 };
+	FILE *f = NULL;
+	int ret = -1;
+	efi_guid_t fw_accept_guid = FW_ACCEPT_OS_GUID;
+	efi_guid_t fw_revert_guid = FW_REVERT_OS_GUID;
+	efi_guid_t capsule_guid;
+
+	f = fopen(path, "w");
+	if (!f) {
+		fprintf(stderr, "cannot open %s\n", path);
+		goto err;
+	}
+
+	capsule_guid = fw_accept ? fw_accept_guid : fw_revert_guid;
+
+	memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
+	header.header_size = sizeof(header);
+	header.flags = 0;
+
+	header.capsule_image_size = fw_accept ?
+		sizeof(header) + sizeof(efi_guid_t) : sizeof(header);
+
+	if (write_capsule_file(f, &header, sizeof(header),
+			       "Capsule header"))
+		goto err;
+
+	if (fw_accept) {
+		if (write_capsule_file(f, guid, sizeof(*guid),
+				       "FW Accept Capsule Payload"))
+			goto err;
+	}
+
+	ret = 0;
+
+err:
+	if (f)
+		fclose(f);
+
+	return ret;
+}
+
 /**
  * main - main entry function of mkeficapsule
  * @argc:	Number of arguments
@@ -592,6 +645,7 @@ int main(int argc, char **argv)
 	privkey_file = NULL;
 	cert_file = NULL;
 	dump_sig = 0;
+	capsule_type = CAPSULE_NORMAL_BLOB;
 	for (;;) {
 		c = getopt_long(argc, argv, opts_short, options, &idx);
 		if (c == -1)
@@ -639,22 +693,50 @@ int main(int argc, char **argv)
 		case 'd':
 			dump_sig = 1;
 			break;
-		case 'h':
+		case 'A':
+			if (capsule_type) {
+				fprintf(stderr,
+					"Select either of Accept or Revert capsule generation\n");
+				exit(1);
+			}
+			capsule_type = CAPSULE_ACCEPT;
+			break;
+		case 'R':
+			if (capsule_type) {
+				fprintf(stderr,
+					"Select either of Accept or Revert capsule generation\n");
+				exit(1);
+			}
+			capsule_type = CAPSULE_REVERT;
+			break;
+		default:
 			print_usage();
 			exit(EXIT_SUCCESS);
 		}
 	}
 
 	/* check necessary parameters */
-	if ((argc != optind + 2) || !guid ||
-	    ((privkey_file && !cert_file) ||
-	     (!privkey_file && cert_file))) {
+	if ((capsule_type == CAPSULE_NORMAL_BLOB &&
+	    ((argc != optind + 2) || !guid ||
+	     ((privkey_file && !cert_file) ||
+	      (!privkey_file && cert_file)))) ||
+	    (capsule_type != CAPSULE_NORMAL_BLOB &&
+	    ((argc != optind + 1) ||
+	     ((capsule_type == CAPSULE_ACCEPT) && !guid) ||
+	     ((capsule_type == CAPSULE_REVERT) && guid)))) {
 		print_usage();
 		exit(EXIT_FAILURE);
 	}
 
-	if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
-			 mcount, privkey_file, cert_file) < 0) {
+	if (capsule_type != CAPSULE_NORMAL_BLOB) {
+		if (create_empty_capsule(argv[argc - 1], guid,
+					 capsule_type == CAPSULE_ACCEPT) < 0) {
+			fprintf(stderr, "Creating empty capsule failed\n");
+			exit(EXIT_FAILURE);
+		}
+	} else 	if (create_fwbin(argv[argc - 1], argv[argc - 2], guid,
+				 index, instance, mcount, privkey_file,
+				 cert_file) < 0) {
 		fprintf(stderr, "Creating firmware capsule failed\n");
 		exit(EXIT_FAILURE);
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 12/13] mkeficapsule: Add support for setting OEM flags in capsule header
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (10 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 11/13] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-17 12:43 ` [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
  12 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

Add support for setting OEM flags in the capsule header. As per the
UEFI specification, bits 0-15 of the flags member of the capsule
header can be defined per capsule GUID.

The oemflags will be used for the FWU Multi Bank update feature, as
specified by the Dependable Boot specification[1]. Bit
15 of the flags member will be used to determine if the
acceptance/rejection of the updated images is to be done by the
firmware or an external component like the OS.

[1] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
Changes since V7: None

 doc/mkeficapsule.1   |  4 ++++
 tools/mkeficapsule.c | 17 ++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
index 77ca061efd..6fb2dd0810 100644
--- a/doc/mkeficapsule.1
+++ b/doc/mkeficapsule.1
@@ -72,6 +72,10 @@ Generate a firmware acceptance empty capsule
 .BI "-R\fR,\fB --fw-revert "
 Generate a firmware revert empty capsule
 
+.TP
+.BI "-o\fR,\fB --capoemflag "
+Capsule OEM flag, value between 0x0000 to 0xffff
+
 .TP
 .BR -h ", " --help
 Print a help message
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 25bfb39e5b..b24f873b48 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule";
 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 
-static const char *opts_short = "g:i:I:v:p:c:m:dhAR";
+static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR";
 
 enum {
 	CAPSULE_NORMAL_BLOB = 0,
@@ -47,6 +47,7 @@ static struct option options[] = {
 	{"dump-sig", no_argument, NULL, 'd'},
 	{"fw-accept", no_argument, NULL, 'A'},
 	{"fw-revert", no_argument, NULL, 'R'},
+	{"capoemflag", required_argument, NULL, 'o'},
 	{"help", no_argument, NULL, 'h'},
 	{NULL, 0, NULL, 0},
 };
@@ -65,6 +66,7 @@ static void print_usage(void)
 		"\t-d, --dump_sig              dump signature (*.p7)\n"
 		"\t-A, --fw-accept  firmware accept capsule, requires GUID, no image blob\n"
 		"\t-R, --fw-revert  firmware revert capsule, takes no GUID, no image blob\n"
+		"\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n"
 		"\t-h, --help                  print a help message\n",
 		tool_name);
 }
@@ -387,6 +389,7 @@ static void free_sig_data(struct auth_context *ctx)
  * @mcount:	Monotonic count in authentication information
  * @private_file:	Path to a private key file
  * @cert_file:	Path to a certificate file
+ * @oemflags:  Capsule OEM Flags, bits 0-15
  *
  * This function actually does the job of creating an uefi capsule file.
  * All the arguments must be supplied.
@@ -399,7 +402,8 @@ static void free_sig_data(struct auth_context *ctx)
  */
 static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 			unsigned long index, unsigned long instance,
-			uint64_t mcount, char *privkey_file, char *cert_file)
+			uint64_t mcount, char *privkey_file, char *cert_file,
+			uint16_t oemflags)
 {
 	struct efi_capsule_header header;
 	struct efi_firmware_management_capsule_header capsule;
@@ -464,6 +468,8 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 	header.header_size = sizeof(header);
 	/* TODO: The current implementation ignores flags */
 	header.flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
+	if (oemflags)
+		header.flags |= oemflags;
 	header.capsule_image_size = sizeof(header)
 					+ sizeof(capsule) + sizeof(uint64_t)
 					+ sizeof(image)
@@ -635,6 +641,7 @@ int main(int argc, char **argv)
 	unsigned char uuid_buf[16];
 	unsigned long index, instance;
 	uint64_t mcount;
+	uint16_t oemflags;
 	char *privkey_file, *cert_file;
 	int c, idx;
 
@@ -646,6 +653,7 @@ int main(int argc, char **argv)
 	cert_file = NULL;
 	dump_sig = 0;
 	capsule_type = CAPSULE_NORMAL_BLOB;
+	oemflags = 0;
 	for (;;) {
 		c = getopt_long(argc, argv, opts_short, options, &idx);
 		if (c == -1)
@@ -709,6 +717,9 @@ int main(int argc, char **argv)
 			}
 			capsule_type = CAPSULE_REVERT;
 			break;
+		case 'o':
+			oemflags = strtoul(optarg, NULL, 0);
+			break;
 		default:
 			print_usage();
 			exit(EXIT_SUCCESS);
@@ -736,7 +747,7 @@ int main(int argc, char **argv)
 		}
 	} else 	if (create_fwbin(argv[argc - 1], argv[argc - 2], guid,
 				 index, instance, mcount, privkey_file,
-				 cert_file) < 0) {
+				 cert_file, oemflags) < 0) {
 		fprintf(stderr, "Creating firmware capsule failed\n");
 		exit(EXIT_FAILURE);
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature
  2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
                   ` (11 preceding siblings ...)
  2022-08-17 12:43 ` [PATCH v8 12/13] mkeficapsule: Add support for setting OEM flags in capsule header Sughosh Ganu
@ 2022-08-17 12:43 ` Sughosh Ganu
  2022-08-18  3:21   ` Simon Glass
  12 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 12:43 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar,
	Sughosh Ganu

Add documentattion for the FWU Multi Bank Update feature. The document
describes the steps needed for setting up the platform for the
feature, as well as steps for enabling the feature on the platform.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V7:
* Handle the various review comments from Heinrich.

 doc/develop/uefi/fwu_updates.rst | 165 +++++++++++++++++++++++++++++++
 doc/develop/uefi/index.rst       |   1 +
 doc/develop/uefi/uefi.rst        |   2 +
 3 files changed, 168 insertions(+)
 create mode 100644 doc/develop/uefi/fwu_updates.rst

diff --git a/doc/develop/uefi/fwu_updates.rst b/doc/develop/uefi/fwu_updates.rst
new file mode 100644
index 0000000000..fad3fbb3a8
--- /dev/null
+++ b/doc/develop/uefi/fwu_updates.rst
@@ -0,0 +1,165 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright (c) 2022 Linaro Limited
+
+FWU Multi Bank Updates in U-Boot
+================================
+
+The FWU Multi Bank Update feature implements the firmware update
+mechanism described in the PSA Firmware Update for A-profile Arm
+Architecture specification [1]. Certain aspects of the Dependable
+Boot specification [2] are also implemented. The feature provides a
+mechanism to have multiple banks of updatable firmware images and for
+updating the firmware images on the non-booted bank. On a successful
+update, the platform boots from the updated bank on subsequent
+boot. The UEFI capsule-on-disk update feature is used for performing
+the actual updates of the updatable firmware images.
+
+The bookkeeping of the updatable images is done through a structure
+called metadata. Currently, the FWU metadata supports identification
+of images based on image GUIDs stored on a GPT partitioned storage
+media. There are plans to extend the metadata structure for non GPT
+partitioned devices as well.
+
+Accessing the FWU metadata is done through generic API's which are
+defined in a driver which complies with the U-Boot's driver model. A
+new uclass UCLASS_FWU_MDATA has been added for accessing the FWU
+metadata. Individual drivers can be added based on the type of storage
+media, and it's partitioning method. Details of the storage device
+containing the FWU metadata partitions are specified through a U-Boot
+specific device tree property `fwu-mdata-store`. Please refer to
+U-Boot `doc <doc/device-tree-bindings/firmware/fwu-mdata-gpt.yaml>`__
+for the device tree bindings.
+
+Enabling the FWU Multi Bank Update feature
+------------------------------------------
+
+The feature can be enabled by specifying the following configs::
+
+    CONFIG_EFI_CAPSULE_ON_DISK=y
+    CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y
+    CONFIG_EFI_CAPSULE_FIRMWARE=y
+    CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
+
+    CONFIG_FWU_MULTI_BANK_UPDATE=y
+    CONFIG_CMD_FWU_METADATA=y
+    CONFIG_DM_FWU_MDATA=y
+    CONFIG_FWU_MDATA_GPT_BLK=y
+    CONFIG_FWU_NUM_BANKS=<val>
+    CONFIG_FWU_NUM_IMAGES_PER_BANK=<val>
+
+in the .config file
+
+The first group of configuration settings enable the UEFI
+capsule-on-disk update functionality. The second group of configs
+enable the FWU Multi Bank Update functionality. Please refer to the
+section :ref:`uefi_capsule_update_ref` for more details on generation
+of the UEFI capsule.
+
+Setting up the device for GPT partitioned storage
+-------------------------------------------------
+
+Before enabling the functionality in U-Boot, a GPT partitioned storage
+device is required. Assuming a GPT partitioned storage device, the
+storage media needs to be partitioned with the correct number of
+partitions, given the number of banks and number of images per bank
+that the platform is going to support. Each updatable firmware image
+will be stored on an separate partition. In addition, the two copies
+of the FWU metadata will be stored on two separate partitions.
+
+As an example, a platform supporting two banks with each bank
+containing three images would need to have 2 * 3 = 6 partitions plus
+the two metadata partitions, or 8 partitions. In addition the storage
+media can have additional partitions of non-updatable images, like the
+EFI System Partition(ESP), a partition for the root file system
+etc. An example list of images on the storage medium would be
+
+* FWU metadata 1
+* U-Boot 1
+* OP-TEE 1
+* FWU metadata 2
+* OP-TEE 2
+* U-Boot 2
+* ESP
+* rootfs
+
+When generating the partitions, a few aspects need to be taken care
+of. Each GPT partition entry in the GPT header has two GUIDs::
+
+* PartitionTypeGUID
+* UniquePartitionGUID
+
+The PartitionTypeGUID value should correspond to the
+``image_type_uuid`` field of the FWU metadata. This field is used to
+identify a given type of updatable firmware image, e.g. U-Boot,
+OP-TEE, FIP etc. This GUID should also be used for specifying the
+`--guid` parameter when generating the capsule.
+
+The UniquePartitionGUID value should correspond to the ``image_uuid``
+field in the FWU metadata. This GUID is used to identify images of a
+given image type in different banks.
+
+Similarly, the FWU specifications defines the GUID value to be used
+for the metadata partitions. This would be the PartitionTypeGUID for
+the metadata partitions.
+
+When generating the metadata, the ``image_type_uuid`` and the
+``image_uuid`` values should match the *PartitionTypeGUID* and the
+*UniquePartitionGUID* values respectively.
+
+Performing the Update
+---------------------
+
+Once the storage media has been partitioned and populated with the
+metadata partitions, the UEFI capsule-on-disk update functionality can
+be used for performing the update. Refer to the section
+:ref:`uefi_capsule_update_ref` for details on how the update can be
+invoked.
+
+On a successful update, the FWU metadata gets updated to reflect the
+bank from which the platform would be booting on subsequent boot.
+
+Based on the value of bit15 of the Flags member of the capsule header,
+the updated images would either be accepted by the U-Boot's UEFI
+implementation, or by the Operating System. If the Operating System is
+accepting the firmware images, it does so by generating an empty
+*accept* capsule. The Operating System can also reject the updated
+firmware by generating a *revert* capsule. The empty capsule can be
+applied by using the exact same procedure used for performing the
+capsule-on-disk update.
+
+The task of accepting the different firmware images, post an update
+may be done by multiple, separate components in the Operating
+System. To help identify the firmware image that is being accepted,
+the accept capsule passes the image GUID of the firmware image being
+accepted. The relevant code in U-Boot then sets the Accept bit of the
+corresponding firmware image for which the accept capsule was
+found. Only when all the firmware components in a bank have been
+accepted does the platform transition to the regular state from trial
+state.
+
+The revert capsule on the other hand does not pass any image GUID,
+since reverting any image of the bank has the same result of the
+platform booting from the other bank on subsequent boot.
+
+Generating an empty capsule
+---------------------------
+
+The empty capsule can be generated using the mkeficapsule utility. To
+build the tool, enable::
+
+    CONFIG_TOOLS_MKEFICAPSULE=y
+
+Run the following commands to generate the accept/revert capsules::
+
+.. code-block:: bash
+
+    $ ./tools/mkeficapsule \
+      [--fw-accept --guid <image guid>] | \
+      [--fw-revert] \
+      <capsule_file_name>
+
+Links
+-----
+
+* [1] https://developer.arm.com/documentation/den0118/a/ - FWU Specification
+* [2] https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf - Dependable Boot Specification
diff --git a/doc/develop/uefi/index.rst b/doc/develop/uefi/index.rst
index 7e65dbc5d5..e26b1fbe05 100644
--- a/doc/develop/uefi/index.rst
+++ b/doc/develop/uefi/index.rst
@@ -13,3 +13,4 @@ can be run an UEFI payload.
    uefi.rst
    u-boot_on_efi.rst
    iscsi.rst
+   fwu_updates.rst
diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
index 941e427093..536b278dd9 100644
--- a/doc/develop/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -277,6 +277,8 @@ Enable ``CONFIG_OPTEE``, ``CONFIG_CMD_OPTEE_RPMB`` and ``CONFIG_EFI_MM_COMM_TEE`
 
 [1] https://optee.readthedocs.io/en/latest/building/efi_vars/stmm.html
 
+.. _uefi_capsule_update_ref:
+
 Enabling UEFI Capsule Update feature
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata
  2022-08-17 12:43 ` [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2022-08-17 17:00   ` Jassi Brar
  2022-08-17 17:55     ` Sughosh Ganu
  2022-08-18 17:50   ` Simon Glass
  1 sibling, 1 reply; 46+ messages in thread
From: Jassi Brar @ 2022-08-17 17:00 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek

On Wed, 17 Aug 2022 at 07:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
.....
> diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> new file mode 100644
> index 0000000000..9808036eec
> --- /dev/null
> +++ b/lib/fwu_updates/fwu.c
> @@ -0,0 +1,22 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#include <fwu.h>
> +#include <fwu_mdata.h>
> +
> +__weak int fwu_plat_get_update_index(u32 *update_idx)
> +{
> +       int ret;
> +       u32 active_idx;
> +
> +       ret = fwu_get_active_index(&active_idx);
> +
> +       if (ret < 0)
> +               return -1;
> +
> +       *update_idx = active_idx ^= 0x1;
> +
It shoud be
        *update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS;

cheers.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata
  2022-08-17 17:00   ` Jassi Brar
@ 2022-08-17 17:55     ` Sughosh Ganu
  0 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-17 17:55 UTC (permalink / raw)
  To: Jassi Brar
  Cc: u-boot, Heinrich Schuchardt, Ilias Apalodimas, Takahiro Akashi,
	Patrick Delaunay, Patrice Chotard, Simon Glass, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek

On Wed, 17 Aug 2022 at 22:30, Jassi Brar <jaswinder.singh@linaro.org> wrote:
>
> On Wed, 17 Aug 2022 at 07:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> .....
> > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> > new file mode 100644
> > index 0000000000..9808036eec
> > --- /dev/null
> > +++ b/lib/fwu_updates/fwu.c
> > @@ -0,0 +1,22 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright (c) 2022, Linaro Limited
> > + */
> > +
> > +#include <fwu.h>
> > +#include <fwu_mdata.h>
> > +
> > +__weak int fwu_plat_get_update_index(u32 *update_idx)
> > +{
> > +       int ret;
> > +       u32 active_idx;
> > +
> > +       ret = fwu_get_active_index(&active_idx);
> > +
> > +       if (ret < 0)
> > +               return -1;
> > +
> > +       *update_idx = active_idx ^= 0x1;
> > +
> It shoud be
>         *update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS;

As mentioned in the commit message, this is a weak function for the
case where CONFIG_FWU_NUM_BANKS = 2, where the above logic works since
the fwu_get_active_index() function checks that a sane value is being
returned for the active_index. However, with the logic that you
suggest, this function can be extended for platforms with the number
of banks more than 2. I will incorporate this in the next version.
Thanks.

-sughosh


>
> cheers.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-17 12:43 ` [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
@ 2022-08-18  1:13   ` Simon Glass
  2022-08-18 11:03     ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18  1:13 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> In the FWU Multi Bank Update feature, the information about the
> updatable images is stored as part of the metadata, which is stored on
> a dedicated partition. Add the metadata structure, and a driver model
> uclass which provides functions to access the metadata. These are
> generic API's, and implementations can be added based on parameters
> like how the metadata partition is accessed and what type of storage
> device houses the metadata.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> ---
> Changes since V7:
> * Rephrased the error message in fwu_update_active_index as per
>   suggestion from Ilias.
> * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
>   from Ilias.
>
>  drivers/Kconfig                      |   2 +
>  drivers/Makefile                     |   1 +
>  drivers/fwu-mdata/Kconfig            |   7 +
>  drivers/fwu-mdata/Makefile           |   6 +
>  drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
>  include/dm/uclass-id.h               |   1 +
>  include/fwu.h                        |  49 +++
>  include/fwu_mdata.h                  |  67 ++++
>  8 files changed, 596 insertions(+)
>  create mode 100644 drivers/fwu-mdata/Kconfig
>  create mode 100644 drivers/fwu-mdata/Makefile
>  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
>  create mode 100644 include/fwu.h
>  create mode 100644 include/fwu_mdata.h
>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 8b6fead351..75ac149d31 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -44,6 +44,8 @@ source "drivers/fuzz/Kconfig"
>
>  source "drivers/fpga/Kconfig"
>
> +source "drivers/fwu-mdata/Kconfig"
> +
>  source "drivers/gpio/Kconfig"
>
>  source "drivers/hwspinlock/Kconfig"
> diff --git a/drivers/Makefile b/drivers/Makefile
> index eba9940231..70bbc2f5e0 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -84,6 +84,7 @@ obj-y += cache/
>  obj-$(CONFIG_CPU) += cpu/
>  obj-y += crypto/
>  obj-$(CONFIG_FASTBOOT) += fastboot/
> +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/
>  obj-y += misc/
>  obj-$(CONFIG_MMC) += mmc/
>  obj-$(CONFIG_NVME) += nvme/
> diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
> new file mode 100644
> index 0000000000..d6a21c8e19
> --- /dev/null
> +++ b/drivers/fwu-mdata/Kconfig
> @@ -0,0 +1,7 @@
> +config DM_FWU_MDATA

Please drop DM_ as there is no non-DM version


> +       bool "Driver support for accessing FWU Metadata"
> +       depends on DM
> +       help
> +         Enable support for accessing FWU Metadata partitions. The
> +         FWU Metadata partitions reside on the same storage device
> +         which contains the other FWU updatable firmware images.
> diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
> new file mode 100644
> index 0000000000..e53a8c9983
> --- /dev/null
> +++ b/drivers/fwu-mdata/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (c) 2022, Linaro Limited
> +#
> +
> +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
> diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c
> new file mode 100644
> index 0000000000..6bf7fa1b03
> --- /dev/null
> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> @@ -0,0 +1,463 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#define LOG_CATEGORY UCLASS_FWU_MDATA
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <efi_loader.h>
> +#include <fwu.h>
> +#include <fwu_mdata.h>
> +#include <log.h>
> +#include <malloc.h>
> +
> +#include <linux/errno.h>
> +#include <linux/types.h>
> +#include <u-boot/crc.h>
> +
> +#define IMAGE_ACCEPT_SET       BIT(0)
> +#define IMAGE_ACCEPT_CLEAR     BIT(1)
> +
> +static int fwu_get_dev_ops(struct udevice **dev,
> +                          const struct fwu_mdata_ops **ops)
> +{
> +       int ret;
> +
> +       ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev);

uclass_first_device() if there is only one

> +       if (ret) {
> +               log_debug("Cannot find fwu device\n");
> +               return ret;
> +       }
> +
> +       if ((*ops = device_get_ops(*dev)) == NULL) {
> +               log_debug("Cannot get fwu device ops\n");
> +               return -ENOSYS;
> +       }

This is actually a bug, so drop this. It is OK to have an assert() if
you want one.

> +
> +       return 0;
> +}
> +
> +/**
> + * fwu_verify_mdata() - Verify the FWU metadata
> + * @mdata: FWU metadata structure
> + * @pri_part: FWU metadata partition is primary or secondary
> + *
> + * Verify the FWU metadata by computing the CRC32 for the metadata
> + * structure and comparing it against the CRC32 value stored as part
> + * of the structure.
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part)
> +{
> +       u32 calc_crc32;
> +       void *buf;
> +
> +       buf = &mdata->version;
> +       calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> +
> +       if (calc_crc32 != mdata->crc32) {
> +               log_err("crc32 check failed for %s FWU metadata partition\n",
> +                       pri_part ? "primary" : "secondary");
> +               return -1;

Please use an -Exxx value like -EPERM

> +       }
> +
> +       return 0;
> +}
> +
> +/**
> + * fwu_get_active_index() - Get active_index from the FWU metadata
> + * @active_idx: active_index value to be read
> + *
> + * Read the active_index field from the FWU metadata and place it in
> + * the variable pointed to be the function argument.
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_get_active_index(u32 *active_idx)

Return the active index rather than having an arg?

> +{
> +       int ret;
> +       struct fwu_mdata *mdata = NULL;
> +
> +       ret = fwu_get_mdata(&mdata);

Can you use a local var and avoid the malloc() / free() ?

> +       if (ret < 0) {
> +               log_err("Unable to get valid FWU metadata\n");
> +               goto out;
> +       }
> +
> +       /*
> +        * Found the FWU metadata partition, now read the active_index
> +        * value
> +        */
> +       *active_idx = mdata->active_index;
> +       if (*active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> +               log_err("Active index value read is incorrect\n");
> +               ret = -EINVAL;
> +       }
> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +/**
> + * fwu_update_active_index() - Update active_index from the FWU metadata
> + * @active_idx: active_index value to be updated
> + *
> + * Update the active_index field in the FWU metadata
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_update_active_index(u32 active_idx)

uint

> +{
> +       int ret;
> +       struct fwu_mdata *mdata = NULL;
> +
> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {

>= CONFIG_FWU_NUM_BANKS

> +               log_err("Invalid active index value\n");
> +               return -1;

error code, pleae fix globally

> +       }
> +
> +       ret = fwu_get_mdata(&mdata);
> +       if (ret < 0) {
> +               log_err("Unable to get valid FWU metadata\n");
> +               goto out;
> +       }
> +
> +       /*
> +        * Update the active index and previous_active_index fields
> +        * in the FWU metadata
> +        */
> +       mdata->previous_active_index = mdata->active_index;
> +       mdata->active_index = active_idx;
> +
> +       /*
> +        * Now write this updated FWU metadata to both the
> +        * FWU metadata partitions
> +        */
> +       ret = fwu_update_mdata(mdata);
> +       if (ret < 0) {
> +               log_err("Failed to update FWU metadata partitions\n");
> +               ret = -EIO;
> +       }
> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +/**
> + * fwu_get_image_alt_num() - Get the dfu alt number to be used for capsule update
> + * @image_type_id: pointer to the image GUID as passed in the capsule
> + * @update_bank: Bank to which the update is to be made
> + * @alt_num: The alt_num for the image
> + *
> + * Based on the GUID value passed in the capsule, along with the bank to which the
> + * image needs to be updated, get the dfu alt number which will be used for the
> + * capsule update
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> +                         int *alt_num)

alt_nump is often used with driver model to indicate a return
value.Again I wonder if the return value could be used?

> +{
> +       int ret, i;
> +       efi_guid_t *image_guid;
> +       struct udevice *dev = NULL;
> +       struct fwu_mdata *mdata = NULL;

Please don't set things to NULL for no reason, it cluttlers the code.

> +       struct fwu_image_entry *img_entry;
> +       const struct fwu_mdata_ops *ops = NULL;
> +       struct fwu_image_bank_info *img_bank_info;
> +
> +       ret = fwu_get_dev_ops(&dev, &ops);

Rather than this, see the pattern used by other uclasses

> +       if (ret)
> +               return ret;
> +
> +       ret = fwu_get_mdata(&mdata);
> +       if (ret) {
> +               log_err("Unable to get valid FWU metadata\n");
> +               goto out;
> +       }
> +
> +       ret = -EINVAL;
> +       /*
> +        * The FWU metadata has been read. Now get the image_uuid for the
> +        * image with the update_bank.
> +        */
> +       for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
> +               if (!guidcmp(image_type_id,
> +                            &mdata->img_entry[i].image_type_uuid)) {
> +                       img_entry = &mdata->img_entry[i];
> +                       img_bank_info = &img_entry->img_bank_info[update_bank];
> +                       image_guid = &img_bank_info->image_uuid;
> +                       ret = fwu_plat_get_alt_num(dev, image_guid, alt_num);
> +                       if (ret) {
> +                               log_err("alt_num not found for partition with GUID %pUs\n",
> +                                       image_guid);
> +                       } else {
> +                               log_debug("alt_num %d for partition %pUs\n",
> +                                         *alt_num, image_guid);
> +                       }
> +
> +                       goto out;
> +               }
> +       }
> +
> +       log_err("Partition with the image type %pUs not found\n",
> +               image_type_id);
> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +/**
> + * fwu_mdata_check() - Check if the FWU metadata is valid
> + *
> + * Validate both copies of the FWU metadata. If one of the copies
> + * has gone bad, restore it from the other bad copy.
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_mdata_check(void)
> +{
> +       int ret;
> +       struct udevice *dev = NULL;
> +       const struct fwu_mdata_ops *ops = NULL;
> +
> +       ret = fwu_get_dev_ops(&dev, &ops);
> +       if (ret)
> +               return ret;
> +
> +       if (!ops->mdata_check) {
> +               log_err("mdata_check() method not defined\n");

log_debug() to avoid code-size issue. This is a s/w bug. Please fix
globally and see other uclasses for how this should be done.

> +               return -ENOSYS;
> +       }
> +
> +       return ops->mdata_check(dev);
> +}
> +
> +/**
> + * fwu_revert_boot_index() - Revert the active index in the FWU metadata
> + *
> + * Revert the active_index value in the FWU metadata, by swapping the values
> + * of active_index and previous_active_index in both copies of the
> + * FWU metadata.
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_revert_boot_index(void)
> +{
> +       int ret;
> +       u32 cur_active_index;
> +       struct fwu_mdata *mdata = NULL;
> +
> +       ret = fwu_get_mdata(&mdata);
> +       if (ret < 0) {
> +               log_err("Unable to get valid FWU metadata\n");

This is supposed to be a uclass so it should not be outputting this
sort of thing except in debug mode.

> +               goto out;
> +       }
> +
> +       /*
> +        * Swap the active index and previous_active_index fields
> +        * in the FWU metadata
> +        */
> +       cur_active_index = mdata->active_index;
> +       mdata->active_index = mdata->previous_active_index;
> +       mdata->previous_active_index = cur_active_index;
> +
> +       /*
> +        * Now write this updated FWU metadata to both the
> +        * FWU metadata partitions
> +        */
> +       ret = fwu_update_mdata(mdata);
> +       if (ret < 0) {
> +               log_err("Failed to update FWU metadata partitions\n");
> +               ret = -EIO;
> +       }
> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +/**
> + * fwu_set_clear_image_accept() - Set or Clear the Acceptance bit for the image
> + * @img_type_id: GUID of the image type for which the accepted bit is to be
> + *               set or cleared
> + * @bank: Bank of which the image's Accept bit is to be set or cleared
> + * @action: Action which specifies whether image's Accept bit is to be set or
> + *          cleared
> + *
> + * Set/Clear the accepted bit for the image specified by the img_guid parameter.
> + * This indicates acceptance or rejection of image for subsequent boots by some
> + * governing component like OS(or firmware).
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +static int fwu_set_clear_image_accept(efi_guid_t *img_type_id,
> +                                     u32 bank, u8 action)
> +{
> +       int ret, i;
> +       struct fwu_mdata *mdata = NULL;
> +       struct fwu_image_entry *img_entry;
> +       struct fwu_image_bank_info *img_bank_info;
> +
> +       ret = fwu_get_mdata(&mdata);
> +       if (ret < 0) {
> +               log_err("Unable to get valid FWU metadata\n");
> +               goto out;
> +       }
> +
> +       img_entry = &mdata->img_entry[0];
> +       for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
> +               if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) {
> +                       img_bank_info = &img_entry[i].img_bank_info[bank];
> +                       if (action == IMAGE_ACCEPT_SET)
> +                               img_bank_info->accepted |= FWU_IMAGE_ACCEPTED;
> +                       else
> +                               img_bank_info->accepted = 0;
> +
> +                       ret = fwu_update_mdata(mdata);
> +                       goto out;
> +               }
> +       }
> +
> +       /* Image not found */
> +       ret = -EINVAL;

-ENOENT then?

> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +/**
> + * fwu_accept_image() - Set the Acceptance bit for the image
> + * @img_type_id: GUID of the image type for which the accepted bit is to be
> + *               cleared
> + * @bank: Bank of which the image's Accept bit is to be set
> + *
> + * Set the accepted bit for the image specified by the img_guid parameter. This
> + * indicates acceptance of image for subsequent boots by some governing component
> + * like OS(or firmware).
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
> +{
> +       return fwu_set_clear_image_accept(img_type_id, bank,
> +                                         IMAGE_ACCEPT_SET);

Use fwu_clrset_... since we have something similar in U-Boot

> +}
> +
> +/**
> + * fwu_clear_accept_image() - Clear the Acceptance bit for the image
> + * @img_type_id: GUID of the image type for which the accepted bit is to be
> + *               cleared
> + * @bank: Bank of which the image's Accept bit is to be cleared
> + *
> + * Clear the accepted bit for the image type specified by the img_type_id parameter.
> + * This function is called after the image has been updated. The accepted bit is
> + * cleared to be set subsequently after passing the image acceptance criteria, by
> + * either the OS(or firmware)
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
> +{
> +       return fwu_set_clear_image_accept(img_type_id, bank,
> +                                         IMAGE_ACCEPT_CLEAR);
> +}
> +
> +/**
> + * fwu_get_mdata() - Get a FWU metadata copy
> + * @mdata: Copy of the FWU metadata
> + *
> + * Get a valid copy of the FWU metadata.
> + *
> + * Note: This function is to be called first when modifying any fields
> + * in the metadata. The sequence of calls to modify any field in the
> + * metadata would  be 1) fwu_get_mdata 2) Modify metadata, followed by
> + * 3) fwu_update_mdata
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_get_mdata(struct fwu_mdata **mdata)
> +{
> +       int ret;
> +       struct udevice *dev = NULL;
> +       const struct fwu_mdata_ops *ops = NULL;
> +
> +       ret = fwu_get_dev_ops(&dev, &ops);
> +       if (ret)
> +               return ret;
> +
> +       if (!ops->get_mdata) {
> +               log_err("get_mdata() method not defined\n");
> +               return -ENOSYS;
> +       }
> +
> +       return ops->get_mdata(dev, mdata);
> +}
> +
> +/**
> + * fwu_update_mdata() - Update the FWU metadata
> + * @mdata: Copy of the FWU metadata
> + *
> + * Update the FWU metadata structure by writing to the
> + * FWU metadata partitions.
> + *
> + * Note: This function is not to be called directly to update the
> + * metadata fields. The sequence of function calls should be
> + * 1) fwu_get_mdata() 2) Modify the medata fields 3) fwu_update_mdata()
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_update_mdata(struct fwu_mdata *mdata)
> +{
> +       int ret;
> +       void *buf;
> +       struct udevice *dev = NULL;
> +       const struct fwu_mdata_ops *ops = NULL;
> +
> +       ret = fwu_get_dev_ops(&dev, &ops);
> +       if (ret)
> +               return ret;
> +
> +       if (!ops->update_mdata) {
> +               log_err("get_mdata() method not defined\n");
> +               return -ENOSYS;
> +       }
> +
> +       /*
> +        * Calculate the crc32 for the updated FWU metadata
> +        * and put the updated value in the FWU metadata crc32
> +        * field
> +        */
> +       buf = &mdata->version;
> +       mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> +
> +       return ops->update_mdata(dev, mdata);
> +}
> +
> +UCLASS_DRIVER(fwu_mdata) = {
> +       .id             = UCLASS_FWU_MDATA,
> +       .name           = "fwu-mdata",
> +};
> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> index a432e43871..598a8c10a0 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -58,6 +58,7 @@ enum uclass_id {
>         UCLASS_FIRMWARE,        /* Firmware */
>         UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
>         UCLASS_FS_FIRMWARE_LOADER,              /* Generic loader */
> +       UCLASS_FWU_MDATA,       /* FWU Metadata Access */
>         UCLASS_GPIO,            /* Bank of general-purpose I/O pins */
>         UCLASS_HASH,            /* Hash device */
>         UCLASS_HWSPINLOCK,      /* Hardware semaphores */
> diff --git a/include/fwu.h b/include/fwu.h
> new file mode 100644
> index 0000000000..e03cfff800
> --- /dev/null
> +++ b/include/fwu.h
> @@ -0,0 +1,49 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#if !defined _FWU_H_
> +#define _FWU_H_
> +
> +#include <blk.h>
> +#include <efi.h>
> +
> +#include <linux/types.h>
> +
> +struct fwu_mdata;
> +struct udevice;
> +
> +/**
> + * @mdata_check: check the validity of the FWU metadata partitions
> + * @get_mdata() - Get a FWU metadata copy
> + * @update_mdata() - Update the FWU metadata copy
> + */
> +struct fwu_mdata_ops {
> +       int (*mdata_check)(struct udevice *dev);
> +
> +       int (*get_mdata)(struct udevice *dev, struct fwu_mdata **mdata);
> +
> +       int (*update_mdata)(struct udevice *dev, struct fwu_mdata *mdata);

Needs full comments - see other uclasses

> +};
> +
> +#define FWU_MDATA_VERSION      0x1
> +
> +#define FWU_MDATA_GUID \
> +       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> +                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)

What is this? Comment?

> +
> +int fwu_get_mdata(struct fwu_mdata **mdata);
> +int fwu_update_mdata(struct fwu_mdata *mdata);
> +int fwu_get_active_index(u32 *active_idx);
> +int fwu_update_active_index(u32 active_idx);
> +int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> +                         int *alt_num);
> +int fwu_mdata_check(void);
> +int fwu_revert_boot_index(void);
> +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_alt_num(struct udevice *dev, efi_guid_t *image_guid,
> +                        int *alt_num);

These all need full comments

> +#endif /* _FWU_H_ */
> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> new file mode 100644
> index 0000000000..72e3edab43
> --- /dev/null
> +++ b/include/fwu_mdata.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#if !defined _FWU_MDATA_H_
> +#define _FWU_MDATA_H_
> +
> +#include <efi.h>
> +
> +/**
> + * struct fwu_image_bank_info - firmware image information
> + * @image_uuid: Guid value of the image in this bank
> + * @accepted: Acceptance status of the image
> + * @reserved: Reserved
> + *
> + * The structure contains image specific fields which are
> + * used to identify the image and to specify the image's
> + * acceptance status
> + */
> +struct fwu_image_bank_info {
> +       efi_guid_t  image_uuid;
> +       uint32_t accepted;
> +       uint32_t reserved;
> +} __attribute__((__packed__));

Why is this packed?

> +
> +/**
> + * struct fwu_image_entry - information for a particular type of image
> + * @image_type_uuid: Guid value for identifying the image type
> + * @location_uuid: Guid of the storage volume where the image is located
> + * @img_bank_info: Array containing properties of images
> + *
> + * This structure contains information on various types of updatable
> + * firmware images. Each image type then contains an array of image
> + * information per bank.
> + */
> +struct fwu_image_entry {
> +       efi_guid_t image_type_uuid;
> +       efi_guid_t location_uuid;
> +       struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS];
> +} __attribute__((__packed__));

why packed?

> +
> +/**
> + * struct fwu_mdata - FWU metadata structure for multi-bank updates
> + * @crc32: crc32 value for the FWU metadata
> + * @version: FWU metadata version
> + * @active_index: Index of the bank currently used for booting images
> + * @previous_active_inde: Index of the bank used before the current bank
> + *                        being used for booting
> + * @img_entry: Array of information on various firmware images that can
> + *             be updated
> + *
> + * This structure is used to store all the needed information for performing
> + * multi bank updates on the platform. This contains info on the bank being
> + * used to boot along with the information needed for identification of
> + * individual images
> + */
> +struct fwu_mdata {
> +       uint32_t crc32;
> +       uint32_t version;
> +       uint32_t active_index;
> +       uint32_t previous_active_index;
> +
> +       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> +} __attribute__((__packed__));

same question

> +
> +#endif /* _FWU_MDATA_H_ */
> --
> 2.34.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-08-17 12:43 ` [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
@ 2022-08-18  3:21   ` Simon Glass
  2022-08-18 11:38     ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18  3:21 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> In the FWU Multi Bank Update feature, the information about the
> updatable images is stored as part of the metadata, on a separate
> partition. Add a driver for reading from and writing to the metadata
> when the updatable images and the metadata are stored on a block
> device which is formated with GPT based partition scheme.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> ---
> Changes since V7: None
>
>  drivers/fwu-mdata/Kconfig             |   9 +
>  drivers/fwu-mdata/Makefile            |   1 +
>  drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410 ++++++++++++++++++++++++++
>  include/fwu.h                         |   5 +
>  4 files changed, 425 insertions(+)
>  create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c
>
> diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
> index d6a21c8e19..d5edef19d6 100644
> --- a/drivers/fwu-mdata/Kconfig
> +++ b/drivers/fwu-mdata/Kconfig
> @@ -5,3 +5,12 @@ config DM_FWU_MDATA
>           Enable support for accessing FWU Metadata partitions. The
>           FWU Metadata partitions reside on the same storage device
>           which contains the other FWU updatable firmware images.

Can we link to the docs here, or will it be easy for people to find in
the U-Boot docs?

> +
> +config FWU_MDATA_GPT_BLK
> +       bool "FWU Metadata access for GPT partitioned Block devices"
> +       select PARTITION_TYPE_GUID
> +       select PARTITION_UUIDS
> +       depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION
> +       help
> +         Enable support for accessing FWU Metadata on GPT partitioned
> +         block devices.

GPT-partitioned (I think)

> diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
> index e53a8c9983..313049f67a 100644
> --- a/drivers/fwu-mdata/Makefile
> +++ b/drivers/fwu-mdata/Makefile
> @@ -4,3 +4,4 @@
>  #
>
>  obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
> +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o
> diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c

Perhaps just call it gpt_blk.c since it is in this directory

> new file mode 100644
> index 0000000000..f694c4369b
> --- /dev/null
> +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> @@ -0,0 +1,410 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#define LOG_CATEGORY UCLASS_FWU_MDATA
> +
> +#include <blk.h>
> +#include <dm.h>
> +#include <efi_loader.h>
> +#include <fwu.h>
> +#include <fwu_mdata.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <memalign.h>
> +#include <part.h>
> +#include <part_efi.h>
> +
> +#include <dm/device-internal.h>
> +#include <linux/errno.h>
> +#include <linux/types.h>
> +#include <u-boot/crc.h>
> +
> +#define PRIMARY_PART           BIT(0)
> +#define SECONDARY_PART         BIT(1)
> +#define BOTH_PARTS             (PRIMARY_PART | SECONDARY_PART)
> +
> +#define MDATA_READ             BIT(0)
> +#define MDATA_WRITE            BIT(1)
> +

comment?

> +static int gpt_get_mdata_partitions(struct blk_desc *desc,
> +                                   u16 *primary_mpart,
> +                                   u16 *secondary_mpart)

Should use uint, no need to select a 16-bit var so far as I can get

> +{
> +       int i, ret;
> +       u32 mdata_parts;
> +       efi_guid_t part_type_guid;
> +       struct disk_partition info;
> +       const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID;
> +
> +       mdata_parts = 0;
> +       for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
> +               if (part_get_info(desc, i, &info))
> +                       continue;
> +               uuid_str_to_bin(info.type_guid, part_type_guid.b,
> +                               UUID_STR_FORMAT_GUID);
> +
> +               if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) {
> +                       ++mdata_parts;
> +                       if (!*primary_mpart)
> +                               *primary_mpart = i;
> +                       else
> +                               *secondary_mpart = i;
> +               }
> +       }
> +
> +       if (mdata_parts != 2) {
> +               log_err("Expect two copies of the FWU metadata instead of %d\n",
> +                       mdata_parts);
> +               ret = -EINVAL;
> +       } else {
> +               ret = 0;
> +       }
> +
> +       return ret;
> +}
> +
> +static int gpt_get_mdata_disk_part(struct blk_desc *desc,
> +                                  struct disk_partition *info,
> +                                  u32 part_num)
> +{
> +       int ret;
> +       char *mdata_guid_str = "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23";

This is fine, but I wonder if it should that go in a header with all
the other GUIDs? Or does it go hear because it is a string?

> +
> +       ret = part_get_info(desc, part_num, info);
> +       if (ret < 0) {
> +               log_err("Unable to get the partition info for the FWU metadata part %d",
> +                       part_num);
> +               return -1;
> +       }
> +
> +       /* Check that it is indeed the FWU metadata partition */
> +       if (!strncmp(info->type_guid, mdata_guid_str, UUID_STR_LEN)) {
> +               /* Found the FWU metadata partition */
> +               return 0;
> +       }
> +
> +       return -1;
> +}
> +
> +static int gpt_read_write_mdata(struct blk_desc *desc,
> +                               struct fwu_mdata *mdata,
> +                               u8 access, u32 part_num)
> +{
> +       int ret;
> +       u32 len, blk_start, blkcnt;
> +       struct disk_partition info;
> +
> +       ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1,
> +                                    desc->blksz);
> +
> +       ret = gpt_get_mdata_disk_part(desc, &info, part_num);
> +       if (ret < 0) {
> +               printf("Unable to get the FWU metadata partition\n");
> +               return -ENODEV;

How about -ENOENT ?

There is a device, so we cannot use -ENODEV

Please fix below too

> +       }
> +
> +       len = sizeof(*mdata);
> +       blkcnt = BLOCK_CNT(len, desc);
> +       if (blkcnt > info.size) {
> +               log_err("Block count exceeds FWU metadata partition size\n");
> +               return -ERANGE;
> +       }
> +
> +       blk_start = info.start;
> +       if (access == MDATA_READ) {
> +               if (blk_dread(desc, blk_start, blkcnt, mdata_aligned) != blkcnt) {
> +                       log_err("Error reading FWU metadata from the device\n");
> +                       return -EIO;
> +               }
> +               memcpy(mdata, mdata_aligned, sizeof(struct fwu_mdata));
> +       } else {
> +               if (blk_dwrite(desc, blk_start, blkcnt, mdata) != blkcnt) {
> +                       log_err("Error writing FWU metadata to the device\n");
> +                       return -EIO;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +static int gpt_read_mdata(struct blk_desc *desc,
> +                         struct fwu_mdata *mdata, u32 part_num)
> +{
> +       return gpt_read_write_mdata(desc, mdata, MDATA_READ, part_num);
> +}
> +
> +static int gpt_write_mdata_partition(struct blk_desc *desc,
> +                                       struct fwu_mdata *mdata,
> +                                       u32 part_num)
> +{
> +       return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, part_num);
> +}
> +
> +static int fwu_gpt_update_mdata(struct udevice *dev, struct fwu_mdata *mdata)
> +{
> +       int ret;
> +       struct blk_desc *desc;
> +       u16 primary_mpart = 0, secondary_mpart = 0;

uint

> +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> +
> +       desc = dev_get_uclass_plat(priv->blk_dev);
> +       if (!desc) {
> +               log_err("Block device not found\n");
> +               return -ENODEV;

This cannot happen, drop this if()

> +       }
> +
> +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> +                                      &secondary_mpart);
> +

drop blank line so the error check is next to the thing that reads it

> +       if (ret < 0) {
> +               log_err("Error getting the FWU metadata partitions\n");
> +               return -ENODEV;
> +       }
> +
> +       /* First write the primary partition*/

space before */

> +       ret = gpt_write_mdata_partition(desc, mdata, primary_mpart);
> +       if (ret < 0) {
> +               log_err("Updating primary FWU metadata partition failed\n");

This is very error-heavy. The log_err() things produce a string in the
code so this ends up being very large. Is that what you want? If these
things can happen in the real world and users need to debug them, then
I suppose it is OK. But normally with driver model we report errors in
the command code, or the logic, not in drivers themselves. Otherwise
when you write tests you get lots of confusing error output that needs
to be ignored.

> +               return ret;
> +       }
> +
> +       /* And now the replica */
> +       ret = gpt_write_mdata_partition(desc, mdata, secondary_mpart);
> +       if (ret < 0) {
> +               log_err("Updating secondary FWU metadata partition failed\n");
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata)

mdatap

> +{
> +       int ret;
> +       u16 primary_mpart = 0, secondary_mpart = 0;

uint

Also do you need to set them to 0

Declare a locate mdata and use that here instead of *mdata, which is a pain.

> +
> +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> +                                      &secondary_mpart);
> +
> +       if (ret < 0) {
> +               log_err("Error getting the FWU metadata partitions\n");
> +               return -ENODEV;
> +       }
> +
> +       *mdata = malloc(sizeof(struct fwu_mdata));
> +       if (!*mdata) {
> +               log_err("Unable to allocate memory for reading FWU metadata\n");
> +               return -ENOMEM;
> +       }
> +
> +       ret = gpt_read_mdata(desc, *mdata, primary_mpart);
> +       if (ret < 0) {
> +               log_err("Failed to read the FWU metadata from the device\n");
> +               return -EIO;
> +       }
> +
> +       ret = fwu_verify_mdata(*mdata, 1);
> +       if (!ret)
> +               return 0;
> +
> +       /*
> +        * Verification of the primary FWU metadata copy failed.
> +        * Try to read the replica.
> +        */
> +       memset(*mdata, 0, sizeof(struct fwu_mdata));

'\0'

> +       ret = gpt_read_mdata(desc, *mdata, secondary_mpart);
> +       if (ret < 0) {
> +               log_err("Failed to read the FWU metadata from the device\n");
> +               return -EIO;
> +       }
> +
> +       ret = fwu_verify_mdata(*mdata, 0);
> +       if (!ret)
> +               return 0;
> +
> +       /* Both the FWU metadata copies are corrupted. */
> +       return -1;

This is -EPERM

Perhaps choose something else?

> +}
> +
> +static int gpt_check_mdata_validity(struct udevice *dev)
> +{
> +       int ret;
> +       struct blk_desc *desc;
> +       struct fwu_mdata pri_mdata;
> +       struct fwu_mdata secondary_mdata;
> +       u16 primary_mpart = 0, secondary_mpart = 0;
> +       u16 valid_partitions, invalid_partitions;
> +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> +
> +       desc = dev_get_uclass_plat(priv->blk_dev);
> +       if (!desc) {
> +               log_err("Block device not found\n");
> +               return -ENODEV;
> +       }
> +
> +       /*
> +        * Two FWU metadata partitions are expected.
> +        * If we don't have two, user needs to create
> +        * them first
> +        */
> +       valid_partitions = 0;
> +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> +                                      &secondary_mpart);
> +
> +       if (ret < 0) {
> +               log_err("Error getting the FWU metadata partitions\n");
> +               return -ENODEV;
> +       }
> +
> +       ret = gpt_read_mdata(desc, &pri_mdata, primary_mpart);
> +       if (ret < 0) {
> +               log_err("Failed to read the FWU metadata from the device\n");
> +               goto secondary_read;
> +       }
> +
> +       ret = fwu_verify_mdata(&pri_mdata, 1);
> +       if (!ret)
> +               valid_partitions |= PRIMARY_PART;
> +
> +secondary_read:
> +       /* Now check the secondary partition */
> +       ret = gpt_read_mdata(desc, &secondary_mdata, secondary_mpart);
> +       if (ret < 0) {
> +               log_err("Failed to read the FWU metadata from the device\n");
> +               goto mdata_restore;
> +       }
> +
> +       ret = fwu_verify_mdata(&secondary_mdata, 0);
> +       if (!ret)
> +               valid_partitions |= SECONDARY_PART;
> +
> +mdata_restore:
> +       if (valid_partitions == (PRIMARY_PART | SECONDARY_PART)) {
> +               ret = -1;
> +               /*
> +                * Before returning, check that both the
> +                * FWU metadata copies are the same. If not,
> +                * the FWU metadata copies need to be
> +                * re-populated.
> +                */
> +               if (!memcmp(&pri_mdata, &secondary_mdata,
> +                           sizeof(struct fwu_mdata))) {
> +                       ret = 0;
> +               } else {
> +                       log_err("Both FWU metadata copies are valid but do not match. Please check!\n");

Honestly the error handling needs a rethink IMO. You should try to
return error codes that indicate what went wrong (you mostly do in
this file) and then have the top-level code decode those errors and
produce an error message.

> +               }
> +               goto out;
> +       }
> +
> +       ret = -1;
> +       if (!(valid_partitions & BOTH_PARTS))
> +               goto out;
> +
> +       invalid_partitions = valid_partitions ^ BOTH_PARTS;
> +       ret = gpt_write_mdata_partition(desc,
> +                                       (invalid_partitions == PRIMARY_PART) ?
> +                                       &secondary_mdata : &pri_mdata,
> +                                       (invalid_partitions == PRIMARY_PART) ?
> +                                       primary_mpart : secondary_mpart);
> +
> +       if (ret < 0)
> +               log_err("Restoring %s FWU metadata partition failed\n",
> +                       (invalid_partitions == PRIMARY_PART) ?
> +                       "primary" : "secondary");
> +
> +out:
> +       return ret;
> +}
> +
> +static int fwu_gpt_mdata_check(struct udevice *dev)
> +{
> +       /*
> +        * Check if both the copies of the FWU metadata are
> +        * valid. If one has gone bad, restore it from the
> +        * other good copy.

word wrap wider

> +        */
> +       return gpt_check_mdata_validity(dev);
> +}
> +
> +static int fwu_gpt_get_mdata(struct udevice *dev, struct fwu_mdata **mdata)
> +{
> +       struct blk_desc *desc;
> +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> +
> +       desc = dev_get_uclass_plat(priv->blk_dev);
> +       if (!desc) {
> +               log_err("Block device not found\n");
> +               return -ENODEV;

Again this cannot happen

> +       }
> +
> +       return gpt_get_mdata(desc, mdata);
> +}
> +
> +static int fwu_get_mdata_device(struct udevice *dev, struct udevice **mdata_dev)
> +{
> +       u32 phandle;
> +       int ret, size;
> +       struct udevice *parent, *child;
> +       const fdt32_t *phandle_p = NULL;
> +
> +       phandle_p = dev_read_prop(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);

Can you use dev_read_u32() ?

> +
> +       ret = device_get_global_by_ofnode(ofnode_get_by_phandle(phandle),
> +                                         &parent);
> +       if (ret)
> +               return ret;
> +
> +       ret = -ENODEV;

Here it is correct to return -ENODEV I think

> +       for (device_find_first_child(parent, &child); child;
> +            device_find_next_child(&child)) {
> +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> +                       *mdata_dev = child;
> +                       ret = 0;

See blk_get_from_parent()

> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> +{
> +       int ret;
> +       struct udevice *mdata_dev = NULL;
> +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> +
> +       ret = fwu_get_mdata_device(dev, &mdata_dev);
> +       if (ret)
> +               return ret;
> +
> +       priv->blk_dev = mdata_dev;
> +
> +       return 0;
> +}
> +
> +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> +       .mdata_check = fwu_gpt_mdata_check,
> +       .get_mdata = fwu_gpt_get_mdata,
> +       .update_mdata = fwu_gpt_update_mdata,
> +};
> +
> +static const struct udevice_id fwu_mdata_ids[] = {
> +       { .compatible = "u-boot,fwu-mdata-gpt" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(fwu_mdata_gpt_blk) = {
> +       .name           = "fwu-mdata-gpt-blk",
> +       .id             = UCLASS_FWU_MDATA,
> +       .of_match       = fwu_mdata_ids,
> +       .ops            = &fwu_gpt_blk_ops,
> +       .probe          = fwu_mdata_gpt_blk_probe,
> +       .priv_auto      = sizeof(struct fwu_mdata_gpt_blk_priv),
> +};
> diff --git a/include/fwu.h b/include/fwu.h
> index e03cfff800..8259c75d12 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -14,6 +14,10 @@
>  struct fwu_mdata;
>  struct udevice;
>
> +struct fwu_mdata_gpt_blk_priv {
> +       struct udevice *blk_dev;
> +};
> +
>  /**
>   * @mdata_check: check the validity of the FWU metadata partitions
>   * @get_mdata() - Get a FWU metadata copy
> @@ -39,6 +43,7 @@ int fwu_get_active_index(u32 *active_idx);
>  int fwu_update_active_index(u32 active_idx);
>  int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
>                           int *alt_num);
> +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part);

comments again

>  int fwu_mdata_check(void);
>  int fwu_revert_boot_index(void);
>  int fwu_accept_image(efi_guid_t *img_type_id, u32 bank);
> --
> 2.34.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification
  2022-08-17 12:43 ` [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2022-08-18  3:21   ` Simon Glass
  2022-08-18 11:41     ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18  3:21 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> The FWU Multi Bank Update specification requires the Update Agent to
> carry out certain checks at the time of platform boot. The Update
> Agent is the component which is responsible for updating the firmware
> components and maintaining and keeping the metadata in sync.
>
> The spec requires that the Update Agent perform the following checks
> at the time of boot
> * Sanity check of both the metadata copies maintained by the platform.
> * Get the boot index passed to U-Boot by the prior stage bootloader
>   and use this value for metadata bookkeeping.
> * Check if the system is booting in Trial State. If the system boots
>   in the Trial State for more than a specified number of boot counts,
>   change the Active Bank to be booting the platform from.
>
> Add these checks in the board initialisation sequence, invoked after
> relocation.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> Changes since V7:
> * Introduce trial_counter_update() to increment and delete the
>   TrialStateCtr variable.
> * Introduce in_trial_state() to check if the platform is booting in
>   Trial State.
>
>  common/board_r.c      |   5 ++
>  include/fwu.h         |   3 +
>  lib/fwu_updates/fwu.c | 175 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 183 insertions(+)

We should use the event system instead of adding another hook. We are
trying to get rid of them!

Also, please separate out the fwu change from touching common code
(although you may not need to touch comment code with events).

Regards,
SImon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-17 12:43 ` [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
@ 2022-08-18  3:21   ` Simon Glass
  2022-08-18 11:53     ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18  3:21 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sugosh,

On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> Add a command to read the metadata as specified in the FWU
> specification and print the fields of the metadata.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> ---
> Changes since V7: None
>
>  cmd/Kconfig     |  7 +++++
>  cmd/Makefile    |  1 +
>  cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 88 insertions(+)
>  create mode 100644 cmd/fwu_mdata.c

This needs docs and a test.

BTW I forgot to mention that the uclass needs a simple test of some sort.

https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html

Regards,
SImon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature
  2022-08-17 12:43 ` [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
@ 2022-08-18  3:21   ` Simon Glass
  2022-08-23  8:24     ` Ilias Apalodimas
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18  3:21 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> Add documentattion for the FWU Multi Bank Update feature. The document

spelling

> describes the steps needed for setting up the platform for the
> feature, as well as steps for enabling the feature on the platform.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> Changes since V7:
> * Handle the various review comments from Heinrich.
>
>  doc/develop/uefi/fwu_updates.rst | 165 +++++++++++++++++++++++++++++++
>  doc/develop/uefi/index.rst       |   1 +
>  doc/develop/uefi/uefi.rst        |   2 +
>  3 files changed, 168 insertions(+)
>  create mode 100644 doc/develop/uefi/fwu_updates.rst

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates
  2022-08-17 12:43 ` [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates Sughosh Ganu
@ 2022-08-18  8:05   ` Yann Gautier
  2022-08-18 12:06     ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Yann Gautier @ 2022-08-18  8:05 UTC (permalink / raw)
  To: u-boot

On 8/17/22 14:43, Sughosh Ganu wrote:
> Enabling capsule update functionality on the platform requires
> populating information on the images that are to be updated using the
> functionality. Do so for the DK2 board.
> 
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> ---
> Changes since V7: None
> 
>   board/st/stm32mp1/stm32mp1.c       | 23 +++++++++++++++++++++++
>   include/configs/stm32mp15_common.h |  4 ++++
>   2 files changed, 27 insertions(+)
> 
> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> index 9496890d16..0fda8f150d 100644
> --- a/board/st/stm32mp1/stm32mp1.c
> +++ b/board/st/stm32mp1/stm32mp1.c
> @@ -11,6 +11,7 @@
>   #include <clk.h>
>   #include <config.h>
>   #include <dm.h>
> +#include <efi_loader.h>
>   #include <env.h>
>   #include <env_internal.h>
>   #include <fdt_simplefb.h>
> @@ -87,6 +88,16 @@
>   #define USB_START_LOW_THRESHOLD_UV	1230000
>   #define USB_START_HIGH_THRESHOLD_UV	2150000
>   
> +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
> +struct efi_fw_image fw_images[1];
> +
> +struct efi_capsule_update_info update_info = {
> +	.images = fw_images,
> +};
> +
> +u8 num_image_type_guids = ARRAY_SIZE(fw_images);
> +#endif /* EFI_HAVE_CAPSULE_SUPPORT */
> +
>   int board_early_init_f(void)
>   {
>   	/* nothing to do, only used in SPL */
> @@ -670,6 +681,18 @@ int board_init(void)
>   
>   	setup_led(LEDST_ON);
>   
> +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
> +	if (board_is_stm32mp15x_dk2()) {
> +		efi_guid_t image_type_guid = STM32MP15_DK2_FIP_IMAGE_GUID;
> +		guidcpy(&fw_images[0].image_type_id, &image_type_guid);
> +		fw_images[0].fw_name = u"STM32MP15-DK2-FIP";
> +		/*
> +		 * For FWU multi bank update, the image
> +		 * index will be computed at runtime
> +		 */
> +		fw_images[0].image_index = 0;
> +	}
> +#endif
>   	return 0;
>   }
>   
> diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h
> index c5412ffeb3..6ab10d8ce5 100644
> --- a/include/configs/stm32mp15_common.h
> +++ b/include/configs/stm32mp15_common.h
> @@ -34,6 +34,10 @@
>   #define CONFIG_SERVERIP                 192.168.1.1
>   #endif
>   

Hi Sugosh,

Sorry for the late review.

> +#define STM32MP15_DK2_FIP_IMAGE_GUID \
Although this is now only supported on this STM32MP15_DK2 board, I don't 
think this macro should be tight to the board name, as it may be used 
for other STM32MP boards. I'd just use STM32MP_FIP_IMAGE_GUID.
This should be the same for the fw_images[0].fw_name.


Best regards,
Yann

> +	EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \
> +		 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5)
> +
>   /*****************************************************************************/
>   #ifdef CONFIG_DISTRO_DEFAULTS
>   /*****************************************************************************/


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-18  1:13   ` Simon Glass
@ 2022-08-18 11:03     ` Sughosh Ganu
  2022-08-18 17:49       ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-18 11:03 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 06:43, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > In the FWU Multi Bank Update feature, the information about the
> > updatable images is stored as part of the metadata, which is stored on
> > a dedicated partition. Add the metadata structure, and a driver model
> > uclass which provides functions to access the metadata. These are
> > generic API's, and implementations can be added based on parameters
> > like how the metadata partition is accessed and what type of storage
> > device houses the metadata.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > ---
> > Changes since V7:
> > * Rephrased the error message in fwu_update_active_index as per
> >   suggestion from Ilias.
> > * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
> >   from Ilias.
> >
> >  drivers/Kconfig                      |   2 +
> >  drivers/Makefile                     |   1 +
> >  drivers/fwu-mdata/Kconfig            |   7 +
> >  drivers/fwu-mdata/Makefile           |   6 +
> >  drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
> >  include/dm/uclass-id.h               |   1 +
> >  include/fwu.h                        |  49 +++
> >  include/fwu_mdata.h                  |  67 ++++
> >  8 files changed, 596 insertions(+)
> >  create mode 100644 drivers/fwu-mdata/Kconfig
> >  create mode 100644 drivers/fwu-mdata/Makefile
> >  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
> >  create mode 100644 include/fwu.h
> >  create mode 100644 include/fwu_mdata.h
> >
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index 8b6fead351..75ac149d31 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -44,6 +44,8 @@ source "drivers/fuzz/Kconfig"
> >
> >  source "drivers/fpga/Kconfig"
> >
> > +source "drivers/fwu-mdata/Kconfig"
> > +
> >  source "drivers/gpio/Kconfig"
> >
> >  source "drivers/hwspinlock/Kconfig"
> > diff --git a/drivers/Makefile b/drivers/Makefile
> > index eba9940231..70bbc2f5e0 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -84,6 +84,7 @@ obj-y += cache/
> >  obj-$(CONFIG_CPU) += cpu/
> >  obj-y += crypto/
> >  obj-$(CONFIG_FASTBOOT) += fastboot/
> > +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata/
> >  obj-y += misc/
> >  obj-$(CONFIG_MMC) += mmc/
> >  obj-$(CONFIG_NVME) += nvme/
> > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
> > new file mode 100644
> > index 0000000000..d6a21c8e19
> > --- /dev/null
> > +++ b/drivers/fwu-mdata/Kconfig
> > @@ -0,0 +1,7 @@
> > +config DM_FWU_MDATA
>
> Please drop DM_ as there is no non-DM version

Okay

>
>
> > +       bool "Driver support for accessing FWU Metadata"
> > +       depends on DM
> > +       help
> > +         Enable support for accessing FWU Metadata partitions. The
> > +         FWU Metadata partitions reside on the same storage device
> > +         which contains the other FWU updatable firmware images.
> > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
> > new file mode 100644
> > index 0000000000..e53a8c9983
> > --- /dev/null
> > +++ b/drivers/fwu-mdata/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0-or-later
> > +#
> > +# Copyright (c) 2022, Linaro Limited
> > +#
> > +
> > +obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
> > diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c
> > new file mode 100644
> > index 0000000000..6bf7fa1b03
> > --- /dev/null
> > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> > @@ -0,0 +1,463 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright (c) 2022, Linaro Limited
> > + */
> > +
> > +#define LOG_CATEGORY UCLASS_FWU_MDATA
> > +
> > +#include <common.h>
> > +#include <dm.h>
> > +#include <efi_loader.h>
> > +#include <fwu.h>
> > +#include <fwu_mdata.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +
> > +#include <linux/errno.h>
> > +#include <linux/types.h>
> > +#include <u-boot/crc.h>
> > +
> > +#define IMAGE_ACCEPT_SET       BIT(0)
> > +#define IMAGE_ACCEPT_CLEAR     BIT(1)
> > +
> > +static int fwu_get_dev_ops(struct udevice **dev,
> > +                          const struct fwu_mdata_ops **ops)
> > +{
> > +       int ret;
> > +
> > +       ret = uclass_get_device(UCLASS_FWU_MDATA, 0, dev);
>
> uclass_first_device() if there is only one

Okay

>
> > +       if (ret) {
> > +               log_debug("Cannot find fwu device\n");
> > +               return ret;
> > +       }
> > +
> > +       if ((*ops = device_get_ops(*dev)) == NULL) {
> > +               log_debug("Cannot get fwu device ops\n");
> > +               return -ENOSYS;
> > +       }
>
> This is actually a bug, so drop this. It is OK to have an assert() if
> you want one.

Okay

>
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * fwu_verify_mdata() - Verify the FWU metadata
> > + * @mdata: FWU metadata structure
> > + * @pri_part: FWU metadata partition is primary or secondary
> > + *
> > + * Verify the FWU metadata by computing the CRC32 for the metadata
> > + * structure and comparing it against the CRC32 value stored as part
> > + * of the structure.
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part)
> > +{
> > +       u32 calc_crc32;
> > +       void *buf;
> > +
> > +       buf = &mdata->version;
> > +       calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> > +
> > +       if (calc_crc32 != mdata->crc32) {
> > +               log_err("crc32 check failed for %s FWU metadata partition\n",
> > +                       pri_part ? "primary" : "secondary");
> > +               return -1;
>
> Please use an -Exxx value like -EPERM

I don't think there is any value which relates to a crc mismatch. If
you insist, I can think of -EIO, but I don't think -EPERM is a good
match in this case.

>
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * fwu_get_active_index() - Get active_index from the FWU metadata
> > + * @active_idx: active_index value to be read
> > + *
> > + * Read the active_index field from the FWU metadata and place it in
> > + * the variable pointed to be the function argument.
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_get_active_index(u32 *active_idx)
>
> Return the active index rather than having an arg?

I would prefer to keep it the way it is. That allows returning an
error value and keep the active_index separate. Moreover it is just a
single parameter.

>
> > +{
> > +       int ret;
> > +       struct fwu_mdata *mdata = NULL;
> > +
> > +       ret = fwu_get_mdata(&mdata);
>
> Can you use a local var and avoid the malloc() / free() ?

Do you see any disadvantages of using space on the heap? If you don't
have a strong opinion on this, I would prefer to keep it as is.

>
> > +       if (ret < 0) {
> > +               log_err("Unable to get valid FWU metadata\n");
> > +               goto out;
> > +       }
> > +
> > +       /*
> > +        * Found the FWU metadata partition, now read the active_index
> > +        * value
> > +        */
> > +       *active_idx = mdata->active_index;
> > +       if (*active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> > +               log_err("Active index value read is incorrect\n");
> > +               ret = -EINVAL;
> > +       }
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> > + * fwu_update_active_index() - Update active_index from the FWU metadata
> > + * @active_idx: active_index value to be updated
> > + *
> > + * Update the active_index field in the FWU metadata
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_update_active_index(u32 active_idx)
>
> uint

Are you referring to the function parameter? If so, it is a u32 since
the active_index field in the metadata structure defined in the spec
is a 32 bit value.

>
> > +{
> > +       int ret;
> > +       struct fwu_mdata *mdata = NULL;
> > +
> > +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
>
> >= CONFIG_FWU_NUM_BANKS
>
> > +               log_err("Invalid active index value\n");
> > +               return -1;
>
> error code, pleae fix globally

Okay

>
> > +       }
> > +
> > +       ret = fwu_get_mdata(&mdata);
> > +       if (ret < 0) {
> > +               log_err("Unable to get valid FWU metadata\n");
> > +               goto out;
> > +       }
> > +
> > +       /*
> > +        * Update the active index and previous_active_index fields
> > +        * in the FWU metadata
> > +        */
> > +       mdata->previous_active_index = mdata->active_index;
> > +       mdata->active_index = active_idx;
> > +
> > +       /*
> > +        * Now write this updated FWU metadata to both the
> > +        * FWU metadata partitions
> > +        */
> > +       ret = fwu_update_mdata(mdata);
> > +       if (ret < 0) {
> > +               log_err("Failed to update FWU metadata partitions\n");
> > +               ret = -EIO;
> > +       }
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> > + * fwu_get_image_alt_num() - Get the dfu alt number to be used for capsule update
> > + * @image_type_id: pointer to the image GUID as passed in the capsule
> > + * @update_bank: Bank to which the update is to be made
> > + * @alt_num: The alt_num for the image
> > + *
> > + * Based on the GUID value passed in the capsule, along with the bank to which the
> > + * image needs to be updated, get the dfu alt number which will be used for the
> > + * capsule update
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> > +                         int *alt_num)
>
> alt_nump is often used with driver model to indicate a return
> value.Again I wonder if the return value could be used?

Can you point me to an example? I could not find any instance of this.
Again, I believe this is a matter of taste, so I would prefer the
current method.

>
> > +{
> > +       int ret, i;
> > +       efi_guid_t *image_guid;
> > +       struct udevice *dev = NULL;
> > +       struct fwu_mdata *mdata = NULL;
>
> Please don't set things to NULL for no reason, it cluttlers the code.

This is being set to NULL in case the called function that is supposed
to populate the metadata structure fails to do so. We can pass NULL to
free, else it could result in freeing up of unrelated memory.

>
> > +       struct fwu_image_entry *img_entry;
> > +       const struct fwu_mdata_ops *ops = NULL;
> > +       struct fwu_image_bank_info *img_bank_info;
> > +
> > +       ret = fwu_get_dev_ops(&dev, &ops);
>
> Rather than this, see the pattern used by other uclasses

Can you point me to some example code. Also, not sure what the issue
is with using this function.

>
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = fwu_get_mdata(&mdata);
> > +       if (ret) {
> > +               log_err("Unable to get valid FWU metadata\n");
> > +               goto out;
> > +       }
> > +
> > +       ret = -EINVAL;
> > +       /*
> > +        * The FWU metadata has been read. Now get the image_uuid for the
> > +        * image with the update_bank.
> > +        */
> > +       for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
> > +               if (!guidcmp(image_type_id,
> > +                            &mdata->img_entry[i].image_type_uuid)) {
> > +                       img_entry = &mdata->img_entry[i];
> > +                       img_bank_info = &img_entry->img_bank_info[update_bank];
> > +                       image_guid = &img_bank_info->image_uuid;
> > +                       ret = fwu_plat_get_alt_num(dev, image_guid, alt_num);
> > +                       if (ret) {
> > +                               log_err("alt_num not found for partition with GUID %pUs\n",
> > +                                       image_guid);
> > +                       } else {
> > +                               log_debug("alt_num %d for partition %pUs\n",
> > +                                         *alt_num, image_guid);
> > +                       }
> > +
> > +                       goto out;
> > +               }
> > +       }
> > +
> > +       log_err("Partition with the image type %pUs not found\n",
> > +               image_type_id);
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> > + * fwu_mdata_check() - Check if the FWU metadata is valid
> > + *
> > + * Validate both copies of the FWU metadata. If one of the copies
> > + * has gone bad, restore it from the other bad copy.
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_mdata_check(void)
> > +{
> > +       int ret;
> > +       struct udevice *dev = NULL;
> > +       const struct fwu_mdata_ops *ops = NULL;
> > +
> > +       ret = fwu_get_dev_ops(&dev, &ops);
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!ops->mdata_check) {
> > +               log_err("mdata_check() method not defined\n");
>
> log_debug() to avoid code-size issue. This is a s/w bug. Please fix
> globally and see other uclasses for how this should be done.

Okay

>
> > +               return -ENOSYS;
> > +       }
> > +
> > +       return ops->mdata_check(dev);
> > +}
> > +
> > +/**
> > + * fwu_revert_boot_index() - Revert the active index in the FWU metadata
> > + *
> > + * Revert the active_index value in the FWU metadata, by swapping the values
> > + * of active_index and previous_active_index in both copies of the
> > + * FWU metadata.
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_revert_boot_index(void)
> > +{
> > +       int ret;
> > +       u32 cur_active_index;
> > +       struct fwu_mdata *mdata = NULL;
> > +
> > +       ret = fwu_get_mdata(&mdata);
> > +       if (ret < 0) {
> > +               log_err("Unable to get valid FWU metadata\n");
>
> This is supposed to be a uclass so it should not be outputting this
> sort of thing except in debug mode.

Will fix

>
> > +               goto out;
> > +       }
> > +
> > +       /*
> > +        * Swap the active index and previous_active_index fields
> > +        * in the FWU metadata
> > +        */
> > +       cur_active_index = mdata->active_index;
> > +       mdata->active_index = mdata->previous_active_index;
> > +       mdata->previous_active_index = cur_active_index;
> > +
> > +       /*
> > +        * Now write this updated FWU metadata to both the
> > +        * FWU metadata partitions
> > +        */
> > +       ret = fwu_update_mdata(mdata);
> > +       if (ret < 0) {
> > +               log_err("Failed to update FWU metadata partitions\n");
> > +               ret = -EIO;
> > +       }
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> > + * fwu_set_clear_image_accept() - Set or Clear the Acceptance bit for the image
> > + * @img_type_id: GUID of the image type for which the accepted bit is to be
> > + *               set or cleared
> > + * @bank: Bank of which the image's Accept bit is to be set or cleared
> > + * @action: Action which specifies whether image's Accept bit is to be set or
> > + *          cleared
> > + *
> > + * Set/Clear the accepted bit for the image specified by the img_guid parameter.
> > + * This indicates acceptance or rejection of image for subsequent boots by some
> > + * governing component like OS(or firmware).
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +static int fwu_set_clear_image_accept(efi_guid_t *img_type_id,
> > +                                     u32 bank, u8 action)
> > +{
> > +       int ret, i;
> > +       struct fwu_mdata *mdata = NULL;
> > +       struct fwu_image_entry *img_entry;
> > +       struct fwu_image_bank_info *img_bank_info;
> > +
> > +       ret = fwu_get_mdata(&mdata);
> > +       if (ret < 0) {
> > +               log_err("Unable to get valid FWU metadata\n");
> > +               goto out;
> > +       }
> > +
> > +       img_entry = &mdata->img_entry[0];
> > +       for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
> > +               if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) {
> > +                       img_bank_info = &img_entry[i].img_bank_info[bank];
> > +                       if (action == IMAGE_ACCEPT_SET)
> > +                               img_bank_info->accepted |= FWU_IMAGE_ACCEPTED;
> > +                       else
> > +                               img_bank_info->accepted = 0;
> > +
> > +                       ret = fwu_update_mdata(mdata);
> > +                       goto out;
> > +               }
> > +       }
> > +
> > +       /* Image not found */
> > +       ret = -EINVAL;
>
> -ENOENT then?

Okay

>
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +/**
> > + * fwu_accept_image() - Set the Acceptance bit for the image
> > + * @img_type_id: GUID of the image type for which the accepted bit is to be
> > + *               cleared
> > + * @bank: Bank of which the image's Accept bit is to be set
> > + *
> > + * Set the accepted bit for the image specified by the img_guid parameter. This
> > + * indicates acceptance of image for subsequent boots by some governing component
> > + * like OS(or firmware).
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
> > +{
> > +       return fwu_set_clear_image_accept(img_type_id, bank,
> > +                                         IMAGE_ACCEPT_SET);
>
> Use fwu_clrset_... since we have something similar in U-Boot

Will change

>
> > +}
> > +
> > +/**
> > + * fwu_clear_accept_image() - Clear the Acceptance bit for the image
> > + * @img_type_id: GUID of the image type for which the accepted bit is to be
> > + *               cleared
> > + * @bank: Bank of which the image's Accept bit is to be cleared
> > + *
> > + * Clear the accepted bit for the image type specified by the img_type_id parameter.
> > + * This function is called after the image has been updated. The accepted bit is
> > + * cleared to be set subsequently after passing the image acceptance criteria, by
> > + * either the OS(or firmware)
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
> > +{
> > +       return fwu_set_clear_image_accept(img_type_id, bank,
> > +                                         IMAGE_ACCEPT_CLEAR);
> > +}
> > +
> > +/**
> > + * fwu_get_mdata() - Get a FWU metadata copy
> > + * @mdata: Copy of the FWU metadata
> > + *
> > + * Get a valid copy of the FWU metadata.
> > + *
> > + * Note: This function is to be called first when modifying any fields
> > + * in the metadata. The sequence of calls to modify any field in the
> > + * metadata would  be 1) fwu_get_mdata 2) Modify metadata, followed by
> > + * 3) fwu_update_mdata
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_get_mdata(struct fwu_mdata **mdata)
> > +{
> > +       int ret;
> > +       struct udevice *dev = NULL;
> > +       const struct fwu_mdata_ops *ops = NULL;
> > +
> > +       ret = fwu_get_dev_ops(&dev, &ops);
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!ops->get_mdata) {
> > +               log_err("get_mdata() method not defined\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       return ops->get_mdata(dev, mdata);
> > +}
> > +
> > +/**
> > + * fwu_update_mdata() - Update the FWU metadata
> > + * @mdata: Copy of the FWU metadata
> > + *
> > + * Update the FWU metadata structure by writing to the
> > + * FWU metadata partitions.
> > + *
> > + * Note: This function is not to be called directly to update the
> > + * metadata fields. The sequence of function calls should be
> > + * 1) fwu_get_mdata() 2) Modify the medata fields 3) fwu_update_mdata()
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_update_mdata(struct fwu_mdata *mdata)
> > +{
> > +       int ret;
> > +       void *buf;
> > +       struct udevice *dev = NULL;
> > +       const struct fwu_mdata_ops *ops = NULL;
> > +
> > +       ret = fwu_get_dev_ops(&dev, &ops);
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!ops->update_mdata) {
> > +               log_err("get_mdata() method not defined\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       /*
> > +        * Calculate the crc32 for the updated FWU metadata
> > +        * and put the updated value in the FWU metadata crc32
> > +        * field
> > +        */
> > +       buf = &mdata->version;
> > +       mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> > +
> > +       return ops->update_mdata(dev, mdata);
> > +}
> > +
> > +UCLASS_DRIVER(fwu_mdata) = {
> > +       .id             = UCLASS_FWU_MDATA,
> > +       .name           = "fwu-mdata",
> > +};
> > diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
> > index a432e43871..598a8c10a0 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -58,6 +58,7 @@ enum uclass_id {
> >         UCLASS_FIRMWARE,        /* Firmware */
> >         UCLASS_FUZZING_ENGINE,  /* Fuzzing engine */
> >         UCLASS_FS_FIRMWARE_LOADER,              /* Generic loader */
> > +       UCLASS_FWU_MDATA,       /* FWU Metadata Access */
> >         UCLASS_GPIO,            /* Bank of general-purpose I/O pins */
> >         UCLASS_HASH,            /* Hash device */
> >         UCLASS_HWSPINLOCK,      /* Hardware semaphores */
> > diff --git a/include/fwu.h b/include/fwu.h
> > new file mode 100644
> > index 0000000000..e03cfff800
> > --- /dev/null
> > +++ b/include/fwu.h
> > @@ -0,0 +1,49 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (c) 2022, Linaro Limited
> > + */
> > +
> > +#if !defined _FWU_H_
> > +#define _FWU_H_
> > +
> > +#include <blk.h>
> > +#include <efi.h>
> > +
> > +#include <linux/types.h>
> > +
> > +struct fwu_mdata;
> > +struct udevice;
> > +
> > +/**
> > + * @mdata_check: check the validity of the FWU metadata partitions
> > + * @get_mdata() - Get a FWU metadata copy
> > + * @update_mdata() - Update the FWU metadata copy
> > + */
> > +struct fwu_mdata_ops {
> > +       int (*mdata_check)(struct udevice *dev);
> > +
> > +       int (*get_mdata)(struct udevice *dev, struct fwu_mdata **mdata);
> > +
> > +       int (*update_mdata)(struct udevice *dev, struct fwu_mdata *mdata);
>
> Needs full comments - see other uclasses

Okay

>
> > +};
> > +
> > +#define FWU_MDATA_VERSION      0x1
> > +
> > +#define FWU_MDATA_GUID \
> > +       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > +                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
>
> What is this? Comment?

Will add

>
> > +
> > +int fwu_get_mdata(struct fwu_mdata **mdata);
> > +int fwu_update_mdata(struct fwu_mdata *mdata);
> > +int fwu_get_active_index(u32 *active_idx);
> > +int fwu_update_active_index(u32 active_idx);
> > +int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> > +                         int *alt_num);
> > +int fwu_mdata_check(void);
> > +int fwu_revert_boot_index(void);
> > +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_alt_num(struct udevice *dev, efi_guid_t *image_guid,
> > +                        int *alt_num);
>
> These all need full comments

Will add

>
> > +#endif /* _FWU_H_ */
> > diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> > new file mode 100644
> > index 0000000000..72e3edab43
> > --- /dev/null
> > +++ b/include/fwu_mdata.h
> > @@ -0,0 +1,67 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/*
> > + * Copyright (c) 2022, Linaro Limited
> > + */
> > +
> > +#if !defined _FWU_MDATA_H_
> > +#define _FWU_MDATA_H_
> > +
> > +#include <efi.h>
> > +
> > +/**
> > + * struct fwu_image_bank_info - firmware image information
> > + * @image_uuid: Guid value of the image in this bank
> > + * @accepted: Acceptance status of the image
> > + * @reserved: Reserved
> > + *
> > + * The structure contains image specific fields which are
> > + * used to identify the image and to specify the image's
> > + * acceptance status
> > + */
> > +struct fwu_image_bank_info {
> > +       efi_guid_t  image_uuid;
> > +       uint32_t accepted;
> > +       uint32_t reserved;
> > +} __attribute__((__packed__));
>
> Why is this packed?

This was based on a review comment from Masami [1], as he wanted to
use the same structure in the low level bootloader as well.

>
> > +
> > +/**
> > + * struct fwu_image_entry - information for a particular type of image
> > + * @image_type_uuid: Guid value for identifying the image type
> > + * @location_uuid: Guid of the storage volume where the image is located
> > + * @img_bank_info: Array containing properties of images
> > + *
> > + * This structure contains information on various types of updatable
> > + * firmware images. Each image type then contains an array of image
> > + * information per bank.
> > + */
> > +struct fwu_image_entry {
> > +       efi_guid_t image_type_uuid;
> > +       efi_guid_t location_uuid;
> > +       struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS];
> > +} __attribute__((__packed__));
>
> why packed?

Same as above

>
> > +
> > +/**
> > + * struct fwu_mdata - FWU metadata structure for multi-bank updates
> > + * @crc32: crc32 value for the FWU metadata
> > + * @version: FWU metadata version
> > + * @active_index: Index of the bank currently used for booting images
> > + * @previous_active_inde: Index of the bank used before the current bank
> > + *                        being used for booting
> > + * @img_entry: Array of information on various firmware images that can
> > + *             be updated
> > + *
> > + * This structure is used to store all the needed information for performing
> > + * multi bank updates on the platform. This contains info on the bank being
> > + * used to boot along with the information needed for identification of
> > + * individual images
> > + */
> > +struct fwu_mdata {
> > +       uint32_t crc32;
> > +       uint32_t version;
> > +       uint32_t active_index;
> > +       uint32_t previous_active_index;
> > +
> > +       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> > +} __attribute__((__packed__));
>
> same question

Same as above

-sughosh

[1] - https://lists.denx.de/pipermail/u-boot/2021-December/470118.html

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-08-18  3:21   ` Simon Glass
@ 2022-08-18 11:38     ` Sughosh Ganu
  2022-08-18 17:49       ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-18 11:38 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > In the FWU Multi Bank Update feature, the information about the
> > updatable images is stored as part of the metadata, on a separate
> > partition. Add a driver for reading from and writing to the metadata
> > when the updatable images and the metadata are stored on a block
> > device which is formated with GPT based partition scheme.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > ---
> > Changes since V7: None
> >
> >  drivers/fwu-mdata/Kconfig             |   9 +
> >  drivers/fwu-mdata/Makefile            |   1 +
> >  drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410 ++++++++++++++++++++++++++
> >  include/fwu.h                         |   5 +
> >  4 files changed, 425 insertions(+)
> >  create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> >
> > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
> > index d6a21c8e19..d5edef19d6 100644
> > --- a/drivers/fwu-mdata/Kconfig
> > +++ b/drivers/fwu-mdata/Kconfig
> > @@ -5,3 +5,12 @@ config DM_FWU_MDATA
> >           Enable support for accessing FWU Metadata partitions. The
> >           FWU Metadata partitions reside on the same storage device
> >           which contains the other FWU updatable firmware images.
>
> Can we link to the docs here, or will it be easy for people to find in
> the U-Boot docs?

The link to the spec is being provided in the documentation for the
feature. I guess that should suffice.

>
> > +
> > +config FWU_MDATA_GPT_BLK
> > +       bool "FWU Metadata access for GPT partitioned Block devices"
> > +       select PARTITION_TYPE_GUID
> > +       select PARTITION_UUIDS
> > +       depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION
> > +       help
> > +         Enable support for accessing FWU Metadata on GPT partitioned
> > +         block devices.
>
> GPT-partitioned (I think)

I see "GPT partition" being used elsewhere. I don't have a strong
opinion on this though.

>
> > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
> > index e53a8c9983..313049f67a 100644
> > --- a/drivers/fwu-mdata/Makefile
> > +++ b/drivers/fwu-mdata/Makefile
> > @@ -4,3 +4,4 @@
> >  #
> >
> >  obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
> > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o
> > diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
>
> Perhaps just call it gpt_blk.c since it is in this directory

Actually, there are both type of examples that can be seen under
drivers/. For e.g. the drivers/clk/ has all files starting with clk_*.
Similarly, under drivers/reset/. But there are other examples as well.
But this is not a big effort. I will change the name as per your
suggestion.

>
> > new file mode 100644
> > index 0000000000..f694c4369b
> > --- /dev/null
> > +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> > @@ -0,0 +1,410 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Copyright (c) 2022, Linaro Limited
> > + */
> > +
> > +#define LOG_CATEGORY UCLASS_FWU_MDATA
> > +
> > +#include <blk.h>
> > +#include <dm.h>
> > +#include <efi_loader.h>
> > +#include <fwu.h>
> > +#include <fwu_mdata.h>
> > +#include <log.h>
> > +#include <malloc.h>
> > +#include <memalign.h>
> > +#include <part.h>
> > +#include <part_efi.h>
> > +
> > +#include <dm/device-internal.h>
> > +#include <linux/errno.h>
> > +#include <linux/types.h>
> > +#include <u-boot/crc.h>
> > +
> > +#define PRIMARY_PART           BIT(0)
> > +#define SECONDARY_PART         BIT(1)
> > +#define BOTH_PARTS             (PRIMARY_PART | SECONDARY_PART)
> > +
> > +#define MDATA_READ             BIT(0)
> > +#define MDATA_WRITE            BIT(1)
> > +
>
> comment?

Umm, is the macro name not descriptive enough? They are just being
used to select a read or write operation.

>
> > +static int gpt_get_mdata_partitions(struct blk_desc *desc,
> > +                                   u16 *primary_mpart,
> > +                                   u16 *secondary_mpart)
>
> Should use uint, no need to select a 16-bit var so far as I can get

Okay

>
> > +{
> > +       int i, ret;
> > +       u32 mdata_parts;
> > +       efi_guid_t part_type_guid;
> > +       struct disk_partition info;
> > +       const efi_guid_t fwu_mdata_guid = FWU_MDATA_GUID;
> > +
> > +       mdata_parts = 0;
> > +       for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
> > +               if (part_get_info(desc, i, &info))
> > +                       continue;
> > +               uuid_str_to_bin(info.type_guid, part_type_guid.b,
> > +                               UUID_STR_FORMAT_GUID);
> > +
> > +               if (!guidcmp(&fwu_mdata_guid, &part_type_guid)) {
> > +                       ++mdata_parts;
> > +                       if (!*primary_mpart)
> > +                               *primary_mpart = i;
> > +                       else
> > +                               *secondary_mpart = i;
> > +               }
> > +       }
> > +
> > +       if (mdata_parts != 2) {
> > +               log_err("Expect two copies of the FWU metadata instead of %d\n",
> > +                       mdata_parts);
> > +               ret = -EINVAL;
> > +       } else {
> > +               ret = 0;
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int gpt_get_mdata_disk_part(struct blk_desc *desc,
> > +                                  struct disk_partition *info,
> > +                                  u32 part_num)
> > +{
> > +       int ret;
> > +       char *mdata_guid_str = "8a7a84a0-8387-40f6-ab41-a8b9a5a60d23";
>
> This is fine, but I wonder if it should that go in a header with all
> the other GUIDs? Or does it go hear because it is a string?

Yes, this is because it is a string

>
> > +
> > +       ret = part_get_info(desc, part_num, info);
> > +       if (ret < 0) {
> > +               log_err("Unable to get the partition info for the FWU metadata part %d",
> > +                       part_num);
> > +               return -1;
> > +       }
> > +
> > +       /* Check that it is indeed the FWU metadata partition */
> > +       if (!strncmp(info->type_guid, mdata_guid_str, UUID_STR_LEN)) {
> > +               /* Found the FWU metadata partition */
> > +               return 0;
> > +       }
> > +
> > +       return -1;
> > +}
> > +
> > +static int gpt_read_write_mdata(struct blk_desc *desc,
> > +                               struct fwu_mdata *mdata,
> > +                               u8 access, u32 part_num)
> > +{
> > +       int ret;
> > +       u32 len, blk_start, blkcnt;
> > +       struct disk_partition info;
> > +
> > +       ALLOC_CACHE_ALIGN_BUFFER_PAD(struct fwu_mdata, mdata_aligned, 1,
> > +                                    desc->blksz);
> > +
> > +       ret = gpt_get_mdata_disk_part(desc, &info, part_num);
> > +       if (ret < 0) {
> > +               printf("Unable to get the FWU metadata partition\n");
> > +               return -ENODEV;
>
> How about -ENOENT ?
>
> There is a device, so we cannot use -ENODEV
>
> Please fix below too

Okay

>
> > +       }
> > +
> > +       len = sizeof(*mdata);
> > +       blkcnt = BLOCK_CNT(len, desc);
> > +       if (blkcnt > info.size) {
> > +               log_err("Block count exceeds FWU metadata partition size\n");
> > +               return -ERANGE;
> > +       }
> > +
> > +       blk_start = info.start;
> > +       if (access == MDATA_READ) {
> > +               if (blk_dread(desc, blk_start, blkcnt, mdata_aligned) != blkcnt) {
> > +                       log_err("Error reading FWU metadata from the device\n");
> > +                       return -EIO;
> > +               }
> > +               memcpy(mdata, mdata_aligned, sizeof(struct fwu_mdata));
> > +       } else {
> > +               if (blk_dwrite(desc, blk_start, blkcnt, mdata) != blkcnt) {
> > +                       log_err("Error writing FWU metadata to the device\n");
> > +                       return -EIO;
> > +               }
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int gpt_read_mdata(struct blk_desc *desc,
> > +                         struct fwu_mdata *mdata, u32 part_num)
> > +{
> > +       return gpt_read_write_mdata(desc, mdata, MDATA_READ, part_num);
> > +}
> > +
> > +static int gpt_write_mdata_partition(struct blk_desc *desc,
> > +                                       struct fwu_mdata *mdata,
> > +                                       u32 part_num)
> > +{
> > +       return gpt_read_write_mdata(desc, mdata, MDATA_WRITE, part_num);
> > +}
> > +
> > +static int fwu_gpt_update_mdata(struct udevice *dev, struct fwu_mdata *mdata)
> > +{
> > +       int ret;
> > +       struct blk_desc *desc;
> > +       u16 primary_mpart = 0, secondary_mpart = 0;
>
> uint

Okay

>
> > +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> > +
> > +       desc = dev_get_uclass_plat(priv->blk_dev);
> > +       if (!desc) {
> > +               log_err("Block device not found\n");
> > +               return -ENODEV;
>
> This cannot happen, drop this if()

Okay

>
> > +       }
> > +
> > +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> > +                                      &secondary_mpart);
> > +
>
> drop blank line so the error check is next to the thing that reads it

Will fix

>
> > +       if (ret < 0) {
> > +               log_err("Error getting the FWU metadata partitions\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       /* First write the primary partition*/
>
> space before */

Will fix

>
> > +       ret = gpt_write_mdata_partition(desc, mdata, primary_mpart);
> > +       if (ret < 0) {
> > +               log_err("Updating primary FWU metadata partition failed\n");
>
> This is very error-heavy. The log_err() things produce a string in the
> code so this ends up being very large. Is that what you want? If these
> things can happen in the real world and users need to debug them, then
> I suppose it is OK. But normally with driver model we report errors in
> the command code, or the logic, not in drivers themselves. Otherwise
> when you write tests you get lots of confusing error output that needs
> to be ignored.

I see your point, but in this specific case, it is only the driver
which will be able to tell about the error in some detail. I can
change this to a log_debug if you so wish. Although I do see quite a
few instances of log_err being used in the driver code as well.

>
> > +               return ret;
> > +       }
> > +
> > +       /* And now the replica */
> > +       ret = gpt_write_mdata_partition(desc, mdata, secondary_mpart);
> > +       if (ret < 0) {
> > +               log_err("Updating secondary FWU metadata partition failed\n");
> > +               return ret;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata)
>
> mdatap

Okay

>
> > +{
> > +       int ret;
> > +       u16 primary_mpart = 0, secondary_mpart = 0;
>
> uint

Okay

>
> Also do you need to set them to 0
>
> Declare a locate mdata and use that here instead of *mdata, which is a pain.

This function is copying the metadata into the callers copy. Unless I
don't understand your comment.

>
> > +
> > +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> > +                                      &secondary_mpart);
> > +
> > +       if (ret < 0) {
> > +               log_err("Error getting the FWU metadata partitions\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       *mdata = malloc(sizeof(struct fwu_mdata));
> > +       if (!*mdata) {
> > +               log_err("Unable to allocate memory for reading FWU metadata\n");
> > +               return -ENOMEM;
> > +       }
> > +
> > +       ret = gpt_read_mdata(desc, *mdata, primary_mpart);
> > +       if (ret < 0) {
> > +               log_err("Failed to read the FWU metadata from the device\n");
> > +               return -EIO;
> > +       }
> > +
> > +       ret = fwu_verify_mdata(*mdata, 1);
> > +       if (!ret)
> > +               return 0;
> > +
> > +       /*
> > +        * Verification of the primary FWU metadata copy failed.
> > +        * Try to read the replica.
> > +        */
> > +       memset(*mdata, 0, sizeof(struct fwu_mdata));
>
> '\0'

Okay

>
> > +       ret = gpt_read_mdata(desc, *mdata, secondary_mpart);
> > +       if (ret < 0) {
> > +               log_err("Failed to read the FWU metadata from the device\n");
> > +               return -EIO;
> > +       }
> > +
> > +       ret = fwu_verify_mdata(*mdata, 0);
> > +       if (!ret)
> > +               return 0;
> > +
> > +       /* Both the FWU metadata copies are corrupted. */
> > +       return -1;
>
> This is -EPERM
>
> Perhaps choose something else?

Again, I am not sure what would be a suitable error to return in this case.

>
> > +}
> > +
> > +static int gpt_check_mdata_validity(struct udevice *dev)
> > +{
> > +       int ret;
> > +       struct blk_desc *desc;
> > +       struct fwu_mdata pri_mdata;
> > +       struct fwu_mdata secondary_mdata;
> > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > +       u16 valid_partitions, invalid_partitions;
> > +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> > +
> > +       desc = dev_get_uclass_plat(priv->blk_dev);
> > +       if (!desc) {
> > +               log_err("Block device not found\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       /*
> > +        * Two FWU metadata partitions are expected.
> > +        * If we don't have two, user needs to create
> > +        * them first
> > +        */
> > +       valid_partitions = 0;
> > +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> > +                                      &secondary_mpart);
> > +
> > +       if (ret < 0) {
> > +               log_err("Error getting the FWU metadata partitions\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       ret = gpt_read_mdata(desc, &pri_mdata, primary_mpart);
> > +       if (ret < 0) {
> > +               log_err("Failed to read the FWU metadata from the device\n");
> > +               goto secondary_read;
> > +       }
> > +
> > +       ret = fwu_verify_mdata(&pri_mdata, 1);
> > +       if (!ret)
> > +               valid_partitions |= PRIMARY_PART;
> > +
> > +secondary_read:
> > +       /* Now check the secondary partition */
> > +       ret = gpt_read_mdata(desc, &secondary_mdata, secondary_mpart);
> > +       if (ret < 0) {
> > +               log_err("Failed to read the FWU metadata from the device\n");
> > +               goto mdata_restore;
> > +       }
> > +
> > +       ret = fwu_verify_mdata(&secondary_mdata, 0);
> > +       if (!ret)
> > +               valid_partitions |= SECONDARY_PART;
> > +
> > +mdata_restore:
> > +       if (valid_partitions == (PRIMARY_PART | SECONDARY_PART)) {
> > +               ret = -1;
> > +               /*
> > +                * Before returning, check that both the
> > +                * FWU metadata copies are the same. If not,
> > +                * the FWU metadata copies need to be
> > +                * re-populated.
> > +                */
> > +               if (!memcmp(&pri_mdata, &secondary_mdata,
> > +                           sizeof(struct fwu_mdata))) {
> > +                       ret = 0;
> > +               } else {
> > +                       log_err("Both FWU metadata copies are valid but do not match. Please check!\n");
>
> Honestly the error handling needs a rethink IMO. You should try to
> return error codes that indicate what went wrong (you mostly do in
> this file) and then have the top-level code decode those errors and
> produce an error message.

The code in efi_capsule.c which is calling the APIs is checking the
error codes and printing the error messages.

>
> > +               }
> > +               goto out;
> > +       }
> > +
> > +       ret = -1;
> > +       if (!(valid_partitions & BOTH_PARTS))
> > +               goto out;
> > +
> > +       invalid_partitions = valid_partitions ^ BOTH_PARTS;
> > +       ret = gpt_write_mdata_partition(desc,
> > +                                       (invalid_partitions == PRIMARY_PART) ?
> > +                                       &secondary_mdata : &pri_mdata,
> > +                                       (invalid_partitions == PRIMARY_PART) ?
> > +                                       primary_mpart : secondary_mpart);
> > +
> > +       if (ret < 0)
> > +               log_err("Restoring %s FWU metadata partition failed\n",
> > +                       (invalid_partitions == PRIMARY_PART) ?
> > +                       "primary" : "secondary");
> > +
> > +out:
> > +       return ret;
> > +}
> > +
> > +static int fwu_gpt_mdata_check(struct udevice *dev)
> > +{
> > +       /*
> > +        * Check if both the copies of the FWU metadata are
> > +        * valid. If one has gone bad, restore it from the
> > +        * other good copy.
>
> word wrap wider

Okay

>
> > +        */
> > +       return gpt_check_mdata_validity(dev);
> > +}
> > +
> > +static int fwu_gpt_get_mdata(struct udevice *dev, struct fwu_mdata **mdata)
> > +{
> > +       struct blk_desc *desc;
> > +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> > +
> > +       desc = dev_get_uclass_plat(priv->blk_dev);
> > +       if (!desc) {
> > +               log_err("Block device not found\n");
> > +               return -ENODEV;
>
> Again this cannot happen

Will remove

>
> > +       }
> > +
> > +       return gpt_get_mdata(desc, mdata);
> > +}
> > +
> > +static int fwu_get_mdata_device(struct udevice *dev, struct udevice **mdata_dev)
> > +{
> > +       u32 phandle;
> > +       int ret, size;
> > +       struct udevice *parent, *child;
> > +       const fdt32_t *phandle_p = NULL;
> > +
> > +       phandle_p = dev_read_prop(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);
>
> Can you use dev_read_u32() ?

Will check if this can be used.

>
> > +
> > +       ret = device_get_global_by_ofnode(ofnode_get_by_phandle(phandle),
> > +                                         &parent);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = -ENODEV;
>
> Here it is correct to return -ENODEV I think
>
> > +       for (device_find_first_child(parent, &child); child;
> > +            device_find_next_child(&child)) {
> > +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> > +                       *mdata_dev = child;
> > +                       ret = 0;
>
> See blk_get_from_parent()

Will check

>
> > +               }
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > +{
> > +       int ret;
> > +       struct udevice *mdata_dev = NULL;
> > +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> > +
> > +       ret = fwu_get_mdata_device(dev, &mdata_dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       priv->blk_dev = mdata_dev;
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > +       .mdata_check = fwu_gpt_mdata_check,
> > +       .get_mdata = fwu_gpt_get_mdata,
> > +       .update_mdata = fwu_gpt_update_mdata,
> > +};
> > +
> > +static const struct udevice_id fwu_mdata_ids[] = {
> > +       { .compatible = "u-boot,fwu-mdata-gpt" },
> > +       { }
> > +};
> > +
> > +U_BOOT_DRIVER(fwu_mdata_gpt_blk) = {
> > +       .name           = "fwu-mdata-gpt-blk",
> > +       .id             = UCLASS_FWU_MDATA,
> > +       .of_match       = fwu_mdata_ids,
> > +       .ops            = &fwu_gpt_blk_ops,
> > +       .probe          = fwu_mdata_gpt_blk_probe,
> > +       .priv_auto      = sizeof(struct fwu_mdata_gpt_blk_priv),
> > +};
> > diff --git a/include/fwu.h b/include/fwu.h
> > index e03cfff800..8259c75d12 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -14,6 +14,10 @@
> >  struct fwu_mdata;
> >  struct udevice;
> >
> > +struct fwu_mdata_gpt_blk_priv {
> > +       struct udevice *blk_dev;
> > +};
> > +
> >  /**
> >   * @mdata_check: check the validity of the FWU metadata partitions
> >   * @get_mdata() - Get a FWU metadata copy
> > @@ -39,6 +43,7 @@ int fwu_get_active_index(u32 *active_idx);
> >  int fwu_update_active_index(u32 active_idx);
> >  int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> >                           int *alt_num);
> > +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part);
>
> comments again

Will add

-sughosh

>
> >  int fwu_mdata_check(void);
> >  int fwu_revert_boot_index(void);
> >  int fwu_accept_image(efi_guid_t *img_type_id, u32 bank);
> > --
> > 2.34.1
> >
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification
  2022-08-18  3:21   ` Simon Glass
@ 2022-08-18 11:41     ` Sughosh Ganu
  2022-08-18 17:49       ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-18 11:41 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > The FWU Multi Bank Update specification requires the Update Agent to
> > carry out certain checks at the time of platform boot. The Update
> > Agent is the component which is responsible for updating the firmware
> > components and maintaining and keeping the metadata in sync.
> >
> > The spec requires that the Update Agent perform the following checks
> > at the time of boot
> > * Sanity check of both the metadata copies maintained by the platform.
> > * Get the boot index passed to U-Boot by the prior stage bootloader
> >   and use this value for metadata bookkeeping.
> > * Check if the system is booting in Trial State. If the system boots
> >   in the Trial State for more than a specified number of boot counts,
> >   change the Active Bank to be booting the platform from.
> >
> > Add these checks in the board initialisation sequence, invoked after
> > relocation.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> > Changes since V7:
> > * Introduce trial_counter_update() to increment and delete the
> >   TrialStateCtr variable.
> > * Introduce in_trial_state() to check if the platform is booting in
> >   Trial State.
> >
> >  common/board_r.c      |   5 ++
> >  include/fwu.h         |   3 +
> >  lib/fwu_updates/fwu.c | 175 ++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 183 insertions(+)
>
> We should use the event system instead of adding another hook. We are
> trying to get rid of them!

Okay, I will check about this.

>
> Also, please separate out the fwu change from touching common code
> (although you may not need to touch comment code with events).

The FWU specification requires certain checks to be run at the
platform boot time. Not sure how else will that be done(although this
might not be relevant if I can use events).

-sughosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-18  3:21   ` Simon Glass
@ 2022-08-18 11:53     ` Sughosh Ganu
  2022-08-18 17:49       ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-18 11:53 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sugosh,
>
> On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > Add a command to read the metadata as specified in the FWU
> > specification and print the fields of the metadata.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > ---
> > Changes since V7: None
> >
> >  cmd/Kconfig     |  7 +++++
> >  cmd/Makefile    |  1 +
> >  cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 88 insertions(+)
> >  create mode 100644 cmd/fwu_mdata.c
>
> This needs docs and a test.
>
> BTW I forgot to mention that the uclass needs a simple test of some sort.
>
> https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html

Okay. I will check how this can be done. Btw, there are plans to add a
test for the feature once support for the feature has been added on
the Synquacer platform. That test will exercise the above command as
well as the driver code. Do we still need a standalone test for the
uclass?

-sughosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates
  2022-08-18  8:05   ` Yann Gautier
@ 2022-08-18 12:06     ` Sughosh Ganu
  2022-08-18 16:36       ` Yann Gautier
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-18 12:06 UTC (permalink / raw)
  To: Yann Gautier; +Cc: u-boot

hi Yann,

On Thu, 18 Aug 2022 at 13:35, Yann Gautier <yann.gautier@foss.st.com> wrote:
>
> On 8/17/22 14:43, Sughosh Ganu wrote:
> > Enabling capsule update functionality on the platform requires
> > populating information on the images that are to be updated using the
> > functionality. Do so for the DK2 board.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > ---
> > Changes since V7: None
> >
> >   board/st/stm32mp1/stm32mp1.c       | 23 +++++++++++++++++++++++
> >   include/configs/stm32mp15_common.h |  4 ++++
> >   2 files changed, 27 insertions(+)
> >
> > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> > index 9496890d16..0fda8f150d 100644
> > --- a/board/st/stm32mp1/stm32mp1.c
> > +++ b/board/st/stm32mp1/stm32mp1.c
> > @@ -11,6 +11,7 @@
> >   #include <clk.h>
> >   #include <config.h>
> >   #include <dm.h>
> > +#include <efi_loader.h>
> >   #include <env.h>
> >   #include <env_internal.h>
> >   #include <fdt_simplefb.h>
> > @@ -87,6 +88,16 @@
> >   #define USB_START_LOW_THRESHOLD_UV  1230000
> >   #define USB_START_HIGH_THRESHOLD_UV 2150000
> >
> > +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
> > +struct efi_fw_image fw_images[1];
> > +
> > +struct efi_capsule_update_info update_info = {
> > +     .images = fw_images,
> > +};
> > +
> > +u8 num_image_type_guids = ARRAY_SIZE(fw_images);
> > +#endif /* EFI_HAVE_CAPSULE_SUPPORT */
> > +
> >   int board_early_init_f(void)
> >   {
> >       /* nothing to do, only used in SPL */
> > @@ -670,6 +681,18 @@ int board_init(void)
> >
> >       setup_led(LEDST_ON);
> >
> > +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
> > +     if (board_is_stm32mp15x_dk2()) {
> > +             efi_guid_t image_type_guid = STM32MP15_DK2_FIP_IMAGE_GUID;
> > +             guidcpy(&fw_images[0].image_type_id, &image_type_guid);
> > +             fw_images[0].fw_name = u"STM32MP15-DK2-FIP";
> > +             /*
> > +              * For FWU multi bank update, the image
> > +              * index will be computed at runtime
> > +              */
> > +             fw_images[0].image_index = 0;
> > +     }
> > +#endif
> >       return 0;
> >   }
> >
> > diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h
> > index c5412ffeb3..6ab10d8ce5 100644
> > --- a/include/configs/stm32mp15_common.h
> > +++ b/include/configs/stm32mp15_common.h
> > @@ -34,6 +34,10 @@
> >   #define CONFIG_SERVERIP                 192.168.1.1
> >   #endif
> >
>
> Hi Sugosh,
>
> Sorry for the late review.
>
> > +#define STM32MP15_DK2_FIP_IMAGE_GUID \
> Although this is now only supported on this STM32MP15_DK2 board, I don't
> think this macro should be tight to the board name, as it may be used
> for other STM32MP boards. I'd just use STM32MP_FIP_IMAGE_GUID.
> This should be the same for the fw_images[0].fw_name.

The idea of this GUID is to identify or associate an image with a
platform. Will the FIP image be common across multiple STM32MP
platforms? If we use a common GUID that might be shared across
multiple ST boards, it would be possible to flash an image generated
for the ev1 board on the dk2 board. However, you would know better
about ST platforms. So I can change this as per your suggestion.
Thanks.

-sughosh

>
>
> Best regards,
> Yann
>
> > +     EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \
> > +              0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5)
> > +
> >   /*****************************************************************************/
> >   #ifdef CONFIG_DISTRO_DEFAULTS
> >   /*****************************************************************************/
>

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates
  2022-08-18 12:06     ` Sughosh Ganu
@ 2022-08-18 16:36       ` Yann Gautier
  0 siblings, 0 replies; 46+ messages in thread
From: Yann Gautier @ 2022-08-18 16:36 UTC (permalink / raw)
  To: Sughosh Ganu, Lionel DEBIEVE-SCND-02; +Cc: u-boot

On 8/18/22 14:06, Sughosh Ganu wrote:
> hi Yann,
> 
> On Thu, 18 Aug 2022 at 13:35, Yann Gautier <yann.gautier@foss.st.com> wrote:
>>
>> On 8/17/22 14:43, Sughosh Ganu wrote:
>>> Enabling capsule update functionality on the platform requires
>>> populating information on the images that are to be updated using the
>>> functionality. Do so for the DK2 board.
>>>
>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
>>> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
>>> ---
>>> Changes since V7: None
>>>
>>>    board/st/stm32mp1/stm32mp1.c       | 23 +++++++++++++++++++++++
>>>    include/configs/stm32mp15_common.h |  4 ++++
>>>    2 files changed, 27 insertions(+)
>>>
>>> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
>>> index 9496890d16..0fda8f150d 100644
>>> --- a/board/st/stm32mp1/stm32mp1.c
>>> +++ b/board/st/stm32mp1/stm32mp1.c
>>> @@ -11,6 +11,7 @@
>>>    #include <clk.h>
>>>    #include <config.h>
>>>    #include <dm.h>
>>> +#include <efi_loader.h>
>>>    #include <env.h>
>>>    #include <env_internal.h>
>>>    #include <fdt_simplefb.h>
>>> @@ -87,6 +88,16 @@
>>>    #define USB_START_LOW_THRESHOLD_UV  1230000
>>>    #define USB_START_HIGH_THRESHOLD_UV 2150000
>>>
>>> +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
>>> +struct efi_fw_image fw_images[1];
>>> +
>>> +struct efi_capsule_update_info update_info = {
>>> +     .images = fw_images,
>>> +};
>>> +
>>> +u8 num_image_type_guids = ARRAY_SIZE(fw_images);
>>> +#endif /* EFI_HAVE_CAPSULE_SUPPORT */
>>> +
>>>    int board_early_init_f(void)
>>>    {
>>>        /* nothing to do, only used in SPL */
>>> @@ -670,6 +681,18 @@ int board_init(void)
>>>
>>>        setup_led(LEDST_ON);
>>>
>>> +#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT)
>>> +     if (board_is_stm32mp15x_dk2()) {
>>> +             efi_guid_t image_type_guid = STM32MP15_DK2_FIP_IMAGE_GUID;
>>> +             guidcpy(&fw_images[0].image_type_id, &image_type_guid);
>>> +             fw_images[0].fw_name = u"STM32MP15-DK2-FIP";
>>> +             /*
>>> +              * For FWU multi bank update, the image
>>> +              * index will be computed at runtime
>>> +              */
>>> +             fw_images[0].image_index = 0;
>>> +     }
>>> +#endif
>>>        return 0;
>>>    }
>>>
>>> diff --git a/include/configs/stm32mp15_common.h b/include/configs/stm32mp15_common.h
>>> index c5412ffeb3..6ab10d8ce5 100644
>>> --- a/include/configs/stm32mp15_common.h
>>> +++ b/include/configs/stm32mp15_common.h
>>> @@ -34,6 +34,10 @@
>>>    #define CONFIG_SERVERIP                 192.168.1.1
>>>    #endif
>>>
>>
>> Hi Sugosh,
>>
>> Sorry for the late review.
>>
>>> +#define STM32MP15_DK2_FIP_IMAGE_GUID \
>> Although this is now only supported on this STM32MP15_DK2 board, I don't
>> think this macro should be tight to the board name, as it may be used
>> for other STM32MP boards. I'd just use STM32MP_FIP_IMAGE_GUID.
>> This should be the same for the fw_images[0].fw_name.
> 
> The idea of this GUID is to identify or associate an image with a
> platform. Will the FIP image be common across multiple STM32MP
> platforms? If we use a common GUID that might be shared across
> multiple ST boards, it would be possible to flash an image generated
> for the ev1 board on the dk2 board. However, you would know better
> about ST platforms. So I can change this as per your suggestion.
> Thanks.
> 
> -sughosh
> 

Hi Sughosh,

This GUID is generic in TF-A for all STM32MP platforms.
Having a per board GUID in U-Boot might then be an issue.
And we'll end up with lots of GUIDs for each new board that will support 
FWU.
But maybe I miss something here.


Yann

>>
>>
>> Best regards,
>> Yann
>>
>>> +     EFI_GUID(0x19d5df83, 0x11b0, 0x457b, 0xbe, 0x2c, \
>>> +              0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5)
>>> +
>>>    /*****************************************************************************/
>>>    #ifdef CONFIG_DISTRO_DEFAULTS
>>>    /*****************************************************************************/
>>


^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-08-18 11:38     ` Sughosh Ganu
@ 2022-08-18 17:49       ` Simon Glass
  2022-08-19  7:35         ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18 17:49 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Thu, 18 Aug 2022 at 05:39, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org>
wrote:
> > >
> > > In the FWU Multi Bank Update feature, the information about the
> > > updatable images is stored as part of the metadata, on a separate
> > > partition. Add a driver for reading from and writing to the metadata
> > > when the updatable images and the metadata are stored on a block
> > > device which is formated with GPT based partition scheme.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > ---
> > > Changes since V7: None
> > >
> > >  drivers/fwu-mdata/Kconfig             |   9 +
> > >  drivers/fwu-mdata/Makefile            |   1 +
> > >  drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410
++++++++++++++++++++++++++
> > >  include/fwu.h                         |   5 +
> > >  4 files changed, 425 insertions(+)
> > >  create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> > >
> > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
> > > index d6a21c8e19..d5edef19d6 100644
> > > --- a/drivers/fwu-mdata/Kconfig
> > > +++ b/drivers/fwu-mdata/Kconfig
> > > @@ -5,3 +5,12 @@ config DM_FWU_MDATA
> > >           Enable support for accessing FWU Metadata partitions. The
> > >           FWU Metadata partitions reside on the same storage device
> > >           which contains the other FWU updatable firmware images.
> >
> > Can we link to the docs here, or will it be easy for people to find in
> > the U-Boot docs?
>
> The link to the spec is being provided in the documentation for the
> feature. I guess that should suffice.

Yes it's the U-Boot documentation that I am referring to. I assume people
can type 'FWU metadata' in the docs and it will come up. If so, that seems
OK.

>
> >
> > > +
> > > +config FWU_MDATA_GPT_BLK
> > > +       bool "FWU Metadata access for GPT partitioned Block devices"
> > > +       select PARTITION_TYPE_GUID
> > > +       select PARTITION_UUIDS
> > > +       depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION
> > > +       help
> > > +         Enable support for accessing FWU Metadata on GPT partitioned
> > > +         block devices.
> >
> > GPT-partitioned (I think)
>
> I see "GPT partition" being used elsewhere. I don't have a strong
> opinion on this though.
>
> >
> > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
> > > index e53a8c9983..313049f67a 100644
> > > --- a/drivers/fwu-mdata/Makefile
> > > +++ b/drivers/fwu-mdata/Makefile
> > > @@ -4,3 +4,4 @@
> > >  #
> > >
> > >  obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
> > > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o
> > > diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> >
> > Perhaps just call it gpt_blk.c since it is in this directory
>
> Actually, there are both type of examples that can be seen under
> drivers/. For e.g. the drivers/clk/ has all files starting with clk_*.
> Similarly, under drivers/reset/. But there are other examples as well.
> But this is not a big effort. I will change the name as per your
> suggestion.
>
> >
> > > new file mode 100644
> > > index 0000000000..f694c4369b
> > > --- /dev/null
> > > +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> > > @@ -0,0 +1,410 @@
> > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > +/*
> > > + * Copyright (c) 2022, Linaro Limited
> > > + */
> > > +
> > > +#define LOG_CATEGORY UCLASS_FWU_MDATA
> > > +
> > > +#include <blk.h>
> > > +#include <dm.h>
> > > +#include <efi_loader.h>
> > > +#include <fwu.h>
> > > +#include <fwu_mdata.h>
> > > +#include <log.h>
> > > +#include <malloc.h>
> > > +#include <memalign.h>
> > > +#include <part.h>
> > > +#include <part_efi.h>
> > > +
> > > +#include <dm/device-internal.h>
> > > +#include <linux/errno.h>
> > > +#include <linux/types.h>
> > > +#include <u-boot/crc.h>
> > > +
> > > +#define PRIMARY_PART           BIT(0)
> > > +#define SECONDARY_PART         BIT(1)
> > > +#define BOTH_PARTS             (PRIMARY_PART | SECONDARY_PART)
> > > +
> > > +#define MDATA_READ             BIT(0)
> > > +#define MDATA_WRITE            BIT(1)
> > > +
> >
> > comment?
>
> Umm, is the macro name not descriptive enough? They are just being
> used to select a read or write operation.

I mean the function below

>
> >
> > > +static int gpt_get_mdata_partitions(struct blk_desc *desc,
> > > +                                   u16 *primary_mpart,
> > > +                                   u16 *secondary_mpart)
> >
> > Should use uint, no need to select a 16-bit var so far as I can get
>
> Okay
>

[..]

> > > +static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata
**mdata)
> >
> > mdatap
>
> Okay
>
> >
> > > +{
> > > +       int ret;
> > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> >
> > uint
>
> Okay
>
> >
> > Also do you need to set them to 0
> >
> > Declare a locate mdata and use that here instead of *mdata, which is a
pain.
>
> This function is copying the metadata into the callers copy. Unless I
> don't understand your comment.

I mean it is easier to do this (the pattern common in driver model);

static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdatap)
{
    struct fwu_mdata *mdata;

    mdata = malloc(sizeof(struct fwu_mdata));
    ... (use mdata throughout function)

    *mdatap = mdata;

    return 0;
}

[..]

> >
> > > +       ret = gpt_read_mdata(desc, *mdata, secondary_mpart);
> > > +       if (ret < 0) {
> > > +               log_err("Failed to read the FWU metadata from the
device\n");
> > > +               return -EIO;
> > > +       }
> > > +
> > > +       ret = fwu_verify_mdata(*mdata, 0);
> > > +       if (!ret)
> > > +               return 0;
> > > +
> > > +       /* Both the FWU metadata copies are corrupted. */
> > > +       return -1;
> >
> > This is -EPERM
> >
> > Perhaps choose something else?
>
> Again, I am not sure what would be a suitable error to return in this
case.

Take a look at errno.h and pick one. Maybe -ELIBBAD ?

It doesn't matter much, so long as your upper-level command code can decode
the error and report it.

>
> >
> > > +}
> > > +
> > > +static int gpt_check_mdata_validity(struct udevice *dev)
> > > +{
> > > +       int ret;
> > > +       struct blk_desc *desc;
> > > +       struct fwu_mdata pri_mdata;
> > > +       struct fwu_mdata secondary_mdata;
> > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > > +       u16 valid_partitions, invalid_partitions;
> > > +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> > > +
> > > +       desc = dev_get_uclass_plat(priv->blk_dev);
> > > +       if (!desc) {
> > > +               log_err("Block device not found\n");
> > > +               return -ENODEV;
> > > +       }
> > > +
> > > +       /*
> > > +        * Two FWU metadata partitions are expected.
> > > +        * If we don't have two, user needs to create
> > > +        * them first
> > > +        */
> > > +       valid_partitions = 0;
> > > +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> > > +                                      &secondary_mpart);
> > > +
> > > +       if (ret < 0) {
> > > +               log_err("Error getting the FWU metadata
partitions\n");
> > > +               return -ENODEV;
> > > +       }
> > > +
> > > +       ret = gpt_read_mdata(desc, &pri_mdata, primary_mpart);
> > > +       if (ret < 0) {
> > > +               log_err("Failed to read the FWU metadata from the
device\n");
> > > +               goto secondary_read;
> > > +       }
> > > +
> > > +       ret = fwu_verify_mdata(&pri_mdata, 1);
> > > +       if (!ret)
> > > +               valid_partitions |= PRIMARY_PART;
> > > +
> > > +secondary_read:
> > > +       /* Now check the secondary partition */
> > > +       ret = gpt_read_mdata(desc, &secondary_mdata, secondary_mpart);
> > > +       if (ret < 0) {
> > > +               log_err("Failed to read the FWU metadata from the
device\n");
> > > +               goto mdata_restore;
> > > +       }
> > > +
> > > +       ret = fwu_verify_mdata(&secondary_mdata, 0);
> > > +       if (!ret)
> > > +               valid_partitions |= SECONDARY_PART;
> > > +
> > > +mdata_restore:
> > > +       if (valid_partitions == (PRIMARY_PART | SECONDARY_PART)) {
> > > +               ret = -1;
> > > +               /*
> > > +                * Before returning, check that both the
> > > +                * FWU metadata copies are the same. If not,
> > > +                * the FWU metadata copies need to be
> > > +                * re-populated.
> > > +                */
> > > +               if (!memcmp(&pri_mdata, &secondary_mdata,
> > > +                           sizeof(struct fwu_mdata))) {
> > > +                       ret = 0;
> > > +               } else {
> > > +                       log_err("Both FWU metadata copies are valid
but do not match. Please check!\n");
> >
> > Honestly the error handling needs a rethink IMO. You should try to
> > return error codes that indicate what went wrong (you mostly do in
> > this file) and then have the top-level code decode those errors and
> > produce an error message.
>
> The code in efi_capsule.c which is calling the APIs is checking the
> error codes and printing the error messages.

log_err() prints a message, though. Change this to log_debug() and it won't
appear unless specifically enabled.

[..]

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-18 11:53     ` Sughosh Ganu
@ 2022-08-18 17:49       ` Simon Glass
  2022-08-19  7:41         ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-18 17:49 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Thu, 18 Aug 2022 at 05:53, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sugosh,
> >
> > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org>
wrote:
> > >
> > > Add a command to read the metadata as specified in the FWU
> > > specification and print the fields of the metadata.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > ---
> > > Changes since V7: None
> > >
> > >  cmd/Kconfig     |  7 +++++
> > >  cmd/Makefile    |  1 +
> > >  cmd/fwu_mdata.c | 80
+++++++++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 88 insertions(+)
> > >  create mode 100644 cmd/fwu_mdata.c
> >
> > This needs docs and a test.
> >
> > BTW I forgot to mention that the uclass needs a simple test of some
sort.
> >
> > https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html
>
> Okay. I will check how this can be done. Btw, there are plans to add a
> test for the feature once support for the feature has been added on
> the Synquacer platform. That test will exercise the above command as
> well as the driver code. Do we still need a standalone test for the
> uclass?

Yes, testing on real hardware has nothing to do with the uclass test, which
runs on sandbox. It should be a small unit test like others in test/dm/...

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification
  2022-08-18 11:41     ` Sughosh Ganu
@ 2022-08-18 17:49       ` Simon Glass
  0 siblings, 0 replies; 46+ messages in thread
From: Simon Glass @ 2022-08-18 17:49 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Thu, 18 Aug 2022 at 05:42, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org>
wrote:
> > >
> > > The FWU Multi Bank Update specification requires the Update Agent to
> > > carry out certain checks at the time of platform boot. The Update
> > > Agent is the component which is responsible for updating the firmware
> > > components and maintaining and keeping the metadata in sync.
> > >
> > > The spec requires that the Update Agent perform the following checks
> > > at the time of boot
> > > * Sanity check of both the metadata copies maintained by the platform.
> > > * Get the boot index passed to U-Boot by the prior stage bootloader
> > >   and use this value for metadata bookkeeping.
> > > * Check if the system is booting in Trial State. If the system boots
> > >   in the Trial State for more than a specified number of boot counts,
> > >   change the Active Bank to be booting the platform from.
> > >
> > > Add these checks in the board initialisation sequence, invoked after
> > > relocation.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > ---
> > > Changes since V7:
> > > * Introduce trial_counter_update() to increment and delete the
> > >   TrialStateCtr variable.
> > > * Introduce in_trial_state() to check if the platform is booting in
> > >   Trial State.
> > >
> > >  common/board_r.c      |   5 ++
> > >  include/fwu.h         |   3 +
> > >  lib/fwu_updates/fwu.c | 175
++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 183 insertions(+)
> >
> > We should use the event system instead of adding another hook. We are
> > trying to get rid of them!
>
> Okay, I will check about this.
>
> >
> > Also, please separate out the fwu change from touching common code
> > (although you may not need to touch comment code with events).
>
> The FWU specification requires certain checks to be run at the
> platform boot time. Not sure how else will that be done(although this
> might not be relevant if I can use events).
>

You can have an 'fwu' command to handle this.

Regards,
Simon

> -sughosh

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-18 11:03     ` Sughosh Ganu
@ 2022-08-18 17:49       ` Simon Glass
  2022-08-19 13:36         ` Sughosh Ganu
  2022-08-19 14:59         ` Jassi Brar
  0 siblings, 2 replies; 46+ messages in thread
From: Simon Glass @ 2022-08-18 17:49 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

pHi Sughosh,

On Thu, 18 Aug 2022 at 05:03, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Thu, 18 Aug 2022 at 06:43, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org>
wrote:
> > >
> > > In the FWU Multi Bank Update feature, the information about the
> > > updatable images is stored as part of the metadata, which is stored on
> > > a dedicated partition. Add the metadata structure, and a driver model
> > > uclass which provides functions to access the metadata. These are
> > > generic API's, and implementations can be added based on parameters
> > > like how the metadata partition is accessed and what type of storage
> > > device houses the metadata.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > ---
> > > Changes since V7:
> > > * Rephrased the error message in fwu_update_active_index as per
> > >   suggestion from Ilias.
> > > * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
> > >   from Ilias.
> > >
> > >  drivers/Kconfig                      |   2 +
> > >  drivers/Makefile                     |   1 +
> > >  drivers/fwu-mdata/Kconfig            |   7 +
> > >  drivers/fwu-mdata/Makefile           |   6 +
> > >  drivers/fwu-mdata/fwu-mdata-uclass.c | 463
+++++++++++++++++++++++++++
> > >  include/dm/uclass-id.h               |   1 +
> > >  include/fwu.h                        |  49 +++
> > >  include/fwu_mdata.h                  |  67 ++++
> > >  8 files changed, 596 insertions(+)
> > >  create mode 100644 drivers/fwu-mdata/Kconfig
> > >  create mode 100644 drivers/fwu-mdata/Makefile
> > >  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
> > >  create mode 100644 include/fwu.h
> > >  create mode 100644 include/fwu_mdata.h
> > >
> > > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > > index 8b6fead351..75ac149d31 100644
> > > --- a/drivers/Kconfig
> > > +++ b/drivers/Kconfig
> > > @@ -44,6 +44,8 @@ source "drivers/fuzz/Kconfig"
> > >
> > >  source "drivers/fpga/Kconfig"
> > >
> > > +source "drivers/fwu-mdata/Kconfig"
> > > +
> > >  source "drivers/gpio/Kconfig"
> > >
> > >  source "drivers/hwspinlock/Kconfig"

[..]

> > > +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part)
> > > +{
> > > +       u32 calc_crc32;
> > > +       void *buf;
> > > +
> > > +       buf = &mdata->version;
> > > +       calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> > > +
> > > +       if (calc_crc32 != mdata->crc32) {
> > > +               log_err("crc32 check failed for %s FWU metadata
partition\n",
> > > +                       pri_part ? "primary" : "secondary");
> > > +               return -1;
> >
> > Please use an -Exxx value like -EPERM
>
> I don't think there is any value which relates to a crc mismatch. If
> you insist, I can think of -EIO, but I don't think -EPERM is a good
> match in this case.

See my comment in the other patch. You should not be printing messages in a
uclass or driver, except in extreme situations.

Choose a value that is somewhat meaningful so you can report the error
sensibly in top-level command code.

>
> >
> > > +       }
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +/**
> > > + * fwu_get_active_index() - Get active_index from the FWU metadata
> > > + * @active_idx: active_index value to be read
> > > + *
> > > + * Read the active_index field from the FWU metadata and place it in
> > > + * the variable pointed to be the function argument.
> > > + *
> > > + * Return: 0 if OK, -ve on error
> > > + *
> > > + */
> > > +int fwu_get_active_index(u32 *active_idx)
> >
> > Return the active index rather than having an arg?
>
> I would prefer to keep it the way it is. That allows returning an
> error value and keep the active_index separate. Moreover it is just a
> single parameter.

OK, then can you use active_idxp for the name, as is generally done in
driver model?

>
> >
> > > +{
> > > +       int ret;
> > > +       struct fwu_mdata *mdata = NULL;
> > > +
> > > +       ret = fwu_get_mdata(&mdata);
> >
> > Can you use a local var and avoid the malloc() / free() ?
>
> Do you see any disadvantages of using space on the heap? If you don't
> have a strong opinion on this, I would prefer to keep it as is.

Yes, this is not UEFI and we try to avoid allocating memory to no purpose.
It takes time and fragments the heap.

>
> >
> > > +       if (ret < 0) {
> > > +               log_err("Unable to get valid FWU metadata\n");
> > > +               goto out;
> > > +       }
> > > +
> > > +       /*
> > > +        * Found the FWU metadata partition, now read the active_index
> > > +        * value
> > > +        */
> > > +       *active_idx = mdata->active_index;
> > > +       if (*active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> > > +               log_err("Active index value read is incorrect\n");
> > > +               ret = -EINVAL;
> > > +       }
> > > +
> > > +out:
> > > +       free(mdata);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +/**
> > > + * fwu_update_active_index() - Update active_index from the FWU
metadata
> > > + * @active_idx: active_index value to be updated
> > > + *
> > > + * Update the active_index field in the FWU metadata
> > > + *
> > > + * Return: 0 if OK, -ve on error
> > > + *
> > > + */
> > > +int fwu_update_active_index(u32 active_idx)
> >
> > uint
>
> Are you referring to the function parameter? If so, it is a u32 since
> the active_index field in the metadata structure defined in the spec
> is a 32 bit value.

Sure, but how does that affect the function parameter? Generally we should
use natural types in function parameters so we don't do silly things like
force a 32-bit arg into a 64-bit register, causing the compiler to have to
mask the value, etc.

[..]

> > > +/**
> > > + * fwu_get_image_alt_num() - Get the dfu alt number to be used for
capsule update
> > > + * @image_type_id: pointer to the image GUID as passed in the capsule
> > > + * @update_bank: Bank to which the update is to be made
> > > + * @alt_num: The alt_num for the image
> > > + *
> > > + * Based on the GUID value passed in the capsule, along with the
bank to which the
> > > + * image needs to be updated, get the dfu alt number which will be
used for the
> > > + * capsule update
> > > + *
> > > + * Return: 0 if OK, -ve on error
> > > + *
> > > + */
> > > +int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> > > +                         int *alt_num)
> >
> > alt_nump is often used with driver model to indicate a return
> > value.Again I wonder if the return value could be used?
>
> Can you point me to an example? I could not find any instance of this.

Where did you look? Just to take one example, returning a device:

git grep -w devp drivers/ |wc -l
316

> Again, I believe this is a matter of taste, so I would prefer the
> current method.

Please fit into the uclass / driver model code style.

>
> >
> > > +{
> > > +       int ret, i;
> > > +       efi_guid_t *image_guid;
> > > +       struct udevice *dev = NULL;
> > > +       struct fwu_mdata *mdata = NULL;
> >
> > Please don't set things to NULL for no reason, it cluttlers the code.
>
> This is being set to NULL in case the called function that is supposed
> to populate the metadata structure fails to do so. We can pass NULL to
> free, else it could result in freeing up of unrelated memory.

If the function fails to set it, then the compiler will complain.

I don't understand your comment about NULL. free(NULL) is valid in U-Boot,
if that is what you are wondering?

>
> >
> > > +       struct fwu_image_entry *img_entry;
> > > +       const struct fwu_mdata_ops *ops = NULL;
> > > +       struct fwu_image_bank_info *img_bank_info;
> > > +
> > > +       ret = fwu_get_dev_ops(&dev, &ops);
> >
> > Rather than this, see the pattern used by other uclasses
>
> Can you point me to some example code. Also, not sure what the issue
> is with using this function.

It is a pointless obfuscation, mainly. See for example clk_request(), but
most uclasses use this pattern. I really encourage you to read more of the
code before submitting a patch.

int clk_request(struct udevice *dev, struct clk *clk)
{
   const struct clk_ops *ops;

   ...
   ops = clk_dev_ops(dev);

(where that is defined in the header file)

[..]

> > > +/**
> > > + * struct fwu_image_bank_info - firmware image information
> > > + * @image_uuid: Guid value of the image in this bank
> > > + * @accepted: Acceptance status of the image
> > > + * @reserved: Reserved
> > > + *
> > > + * The structure contains image specific fields which are
> > > + * used to identify the image and to specify the image's
> > > + * acceptance status
> > > + */
> > > +struct fwu_image_bank_info {
> > > +       efi_guid_t  image_uuid;
> > > +       uint32_t accepted;
> > > +       uint32_t reserved;
> > > +} __attribute__((__packed__));
> >
> > Why is this packed?
>
> This was based on a review comment from Masami [1], as he wanted to
> use the same structure in the low level bootloader as well.

It doesn't actually make any sense though. The packed struct is the same as
the normal struct, so far as I can tell. What am I missing?

It does have a cost for the compiler. For example I tried adding __packed
to struct image_header (which has the same issue mentioned by Masami in
that it is a file header) and it added 400 bytes to snow.

[..]

>
> -sughosh
>
> [1] - https://lists.denx.de/pipermail/u-boot/2021-December/470118.html

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata
  2022-08-17 12:43 ` [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata Sughosh Ganu
  2022-08-17 17:00   ` Jassi Brar
@ 2022-08-18 17:50   ` Simon Glass
  1 sibling, 0 replies; 46+ messages in thread
From: Simon Glass @ 2022-08-18 17:50 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> Add weak functions for getting the update index value and dfu
> alternate number needed for FWU Multi Bank update
> functionality.
>
> The current implementation for getting the update index value is for
> platforms with 2 banks. If a platform supports more than 2 banks, it
> can implement it's own function. The function to get the dfu alternate
> number has been added for platforms with GPT partitioned storage
> devices. Platforms with other storage partition scheme need to
> implement their own function.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> ---
> Changes since V7:
> * Moved the API's fwu_plat_get_update_index() and
>   fwu_plat_get_alt_num() as weak functions in common code as suggested
>   by Ilias.
>
>  include/fwu.h             |   1 +
>  lib/fwu_updates/Makefile  |   7 +++
>  lib/fwu_updates/fwu.c     |  22 ++++++++
>  lib/fwu_updates/fwu_gpt.c | 104 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 134 insertions(+)
>  create mode 100644 lib/fwu_updates/Makefile
>  create mode 100644 lib/fwu_updates/fwu.c
>  create mode 100644 lib/fwu_updates/fwu_gpt.c
>
> diff --git a/include/fwu.h b/include/fwu.h
> index 8259c75d12..f14175cc9a 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -51,4 +51,5 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32
bank);
>
>  int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t *image_guid,
>                          int *alt_num);
> +int fwu_plat_get_update_index(u32 *update_idx);

Don't forget to add a proper comment, also this should be uint, not u32

>  #endif /* _FWU_H_ */
> diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile
> new file mode 100644
> index 0000000000..1993088e5b
> --- /dev/null
> +++ b/lib/fwu_updates/Makefile
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (c) 2022, Linaro Limited
> +#
> +
> +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o
> +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_gpt.o
> diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> new file mode 100644
> index 0000000000..9808036eec
> --- /dev/null
> +++ b/lib/fwu_updates/fwu.c
> @@ -0,0 +1,22 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#include <fwu.h>
> +#include <fwu_mdata.h>
> +
> +__weak int fwu_plat_get_update_index(u32 *update_idx)

This should come from the device tree, right?

> +{
> +       int ret;
> +       u32 active_idx;
> +
> +       ret = fwu_get_active_index(&active_idx);
> +
> +       if (ret < 0)
> +               return -1;
> +
> +       *update_idx = active_idx ^= 0x1;
> +
> +       return ret;
> +}
> diff --git a/lib/fwu_updates/fwu_gpt.c b/lib/fwu_updates/fwu_gpt.c
> new file mode 100644
> index 0000000000..b7ccca3645
> --- /dev/null
> +++ b/lib/fwu_updates/fwu_gpt.c
> @@ -0,0 +1,104 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#include <blk.h>
> +#include <dfu.h>
> +#include <efi.h>
> +#include <efi_loader.h>
> +#include <fwu.h>
> +#include <log.h>
> +#include <part.h>
> +
> +#include <linux/errno.h>
> +
> +static int get_gpt_dfu_identifier(struct blk_desc *desc, efi_guid_t
*image_guid)
> +{
> +       int i;
> +       struct disk_partition info;
> +       efi_guid_t unique_part_guid;
> +
> +       for (i = 1; i < MAX_SEARCH_PARTITIONS; i++) {
> +               if (part_get_info(desc, i, &info))
> +                       continue;
> +               uuid_str_to_bin(info.uuid, unique_part_guid.b,
> +                               UUID_STR_FORMAT_GUID);
> +
> +               if (!guidcmp(&unique_part_guid, image_guid))
> +                       return i;
> +       }
> +
> +       log_err("No partition found with image_guid %pUs\n", image_guid);
> +       return -ENOENT;
> +}
> +
> +static int fwu_gpt_get_alt_num(struct blk_desc *desc, efi_guid_t
*image_guid,
> +                              int *alt_num, unsigned char dfu_dev)
> +{
> +       int ret = -1;
> +       int i, part, dev_num;
> +       int nalt;
> +       struct dfu_entity *dfu;
> +
> +       dev_num = desc->devnum;
> +       part = get_gpt_dfu_identifier(desc, image_guid);
> +       if (part < 0)
> +               return -ENOENT;
> +
> +       dfu_init_env_entities(NULL, NULL);
> +
> +       nalt = 0;
> +       list_for_each_entry(dfu, &dfu_list, list) {
> +               nalt++;
> +       }
> +
> +       if (!nalt) {
> +               log_warning("No entities in dfu_alt_info\n");
> +               dfu_free_entities();
> +               return -ENOENT;
> +       }
> +
> +       for (i = 0; i < nalt; i++) {
> +               dfu = dfu_get_entity(i);
> +
> +               if (!dfu)
> +                       continue;
> +
> +               /*
> +                * Currently, Multi Bank update
> +                * feature is being supported
> +                * only on GPT partitioned
> +                * MMC/SD devices.
> +                */
> +               if (dfu->dev_type != dfu_dev)
> +                       continue;
> +
> +               if (dfu->layout == DFU_RAW_ADDR &&
> +                   dfu->data.mmc.dev_num == dev_num &&
> +                   dfu->data.mmc.part == part) {
> +                       *alt_num = dfu->alt;
> +                       ret = 0;
> +                       break;
> +               }
> +       }
> +
> +       dfu_free_entities();
> +
> +       return ret;
> +}
> +
> +__weak int fwu_plat_get_alt_num(struct udevice *dev, efi_guid_t
*image_guid,
> +                               int *alt_num)
> +{
> +       struct blk_desc *desc;
> +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> +
> +       desc = dev_get_uclass_plat(priv->blk_dev);
> +       if (!desc) {
> +               log_err("Block device not found\n");
> +               return -ENODEV;
> +       }

Please remove all of these checks. They do nothing since it cannot happen.
Also please check you don't use -ENODEV anywhere.

You cannot use a device (in most cases) unless it is probed, so make sure
you are using the 'get' uclass functions rather than the 'find' functions

> +
> +       return fwu_gpt_get_alt_num(desc, image_guid, alt_num,
DFU_DEV_MMC);
> +}
> --
> 2.34.1
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-08-18 17:49       ` Simon Glass
@ 2022-08-19  7:35         ` Sughosh Ganu
  0 siblings, 0 replies; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-19  7:35 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 23:19, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Thu, 18 Aug 2022 at 05:39, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > hi Simon,
> >
> > On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Sughosh,
> > >
> > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > >
> > > > In the FWU Multi Bank Update feature, the information about the
> > > > updatable images is stored as part of the metadata, on a separate
> > > > partition. Add a driver for reading from and writing to the metadata
> > > > when the updatable images and the metadata are stored on a block
> > > > device which is formated with GPT based partition scheme.
> > > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > > ---
> > > > Changes since V7: None
> > > >
> > > >  drivers/fwu-mdata/Kconfig             |   9 +
> > > >  drivers/fwu-mdata/Makefile            |   1 +
> > > >  drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 410 ++++++++++++++++++++++++++
> > > >  include/fwu.h                         |   5 +
> > > >  4 files changed, 425 insertions(+)
> > > >  create mode 100644 drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> > > >
> > > > diff --git a/drivers/fwu-mdata/Kconfig b/drivers/fwu-mdata/Kconfig
> > > > index d6a21c8e19..d5edef19d6 100644
> > > > --- a/drivers/fwu-mdata/Kconfig
> > > > +++ b/drivers/fwu-mdata/Kconfig
> > > > @@ -5,3 +5,12 @@ config DM_FWU_MDATA
> > > >           Enable support for accessing FWU Metadata partitions. The
> > > >           FWU Metadata partitions reside on the same storage device
> > > >           which contains the other FWU updatable firmware images.
> > >
> > > Can we link to the docs here, or will it be easy for people to find in
> > > the U-Boot docs?
> >
> > The link to the spec is being provided in the documentation for the
> > feature. I guess that should suffice.
>
> Yes it's the U-Boot documentation that I am referring to. I assume people can type 'FWU metadata' in the docs and it will come up. If so, that seems OK.
>
> >
> > >
> > > > +
> > > > +config FWU_MDATA_GPT_BLK
> > > > +       bool "FWU Metadata access for GPT partitioned Block devices"
> > > > +       select PARTITION_TYPE_GUID
> > > > +       select PARTITION_UUIDS
> > > > +       depends on DM && HAVE_BLOCK_DEVICE && EFI_PARTITION
> > > > +       help
> > > > +         Enable support for accessing FWU Metadata on GPT partitioned
> > > > +         block devices.
> > >
> > > GPT-partitioned (I think)
> >
> > I see "GPT partition" being used elsewhere. I don't have a strong
> > opinion on this though.
> >
> > >
> > > > diff --git a/drivers/fwu-mdata/Makefile b/drivers/fwu-mdata/Makefile
> > > > index e53a8c9983..313049f67a 100644
> > > > --- a/drivers/fwu-mdata/Makefile
> > > > +++ b/drivers/fwu-mdata/Makefile
> > > > @@ -4,3 +4,4 @@
> > > >  #
> > > >
> > > >  obj-$(CONFIG_DM_FWU_MDATA) += fwu-mdata-uclass.o
> > > > +obj-$(CONFIG_FWU_MDATA_GPT_BLK) += fwu_mdata_gpt_blk.o
> > > > diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> > >
> > > Perhaps just call it gpt_blk.c since it is in this directory
> >
> > Actually, there are both type of examples that can be seen under
> > drivers/. For e.g. the drivers/clk/ has all files starting with clk_*.
> > Similarly, under drivers/reset/. But there are other examples as well.
> > But this is not a big effort. I will change the name as per your
> > suggestion.
> >
> > >
> > > > new file mode 100644
> > > > index 0000000000..f694c4369b
> > > > --- /dev/null
> > > > +++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
> > > > @@ -0,0 +1,410 @@
> > > > +// SPDX-License-Identifier: GPL-2.0-or-later
> > > > +/*
> > > > + * Copyright (c) 2022, Linaro Limited
> > > > + */
> > > > +
> > > > +#define LOG_CATEGORY UCLASS_FWU_MDATA
> > > > +
> > > > +#include <blk.h>
> > > > +#include <dm.h>
> > > > +#include <efi_loader.h>
> > > > +#include <fwu.h>
> > > > +#include <fwu_mdata.h>
> > > > +#include <log.h>
> > > > +#include <malloc.h>
> > > > +#include <memalign.h>
> > > > +#include <part.h>
> > > > +#include <part_efi.h>
> > > > +
> > > > +#include <dm/device-internal.h>
> > > > +#include <linux/errno.h>
> > > > +#include <linux/types.h>
> > > > +#include <u-boot/crc.h>
> > > > +
> > > > +#define PRIMARY_PART           BIT(0)
> > > > +#define SECONDARY_PART         BIT(1)
> > > > +#define BOTH_PARTS             (PRIMARY_PART | SECONDARY_PART)
> > > > +
> > > > +#define MDATA_READ             BIT(0)
> > > > +#define MDATA_WRITE            BIT(1)
> > > > +
> > >
> > > comment?
> >
> > Umm, is the macro name not descriptive enough? They are just being
> > used to select a read or write operation.
>
> I mean the function below
>
> >
> > >
> > > > +static int gpt_get_mdata_partitions(struct blk_desc *desc,
> > > > +                                   u16 *primary_mpart,
> > > > +                                   u16 *secondary_mpart)
> > >
> > > Should use uint, no need to select a 16-bit var so far as I can get
> >
> > Okay
> >
>
> [..]
>
> > > > +static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata)
> > >
> > > mdatap
> >
> > Okay
> >
> > >
> > > > +{
> > > > +       int ret;
> > > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > >
> > > uint
> >
> > Okay
> >
> > >
> > > Also do you need to set them to 0
> > >
> > > Declare a locate mdata and use that here instead of *mdata, which is a pain.
> >
> > This function is copying the metadata into the callers copy. Unless I
> > don't understand your comment.
>
> I mean it is easier to do this (the pattern common in driver model);
>
> static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdatap)
> {
>     struct fwu_mdata *mdata;
>
>     mdata = malloc(sizeof(struct fwu_mdata));
>     ... (use mdata throughout function)
>
>     *mdatap = mdata;
>
>     return 0;
> }

Fair enough. Based on your comment in the other patch, I will look at
the code to see where I can use the stack instead of allocating memory
for the metadata.

>
> [..]
>
> > >
> > > > +       ret = gpt_read_mdata(desc, *mdata, secondary_mpart);
> > > > +       if (ret < 0) {
> > > > +               log_err("Failed to read the FWU metadata from the device\n");
> > > > +               return -EIO;
> > > > +       }
> > > > +
> > > > +       ret = fwu_verify_mdata(*mdata, 0);
> > > > +       if (!ret)
> > > > +               return 0;
> > > > +
> > > > +       /* Both the FWU metadata copies are corrupted. */
> > > > +       return -1;
> > >
> > > This is -EPERM
> > >
> > > Perhaps choose something else?
> >
> > Again, I am not sure what would be a suitable error to return in this case.
>
> Take a look at errno.h and pick one. Maybe -ELIBBAD ?
>
> It doesn't matter much, so long as your upper-level command code can decode the error and report it.

Okay. I will change log_err to log_debug in the driver code.

-sughosh

>
> >
> > >
> > > > +}
> > > > +
> > > > +static int gpt_check_mdata_validity(struct udevice *dev)
> > > > +{
> > > > +       int ret;
> > > > +       struct blk_desc *desc;
> > > > +       struct fwu_mdata pri_mdata;
> > > > +       struct fwu_mdata secondary_mdata;
> > > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > > > +       u16 valid_partitions, invalid_partitions;
> > > > +       struct fwu_mdata_gpt_blk_priv *priv = dev_get_priv(dev);
> > > > +
> > > > +       desc = dev_get_uclass_plat(priv->blk_dev);
> > > > +       if (!desc) {
> > > > +               log_err("Block device not found\n");
> > > > +               return -ENODEV;
> > > > +       }
> > > > +
> > > > +       /*
> > > > +        * Two FWU metadata partitions are expected.
> > > > +        * If we don't have two, user needs to create
> > > > +        * them first
> > > > +        */
> > > > +       valid_partitions = 0;
> > > > +       ret = gpt_get_mdata_partitions(desc, &primary_mpart,
> > > > +                                      &secondary_mpart);
> > > > +
> > > > +       if (ret < 0) {
> > > > +               log_err("Error getting the FWU metadata partitions\n");
> > > > +               return -ENODEV;
> > > > +       }
> > > > +
> > > > +       ret = gpt_read_mdata(desc, &pri_mdata, primary_mpart);
> > > > +       if (ret < 0) {
> > > > +               log_err("Failed to read the FWU metadata from the device\n");
> > > > +               goto secondary_read;
> > > > +       }
> > > > +
> > > > +       ret = fwu_verify_mdata(&pri_mdata, 1);
> > > > +       if (!ret)
> > > > +               valid_partitions |= PRIMARY_PART;
> > > > +
> > > > +secondary_read:
> > > > +       /* Now check the secondary partition */
> > > > +       ret = gpt_read_mdata(desc, &secondary_mdata, secondary_mpart);
> > > > +       if (ret < 0) {
> > > > +               log_err("Failed to read the FWU metadata from the device\n");
> > > > +               goto mdata_restore;
> > > > +       }
> > > > +
> > > > +       ret = fwu_verify_mdata(&secondary_mdata, 0);
> > > > +       if (!ret)
> > > > +               valid_partitions |= SECONDARY_PART;
> > > > +
> > > > +mdata_restore:
> > > > +       if (valid_partitions == (PRIMARY_PART | SECONDARY_PART)) {
> > > > +               ret = -1;
> > > > +               /*
> > > > +                * Before returning, check that both the
> > > > +                * FWU metadata copies are the same. If not,
> > > > +                * the FWU metadata copies need to be
> > > > +                * re-populated.
> > > > +                */
> > > > +               if (!memcmp(&pri_mdata, &secondary_mdata,
> > > > +                           sizeof(struct fwu_mdata))) {
> > > > +                       ret = 0;
> > > > +               } else {
> > > > +                       log_err("Both FWU metadata copies are valid but do not match. Please check!\n");
> > >
> > > Honestly the error handling needs a rethink IMO. You should try to
> > > return error codes that indicate what went wrong (you mostly do in
> > > this file) and then have the top-level code decode those errors and
> > > produce an error message.
> >
> > The code in efi_capsule.c which is calling the APIs is checking the
> > error codes and printing the error messages.
>
> log_err() prints a message, though. Change this to log_debug() and it won't appear unless specifically enabled.
>
> [..]
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-18 17:49       ` Simon Glass
@ 2022-08-19  7:41         ` Sughosh Ganu
  2022-08-19 15:24           ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-19  7:41 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 23:19, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Thu, 18 Aug 2022 at 05:53, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > hi Simon,
> >
> > On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Sugosh,
> > >
> > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > >
> > > > Add a command to read the metadata as specified in the FWU
> > > > specification and print the fields of the metadata.
> > > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > ---
> > > > Changes since V7: None
> > > >
> > > >  cmd/Kconfig     |  7 +++++
> > > >  cmd/Makefile    |  1 +
> > > >  cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 88 insertions(+)
> > > >  create mode 100644 cmd/fwu_mdata.c
> > >
> > > This needs docs and a test.
> > >
> > > BTW I forgot to mention that the uclass needs a simple test of some sort.
> > >
> > > https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html
> >
> > Okay. I will check how this can be done. Btw, there are plans to add a
> > test for the feature once support for the feature has been added on
> > the Synquacer platform. That test will exercise the above command as
> > well as the driver code. Do we still need a standalone test for the
> > uclass?
>
> Yes, testing on real hardware has nothing to do with the uclass test, which runs on sandbox. It should be a small unit test like others in test/dm/...

I am not talking about testing on real hardware, but a test to be run
on sandbox. I had posted the relevant patch [1] in an earlier version
of the patch series. But this test relies on support being added for
the feature on the Synquacer platform. Once those patches get in, I
will be adding the test for the feature as well. And this test
exercises both the fwu_mdata_read command as well as the driver code.
Which is why I was asking if it is necessary to add additional tests
for the command and dm code.

-sughosh

[1] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html

>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-18 17:49       ` Simon Glass
@ 2022-08-19 13:36         ` Sughosh Ganu
  2022-08-19 15:23           ` Simon Glass
  2022-08-19 14:59         ` Jassi Brar
  1 sibling, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-19 13:36 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Thu, 18 Aug 2022 at 23:20, Simon Glass <sjg@chromium.org> wrote:
>
> pHi Sughosh,
>
> On Thu, 18 Aug 2022 at 05:03, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > hi Simon,
> >
> > On Thu, 18 Aug 2022 at 06:43, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Sughosh,
> > >
> > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > >
> > > > In the FWU Multi Bank Update feature, the information about the
> > > > updatable images is stored as part of the metadata, which is stored on
> > > > a dedicated partition. Add the metadata structure, and a driver model
> > > > uclass which provides functions to access the metadata. These are
> > > > generic API's, and implementations can be added based on parameters
> > > > like how the metadata partition is accessed and what type of storage
> > > > device houses the metadata.
> > > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > > ---
> > > > Changes since V7:
> > > > * Rephrased the error message in fwu_update_active_index as per
> > > >   suggestion from Ilias.
> > > > * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
> > > >   from Ilias.
> > > >
> > > >  drivers/Kconfig                      |   2 +
> > > >  drivers/Makefile                     |   1 +
> > > >  drivers/fwu-mdata/Kconfig            |   7 +
> > > >  drivers/fwu-mdata/Makefile           |   6 +
> > > >  drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
> > > >  include/dm/uclass-id.h               |   1 +
> > > >  include/fwu.h                        |  49 +++
> > > >  include/fwu_mdata.h                  |  67 ++++
> > > >  8 files changed, 596 insertions(+)
> > > >  create mode 100644 drivers/fwu-mdata/Kconfig
> > > >  create mode 100644 drivers/fwu-mdata/Makefile
> > > >  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
> > > >  create mode 100644 include/fwu.h
> > > >  create mode 100644 include/fwu_mdata.h
> > > >
> > > > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > > > index 8b6fead351..75ac149d31 100644
> > > > --- a/drivers/Kconfig
> > > > +++ b/drivers/Kconfig
> > > > @@ -44,6 +44,8 @@ source "drivers/fuzz/Kconfig"
> > > >
> > > >  source "drivers/fpga/Kconfig"
> > > >
> > > > +source "drivers/fwu-mdata/Kconfig"
> > > > +
> > > >  source "drivers/gpio/Kconfig"
> > > >
> > > >  source "drivers/hwspinlock/Kconfig"
>
> [..]
>
> > > > +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part)
> > > > +{
> > > > +       u32 calc_crc32;
> > > > +       void *buf;
> > > > +
> > > > +       buf = &mdata->version;
> > > > +       calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
> > > > +
> > > > +       if (calc_crc32 != mdata->crc32) {
> > > > +               log_err("crc32 check failed for %s FWU metadata partition\n",
> > > > +                       pri_part ? "primary" : "secondary");
> > > > +               return -1;
> > >
> > > Please use an -Exxx value like -EPERM
> >
> > I don't think there is any value which relates to a crc mismatch. If
> > you insist, I can think of -EIO, but I don't think -EPERM is a good
> > match in this case.
>
> See my comment in the other patch. You should not be printing messages in a uclass or driver, except in extreme situations.
>
> Choose a value that is somewhat meaningful so you can report the error sensibly in top-level command code.
>
> >
> > >
> > > > +       }
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + * fwu_get_active_index() - Get active_index from the FWU metadata
> > > > + * @active_idx: active_index value to be read
> > > > + *
> > > > + * Read the active_index field from the FWU metadata and place it in
> > > > + * the variable pointed to be the function argument.
> > > > + *
> > > > + * Return: 0 if OK, -ve on error
> > > > + *
> > > > + */
> > > > +int fwu_get_active_index(u32 *active_idx)
> > >
> > > Return the active index rather than having an arg?
> >
> > I would prefer to keep it the way it is. That allows returning an
> > error value and keep the active_index separate. Moreover it is just a
> > single parameter.
>
> OK, then can you use active_idxp for the name, as is generally done in driver model?
>
> >
> > >
> > > > +{
> > > > +       int ret;
> > > > +       struct fwu_mdata *mdata = NULL;
> > > > +
> > > > +       ret = fwu_get_mdata(&mdata);
> > >
> > > Can you use a local var and avoid the malloc() / free() ?
> >
> > Do you see any disadvantages of using space on the heap? If you don't
> > have a strong opinion on this, I would prefer to keep it as is.
>
> Yes, this is not UEFI and we try to avoid allocating memory to no purpose. It takes time and fragments the heap.
>
> >
> > >
> > > > +       if (ret < 0) {
> > > > +               log_err("Unable to get valid FWU metadata\n");
> > > > +               goto out;
> > > > +       }
> > > > +
> > > > +       /*
> > > > +        * Found the FWU metadata partition, now read the active_index
> > > > +        * value
> > > > +        */
> > > > +       *active_idx = mdata->active_index;
> > > > +       if (*active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> > > > +               log_err("Active index value read is incorrect\n");
> > > > +               ret = -EINVAL;
> > > > +       }
> > > > +
> > > > +out:
> > > > +       free(mdata);
> > > > +
> > > > +       return ret;
> > > > +}
> > > > +
> > > > +/**
> > > > + * fwu_update_active_index() - Update active_index from the FWU metadata
> > > > + * @active_idx: active_index value to be updated
> > > > + *
> > > > + * Update the active_index field in the FWU metadata
> > > > + *
> > > > + * Return: 0 if OK, -ve on error
> > > > + *
> > > > + */
> > > > +int fwu_update_active_index(u32 active_idx)
> > >
> > > uint
> >
> > Are you referring to the function parameter? If so, it is a u32 since
> > the active_index field in the metadata structure defined in the spec
> > is a 32 bit value.
>
> Sure, but how does that affect the function parameter? Generally we should use natural types in function parameters so we don't do silly things like force a 32-bit arg into a 64-bit register, causing the compiler to have to mask the value, etc.
>
> [..]
>
> > > > +/**
> > > > + * fwu_get_image_alt_num() - Get the dfu alt number to be used for capsule update
> > > > + * @image_type_id: pointer to the image GUID as passed in the capsule
> > > > + * @update_bank: Bank to which the update is to be made
> > > > + * @alt_num: The alt_num for the image
> > > > + *
> > > > + * Based on the GUID value passed in the capsule, along with the bank to which the
> > > > + * image needs to be updated, get the dfu alt number which will be used for the
> > > > + * capsule update
> > > > + *
> > > > + * Return: 0 if OK, -ve on error
> > > > + *
> > > > + */
> > > > +int fwu_get_image_alt_num(efi_guid_t *image_type_id, u32 update_bank,
> > > > +                         int *alt_num)
> > >
> > > alt_nump is often used with driver model to indicate a return
> > > value.Again I wonder if the return value could be used?
> >
> > Can you point me to an example? I could not find any instance of this.
>
> Where did you look? Just to take one example, returning a device:
>
> git grep -w devp drivers/ |wc -l
> 316
>
> > Again, I believe this is a matter of taste, so I would prefer the
> > current method.
>
> Please fit into the uclass / driver model code style.
>
> >
> > >
> > > > +{
> > > > +       int ret, i;
> > > > +       efi_guid_t *image_guid;
> > > > +       struct udevice *dev = NULL;
> > > > +       struct fwu_mdata *mdata = NULL;
> > >
> > > Please don't set things to NULL for no reason, it cluttlers the code.
> >
> > This is being set to NULL in case the called function that is supposed
> > to populate the metadata structure fails to do so. We can pass NULL to
> > free, else it could result in freeing up of unrelated memory.
>
> If the function fails to set it, then the compiler will complain.
>
> I don't understand your comment about NULL. free(NULL) is valid in U-Boot, if that is what you are wondering?
>
> >
> > >
> > > > +       struct fwu_image_entry *img_entry;
> > > > +       const struct fwu_mdata_ops *ops = NULL;
> > > > +       struct fwu_image_bank_info *img_bank_info;
> > > > +
> > > > +       ret = fwu_get_dev_ops(&dev, &ops);
> > >
> > > Rather than this, see the pattern used by other uclasses
> >
> > Can you point me to some example code. Also, not sure what the issue
> > is with using this function.
>
> It is a pointless obfuscation, mainly. See for example clk_request(), but most uclasses use this pattern. I really encourage you to read more of the code before submitting a patch.
>
> int clk_request(struct udevice *dev, struct clk *clk)
> {
>    const struct clk_ops *ops;
>
>    ...
>    ops = clk_dev_ops(dev);
>
> (where that is defined in the header file)

If you mean clk_dev_ops, it is defined in clk-uclass.c, and IMO that
makes sense, since it is being called multiple times in the driver.
Similarly, the fwu_get_dev_ops is being called multiple times in the
uclass driver, so I think it makes sense to have it as a function. If
you want me to move it to a header file or rename it, I can do that.

-sughosh
>
> [..]
>
> > > > +/**
> > > > + * struct fwu_image_bank_info - firmware image information
> > > > + * @image_uuid: Guid value of the image in this bank
> > > > + * @accepted: Acceptance status of the image
> > > > + * @reserved: Reserved
> > > > + *
> > > > + * The structure contains image specific fields which are
> > > > + * used to identify the image and to specify the image's
> > > > + * acceptance status
> > > > + */
> > > > +struct fwu_image_bank_info {
> > > > +       efi_guid_t  image_uuid;
> > > > +       uint32_t accepted;
> > > > +       uint32_t reserved;
> > > > +} __attribute__((__packed__));
> > >
> > > Why is this packed?
> >
> > This was based on a review comment from Masami [1], as he wanted to
> > use the same structure in the low level bootloader as well.
>
> It doesn't actually make any sense though. The packed struct is the same as the normal struct, so far as I can tell. What am I missing?
>
> It does have a cost for the compiler. For example I tried adding __packed to struct image_header (which has the same issue mentioned by Masami in that it is a file header) and it added 400 bytes to snow.
>
> [..]
>
> >
> > -sughosh
> >
> > [1] - https://lists.denx.de/pipermail/u-boot/2021-December/470118.html

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-18 17:49       ` Simon Glass
  2022-08-19 13:36         ` Sughosh Ganu
@ 2022-08-19 14:59         ` Jassi Brar
  2022-08-19 15:24           ` Simon Glass
  1 sibling, 1 reply; 46+ messages in thread
From: Jassi Brar @ 2022-08-19 14:59 UTC (permalink / raw)
  To: Simon Glass
  Cc: Sughosh Ganu, U-Boot Mailing List, Heinrich Schuchardt,
	Ilias Apalodimas, Takahiro Akashi, Patrick Delaunay,
	Patrice Chotard, Bin Meng, Tom Rini, Etienne Carriere,
	Michal Simek, Jassi Brar

Hi Simon,

On Thu, Aug 18, 2022 at 12:50 PM Simon Glass <sjg@chromium.org> wrote:

> > > > +/**
> > > > + * struct fwu_image_bank_info - firmware image information
> > > > + * @image_uuid: Guid value of the image in this bank
> > > > + * @accepted: Acceptance status of the image
> > > > + * @reserved: Reserved
> > > > + *
> > > > + * The structure contains image specific fields which are
> > > > + * used to identify the image and to specify the image's
> > > > + * acceptance status
> > > > + */
> > > > +struct fwu_image_bank_info {
> > > > +       efi_guid_t  image_uuid;
> > > > +       uint32_t accepted;
> > > > +       uint32_t reserved;
> > > > +} __attribute__((__packed__));
> > >
> > > Why is this packed?
> >
> > This was based on a review comment from Masami [1], as he wanted to
> > use the same structure in the low level bootloader as well.
>
> It doesn't actually make any sense though. The packed struct is the same as
> the normal struct, so far as I can tell. What am I missing?
>
I think because we want the structure to be read/written onto
persistent storage, and possibly manipulated by entities other than
uboot.

I totally agree with all the rest of your comments on the patchset.

cheers!

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-19 13:36         ` Sughosh Ganu
@ 2022-08-19 15:23           ` Simon Glass
  2022-08-19 16:18             ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-19 15:23 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Fri, 19 Aug 2022 at 07:36, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Thu, 18 Aug 2022 at 23:20, Simon Glass <sjg@chromium.org> wrote:
> >
> > pHi Sughosh,
> >
> > On Thu, 18 Aug 2022 at 05:03, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > >
> > > hi Simon,
> > >
> > > On Thu, 18 Aug 2022 at 06:43, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Sughosh,
> > > >
> > > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > >
> > > > > In the FWU Multi Bank Update feature, the information about the
> > > > > updatable images is stored as part of the metadata, which is stored on
> > > > > a dedicated partition. Add the metadata structure, and a driver model
> > > > > uclass which provides functions to access the metadata. These are
> > > > > generic API's, and implementations can be added based on parameters
> > > > > like how the metadata partition is accessed and what type of storage
> > > > > device houses the metadata.
> > > > >
> > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > > > ---
> > > > > Changes since V7:
> > > > > * Rephrased the error message in fwu_update_active_index as per
> > > > >   suggestion from Ilias.
> > > > > * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
> > > > >   from Ilias.
> > > > >
> > > > >  drivers/Kconfig                      |   2 +
> > > > >  drivers/Makefile                     |   1 +
> > > > >  drivers/fwu-mdata/Kconfig            |   7 +
> > > > >  drivers/fwu-mdata/Makefile           |   6 +
> > > > >  drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
> > > > >  include/dm/uclass-id.h               |   1 +
> > > > >  include/fwu.h                        |  49 +++
> > > > >  include/fwu_mdata.h                  |  67 ++++
> > > > >  8 files changed, 596 insertions(+)
> > > > >  create mode 100644 drivers/fwu-mdata/Kconfig
> > > > >  create mode 100644 drivers/fwu-mdata/Makefile
> > > > >  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
> > > > >  create mode 100644 include/fwu.h
> > > > >  create mode 100644 include/fwu_mdata.h
> > > > >

[..]

> >
> > I don't understand your comment about NULL. free(NULL) is valid in U-Boot, if that is what you are wondering?
> >
> > >
> > > >
> > > > > +       struct fwu_image_entry *img_entry;
> > > > > +       const struct fwu_mdata_ops *ops = NULL;
> > > > > +       struct fwu_image_bank_info *img_bank_info;
> > > > > +
> > > > > +       ret = fwu_get_dev_ops(&dev, &ops);
> > > >
> > > > Rather than this, see the pattern used by other uclasses
> > >
> > > Can you point me to some example code. Also, not sure what the issue
> > > is with using this function.
> >
> > It is a pointless obfuscation, mainly. See for example clk_request(), but most uclasses use this pattern. I really encourage you to read more of the code before submitting a patch.
> >
> > int clk_request(struct udevice *dev, struct clk *clk)
> > {
> >    const struct clk_ops *ops;
> >
> >    ...
> >    ops = clk_dev_ops(dev);
> >
> > (where that is defined in the header file)
>
> If you mean clk_dev_ops, it is defined in clk-uclass.c, and IMO that
> makes sense, since it is being called multiple times in the driver.
> Similarly, the fwu_get_dev_ops is being called multiple times in the
> uclass driver, so I think it makes sense to have it as a function. If
> you want me to move it to a header file or rename it, I can do that.

Yes, rename and move to header, and use the same function signature as
clk and the other uclasses (i.e. no dev parameter).

Your uclass functions need to be defined with a device parameter as
the first arg. They cannot go and hunt down a uclass themselves. See
other uclasses for how this works.

If you want a common function to find the first device, use
uclass_first_device() in the caller, not internal to the uclass!

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-19  7:41         ` Sughosh Ganu
@ 2022-08-19 15:24           ` Simon Glass
  2022-08-22  4:59             ` Sughosh Ganu
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-19 15:24 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Fri, 19 Aug 2022 at 01:41, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Thu, 18 Aug 2022 at 23:19, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Thu, 18 Aug 2022 at 05:53, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > >
> > > hi Simon,
> > >
> > > On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Sugosh,
> > > >
> > > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > >
> > > > > Add a command to read the metadata as specified in the FWU
> > > > > specification and print the fields of the metadata.
> > > > >
> > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > > ---
> > > > > Changes since V7: None
> > > > >
> > > > >  cmd/Kconfig     |  7 +++++
> > > > >  cmd/Makefile    |  1 +
> > > > >  cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >  3 files changed, 88 insertions(+)
> > > > >  create mode 100644 cmd/fwu_mdata.c
> > > >
> > > > This needs docs and a test.
> > > >
> > > > BTW I forgot to mention that the uclass needs a simple test of some sort.
> > > >
> > > > https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html
> > >
> > > Okay. I will check how this can be done. Btw, there are plans to add a
> > > test for the feature once support for the feature has been added on
> > > the Synquacer platform. That test will exercise the above command as
> > > well as the driver code. Do we still need a standalone test for the
> > > uclass?
> >
> > Yes, testing on real hardware has nothing to do with the uclass test, which runs on sandbox. It should be a small unit test like others in test/dm/...
>
> I am not talking about testing on real hardware, but a test to be run
> on sandbox. I had posted the relevant patch [1] in an earlier version
> of the patch series. But this test relies on support being added for
> the feature on the Synquacer platform. Once those patches get in, I
> will be adding the test for the feature as well. And this test
> exercises both the fwu_mdata_read command as well as the driver code.
> Which is why I was asking if it is necessary to add additional tests
> for the command and dm code.

It looks like that 'functional' test should be split into several unit
tests that check particular things. See how this works with bootstd,
in test/boot - the Python sets things up and the unit tests cover
particular areas. The test seems to rely on things happening at
reboot, so create a command to do those things, to provide for
testability.

So for example 'ut boot fwu_prepare_update' could set up the update
and 'ut boot fwu_apply_update' could apply it.

Regards,
Simon


>
> -sughosh
>
> [1] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html
>
> >
> > Regards,
> > Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-19 14:59         ` Jassi Brar
@ 2022-08-19 15:24           ` Simon Glass
  2022-08-19 16:09             ` Jassi Brar
  0 siblings, 1 reply; 46+ messages in thread
From: Simon Glass @ 2022-08-19 15:24 UTC (permalink / raw)
  To: Jassi Brar
  Cc: Sughosh Ganu, U-Boot Mailing List, Heinrich Schuchardt,
	Ilias Apalodimas, Takahiro Akashi, Patrick Delaunay,
	Patrice Chotard, Bin Meng, Tom Rini, Etienne Carriere,
	Michal Simek, Jassi Brar

Hi Jassi,

On Fri, 19 Aug 2022 at 08:59, Jassi Brar <jassisinghbrar@gmail.com> wrote:
>
> Hi Simon,
>
> On Thu, Aug 18, 2022 at 12:50 PM Simon Glass <sjg@chromium.org> wrote:
>
> > > > > +/**
> > > > > + * struct fwu_image_bank_info - firmware image information
> > > > > + * @image_uuid: Guid value of the image in this bank
> > > > > + * @accepted: Acceptance status of the image
> > > > > + * @reserved: Reserved
> > > > > + *
> > > > > + * The structure contains image specific fields which are
> > > > > + * used to identify the image and to specify the image's
> > > > > + * acceptance status
> > > > > + */
> > > > > +struct fwu_image_bank_info {
> > > > > +       efi_guid_t  image_uuid;
> > > > > +       uint32_t accepted;
> > > > > +       uint32_t reserved;
> > > > > +} __attribute__((__packed__));
> > > >
> > > > Why is this packed?
> > >
> > > This was based on a review comment from Masami [1], as he wanted to
> > > use the same structure in the low level bootloader as well.
> >
> > It doesn't actually make any sense though. The packed struct is the same as
> > the normal struct, so far as I can tell. What am I missing?
> >
> I think because we want the structure to be read/written onto
> persistent storage, and possibly manipulated by entities other than
> uboot.

But specifically, how does __packed help here? What are the other
entities doing that changes the format and what is __packed doing to
update that? This is actually standard C code.

>
> I totally agree with all the rest of your comments on the patchset.

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-19 15:24           ` Simon Glass
@ 2022-08-19 16:09             ` Jassi Brar
  0 siblings, 0 replies; 46+ messages in thread
From: Jassi Brar @ 2022-08-19 16:09 UTC (permalink / raw)
  To: Simon Glass
  Cc: Sughosh Ganu, U-Boot Mailing List, Heinrich Schuchardt,
	Ilias Apalodimas, Takahiro Akashi, Patrick Delaunay,
	Patrice Chotard, Bin Meng, Tom Rini, Etienne Carriere,
	Michal Simek, Jassi Brar

On Fri, Aug 19, 2022 at 10:25 AM Simon Glass <sjg@chromium.org> wrote:
>
> Hi Jassi,
>
> On Fri, 19 Aug 2022 at 08:59, Jassi Brar <jassisinghbrar@gmail.com> wrote:
> >
> > Hi Simon,
> >
> > On Thu, Aug 18, 2022 at 12:50 PM Simon Glass <sjg@chromium.org> wrote:
> >
> > > > > > +/**
> > > > > > + * struct fwu_image_bank_info - firmware image information
> > > > > > + * @image_uuid: Guid value of the image in this bank
> > > > > > + * @accepted: Acceptance status of the image
> > > > > > + * @reserved: Reserved
> > > > > > + *
> > > > > > + * The structure contains image specific fields which are
> > > > > > + * used to identify the image and to specify the image's
> > > > > > + * acceptance status
> > > > > > + */
> > > > > > +struct fwu_image_bank_info {
> > > > > > +       efi_guid_t  image_uuid;
> > > > > > +       uint32_t accepted;
> > > > > > +       uint32_t reserved;
> > > > > > +} __attribute__((__packed__));
> > > > >
> > > > > Why is this packed?
> > > >
> > > > This was based on a review comment from Masami [1], as he wanted to
> > > > use the same structure in the low level bootloader as well.
> > >
> > > It doesn't actually make any sense though. The packed struct is the same as
> > > the normal struct, so far as I can tell. What am I missing?
> > >
> > I think because we want the structure to be read/written onto
> > persistent storage, and possibly manipulated by entities other than
> > uboot.
>
> But specifically, how does __packed help here? What are the other
> entities doing that changes the format and what is __packed doing to
> update that? This is actually standard C code.
>
It is just to make sure there is no padding between structure members,
and the size of structure is exactly as in the specification.
Though in this case it likely won't make any difference because the
members are already 16, 4 and 4 bytes.

Cheers.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-19 15:23           ` Simon Glass
@ 2022-08-19 16:18             ` Sughosh Ganu
  2022-08-21  0:11               ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-19 16:18 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Fri, 19 Aug 2022 at 20:53, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Fri, 19 Aug 2022 at 07:36, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > hi Simon,
> >
> > On Thu, 18 Aug 2022 at 23:20, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > pHi Sughosh,
> > >
> > > On Thu, 18 Aug 2022 at 05:03, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > >
> > > > hi Simon,
> > > >
> > > > On Thu, 18 Aug 2022 at 06:43, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Sughosh,
> > > > >
> > > > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > > >
> > > > > > In the FWU Multi Bank Update feature, the information about the
> > > > > > updatable images is stored as part of the metadata, which is stored on
> > > > > > a dedicated partition. Add the metadata structure, and a driver model
> > > > > > uclass which provides functions to access the metadata. These are
> > > > > > generic API's, and implementations can be added based on parameters
> > > > > > like how the metadata partition is accessed and what type of storage
> > > > > > device houses the metadata.
> > > > > >
> > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > > > > ---
> > > > > > Changes since V7:
> > > > > > * Rephrased the error message in fwu_update_active_index as per
> > > > > >   suggestion from Ilias.
> > > > > > * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
> > > > > >   from Ilias.
> > > > > >
> > > > > >  drivers/Kconfig                      |   2 +
> > > > > >  drivers/Makefile                     |   1 +
> > > > > >  drivers/fwu-mdata/Kconfig            |   7 +
> > > > > >  drivers/fwu-mdata/Makefile           |   6 +
> > > > > >  drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
> > > > > >  include/dm/uclass-id.h               |   1 +
> > > > > >  include/fwu.h                        |  49 +++
> > > > > >  include/fwu_mdata.h                  |  67 ++++
> > > > > >  8 files changed, 596 insertions(+)
> > > > > >  create mode 100644 drivers/fwu-mdata/Kconfig
> > > > > >  create mode 100644 drivers/fwu-mdata/Makefile
> > > > > >  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
> > > > > >  create mode 100644 include/fwu.h
> > > > > >  create mode 100644 include/fwu_mdata.h
> > > > > >
>
> [..]
>
> > >
> > > I don't understand your comment about NULL. free(NULL) is valid in U-Boot, if that is what you are wondering?
> > >
> > > >
> > > > >
> > > > > > +       struct fwu_image_entry *img_entry;
> > > > > > +       const struct fwu_mdata_ops *ops = NULL;
> > > > > > +       struct fwu_image_bank_info *img_bank_info;
> > > > > > +
> > > > > > +       ret = fwu_get_dev_ops(&dev, &ops);
> > > > >
> > > > > Rather than this, see the pattern used by other uclasses
> > > >
> > > > Can you point me to some example code. Also, not sure what the issue
> > > > is with using this function.
> > >
> > > It is a pointless obfuscation, mainly. See for example clk_request(), but most uclasses use this pattern. I really encourage you to read more of the code before submitting a patch.
> > >
> > > int clk_request(struct udevice *dev, struct clk *clk)
> > > {
> > >    const struct clk_ops *ops;
> > >
> > >    ...
> > >    ops = clk_dev_ops(dev);
> > >
> > > (where that is defined in the header file)
> >
> > If you mean clk_dev_ops, it is defined in clk-uclass.c, and IMO that
> > makes sense, since it is being called multiple times in the driver.
> > Similarly, the fwu_get_dev_ops is being called multiple times in the
> > uclass driver, so I think it makes sense to have it as a function. If
> > you want me to move it to a header file or rename it, I can do that.
>
> Yes, rename and move to header, and use the same function signature as
> clk and the other uclasses (i.e. no dev parameter).
>
> Your uclass functions need to be defined with a device parameter as
> the first arg. They cannot go and hunt down a uclass themselves. See
> other uclasses for how this works.
>
> If you want a common function to find the first device, use
> uclass_first_device() in the caller, not internal to the uclass!

I can do that, sure. But there doesn't seem to be uniformity in these
rules. There are a bunch of uclass drivers which seem to be doing
exactly the same thing, including, but not limited to bootcount,
pinctrl, regulators. These uclass drivers all have instances of common
API being called and the uclass driver finding the device. Please note
that the FWU uclass is not representing a real device -- it is pretty
similar to bootcount in that regard. Which was the primary reason I
kept the FWU API's device agnostic.

-sughosh

>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-08-19 16:18             ` Sughosh Ganu
@ 2022-08-21  0:11               ` Simon Glass
  0 siblings, 0 replies; 46+ messages in thread
From: Simon Glass @ 2022-08-21  0:11 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Fri, 19 Aug 2022 at 10:18, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Fri, 19 Aug 2022 at 20:53, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Fri, 19 Aug 2022 at 07:36, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > >
> > > hi Simon,
> > >
> > > On Thu, 18 Aug 2022 at 23:20, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > pHi Sughosh,
> > > >
> > > > On Thu, 18 Aug 2022 at 05:03, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > >
> > > > > hi Simon,
> > > > >
> > > > > On Thu, 18 Aug 2022 at 06:43, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Sughosh,
> > > > > >
> > > > > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > > > >
> > > > > > > In the FWU Multi Bank Update feature, the information about the
> > > > > > > updatable images is stored as part of the metadata, which is stored on
> > > > > > > a dedicated partition. Add the metadata structure, and a driver model
> > > > > > > uclass which provides functions to access the metadata. These are
> > > > > > > generic API's, and implementations can be added based on parameters
> > > > > > > like how the metadata partition is accessed and what type of storage
> > > > > > > device houses the metadata.
> > > > > > >
> > > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > > Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
> > > > > > > ---
> > > > > > > Changes since V7:
> > > > > > > * Rephrased the error message in fwu_update_active_index as per
> > > > > > >   suggestion from Ilias.
> > > > > > > * Reworked the logic in fwu_get_image_alt_num() as per the suggestion
> > > > > > >   from Ilias.
> > > > > > >
> > > > > > >  drivers/Kconfig                      |   2 +
> > > > > > >  drivers/Makefile                     |   1 +
> > > > > > >  drivers/fwu-mdata/Kconfig            |   7 +
> > > > > > >  drivers/fwu-mdata/Makefile           |   6 +
> > > > > > >  drivers/fwu-mdata/fwu-mdata-uclass.c | 463 +++++++++++++++++++++++++++
> > > > > > >  include/dm/uclass-id.h               |   1 +
> > > > > > >  include/fwu.h                        |  49 +++
> > > > > > >  include/fwu_mdata.h                  |  67 ++++
> > > > > > >  8 files changed, 596 insertions(+)
> > > > > > >  create mode 100644 drivers/fwu-mdata/Kconfig
> > > > > > >  create mode 100644 drivers/fwu-mdata/Makefile
> > > > > > >  create mode 100644 drivers/fwu-mdata/fwu-mdata-uclass.c
> > > > > > >  create mode 100644 include/fwu.h
> > > > > > >  create mode 100644 include/fwu_mdata.h
> > > > > > >
> >
> > [..]
> >
> > > >
> > > > I don't understand your comment about NULL. free(NULL) is valid in U-Boot, if that is what you are wondering?
> > > >
> > > > >
> > > > > >
> > > > > > > +       struct fwu_image_entry *img_entry;
> > > > > > > +       const struct fwu_mdata_ops *ops = NULL;
> > > > > > > +       struct fwu_image_bank_info *img_bank_info;
> > > > > > > +
> > > > > > > +       ret = fwu_get_dev_ops(&dev, &ops);
> > > > > >
> > > > > > Rather than this, see the pattern used by other uclasses
> > > > >
> > > > > Can you point me to some example code. Also, not sure what the issue
> > > > > is with using this function.
> > > >
> > > > It is a pointless obfuscation, mainly. See for example clk_request(), but most uclasses use this pattern. I really encourage you to read more of the code before submitting a patch.
> > > >
> > > > int clk_request(struct udevice *dev, struct clk *clk)
> > > > {
> > > >    const struct clk_ops *ops;
> > > >
> > > >    ...
> > > >    ops = clk_dev_ops(dev);
> > > >
> > > > (where that is defined in the header file)
> > >
> > > If you mean clk_dev_ops, it is defined in clk-uclass.c, and IMO that
> > > makes sense, since it is being called multiple times in the driver.
> > > Similarly, the fwu_get_dev_ops is being called multiple times in the
> > > uclass driver, so I think it makes sense to have it as a function. If
> > > you want me to move it to a header file or rename it, I can do that.
> >
> > Yes, rename and move to header, and use the same function signature as
> > clk and the other uclasses (i.e. no dev parameter).
> >
> > Your uclass functions need to be defined with a device parameter as
> > the first arg. They cannot go and hunt down a uclass themselves. See
> > other uclasses for how this works.
> >
> > If you want a common function to find the first device, use
> > uclass_first_device() in the caller, not internal to the uclass!
>
> I can do that, sure. But there doesn't seem to be uniformity in these
> rules. There are a bunch of uclass drivers which seem to be doing
> exactly the same thing, including, but not limited to bootcount,
> pinctrl, regulators. These uclass drivers all have instances of common

pinctrl has pinctrl_select_state() and two GPIO functions that violate
this. It should be fixed to store the default pinctrl driver in gd,
like we do with serial_dev. Please do send a patch if you can.

regulators have some functions which act on all regulators, or at
least a selection. That is fine, I think, but let me know if you see
somethign wrong.

bootcount is not fully converted to driver model and assumes a single
bootcount. That should be fixed. in that it should work like sysreset,
loading / storing from anything that exists (e.g. the 'walk'
functions).

> API being called and the uclass driver finding the device. Please note
> that the FWU uclass is not representing a real device -- it is pretty
> similar to bootcount in that regard. Which was the primary reason I
> kept the FWU API's device agnostic.

The 'real device' thing doesn't really matter. What is a real device,
anyway? Anything we want to model with drivers, a uclass and methods
is a device. It is also the primary way we call code from the
top-level part of U-Boot.

Regards,
Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-19 15:24           ` Simon Glass
@ 2022-08-22  4:59             ` Sughosh Ganu
  2022-08-22 16:39               ` Simon Glass
  0 siblings, 1 reply; 46+ messages in thread
From: Sughosh Ganu @ 2022-08-22  4:59 UTC (permalink / raw)
  To: Simon Glass
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

hi Simon,

On Fri, 19 Aug 2022 at 20:55, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Sughosh,
>
> On Fri, 19 Aug 2022 at 01:41, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > hi Simon,
> >
> > On Thu, 18 Aug 2022 at 23:19, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Sughosh,
> > >
> > > On Thu, 18 Aug 2022 at 05:53, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > >
> > > > hi Simon,
> > > >
> > > > On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> > > > >
> > > > > Hi Sugosh,
> > > > >
> > > > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > > >
> > > > > > Add a command to read the metadata as specified in the FWU
> > > > > > specification and print the fields of the metadata.
> > > > > >
> > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > > > ---
> > > > > > Changes since V7: None
> > > > > >
> > > > > >  cmd/Kconfig     |  7 +++++
> > > > > >  cmd/Makefile    |  1 +
> > > > > >  cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  3 files changed, 88 insertions(+)
> > > > > >  create mode 100644 cmd/fwu_mdata.c
> > > > >
> > > > > This needs docs and a test.
> > > > >
> > > > > BTW I forgot to mention that the uclass needs a simple test of some sort.
> > > > >
> > > > > https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html
> > > >
> > > > Okay. I will check how this can be done. Btw, there are plans to add a
> > > > test for the feature once support for the feature has been added on
> > > > the Synquacer platform. That test will exercise the above command as
> > > > well as the driver code. Do we still need a standalone test for the
> > > > uclass?
> > >
> > > Yes, testing on real hardware has nothing to do with the uclass test, which runs on sandbox. It should be a small unit test like others in test/dm/...
> >
> > I am not talking about testing on real hardware, but a test to be run
> > on sandbox. I had posted the relevant patch [1] in an earlier version
> > of the patch series. But this test relies on support being added for
> > the feature on the Synquacer platform. Once those patches get in, I
> > will be adding the test for the feature as well. And this test
> > exercises both the fwu_mdata_read command as well as the driver code.
> > Which is why I was asking if it is necessary to add additional tests
> > for the command and dm code.
>
> It looks like that 'functional' test should be split into several unit
> tests that check particular things. See how this works with bootstd,
> in test/boot - the Python sets things up and the unit tests cover
> particular areas. The test seems to rely on things happening at
> reboot, so create a command to do those things, to provide for
> testability.

The testing of the feature is being done on similar lines to how the
capsule update feature is being tested -- in fact, the FWU feature
relies on the capsule update for the underlying update functionality.
I think it would be good to have a script to test the feature. If you
want, I can see how I can add a test for the command, although I think
it would be superfluous given that the command will be tested as part
of the feature testing.

-sughosh

>
> So for example 'ut boot fwu_prepare_update' could set up the update
> and 'ut boot fwu_apply_update' could apply it.
>
> Regards,
> Simon
>
>
> >
> > -sughosh
> >
> > [1] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html
> >
> > >
> > > Regards,
> > > Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata
  2022-08-22  4:59             ` Sughosh Ganu
@ 2022-08-22 16:39               ` Simon Glass
  0 siblings, 0 replies; 46+ messages in thread
From: Simon Glass @ 2022-08-22 16:39 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh,

On Sun, 21 Aug 2022 at 22:59, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> hi Simon,
>
> On Fri, 19 Aug 2022 at 20:55, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Fri, 19 Aug 2022 at 01:41, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > >
> > > hi Simon,
> > >
> > > On Thu, 18 Aug 2022 at 23:19, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Sughosh,
> > > >
> > > > On Thu, 18 Aug 2022 at 05:53, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > >
> > > > > hi Simon,
> > > > >
> > > > > On Thu, 18 Aug 2022 at 08:51, Simon Glass <sjg@chromium.org> wrote:
> > > > > >
> > > > > > Hi Sugosh,
> > > > > >
> > > > > > On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> > > > > > >
> > > > > > > Add a command to read the metadata as specified in the FWU
> > > > > > > specification and print the fields of the metadata.
> > > > > > >
> > > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> > > > > > > ---
> > > > > > > Changes since V7: None
> > > > > > >
> > > > > > >  cmd/Kconfig     |  7 +++++
> > > > > > >  cmd/Makefile    |  1 +
> > > > > > >  cmd/fwu_mdata.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > > >  3 files changed, 88 insertions(+)
> > > > > > >  create mode 100644 cmd/fwu_mdata.c
> > > > > >
> > > > > > This needs docs and a test.
> > > > > >
> > > > > > BTW I forgot to mention that the uclass needs a simple test of some sort.
> > > > > >
> > > > > > https://u-boot.readthedocs.io/en/latest/develop/tests_writing.html
> > > > >
> > > > > Okay. I will check how this can be done. Btw, there are plans to add a
> > > > > test for the feature once support for the feature has been added on
> > > > > the Synquacer platform. That test will exercise the above command as
> > > > > well as the driver code. Do we still need a standalone test for the
> > > > > uclass?
> > > >
> > > > Yes, testing on real hardware has nothing to do with the uclass test, which runs on sandbox. It should be a small unit test like others in test/dm/...
> > >
> > > I am not talking about testing on real hardware, but a test to be run
> > > on sandbox. I had posted the relevant patch [1] in an earlier version
> > > of the patch series. But this test relies on support being added for
> > > the feature on the Synquacer platform. Once those patches get in, I
> > > will be adding the test for the feature as well. And this test
> > > exercises both the fwu_mdata_read command as well as the driver code.
> > > Which is why I was asking if it is necessary to add additional tests
> > > for the command and dm code.
> >
> > It looks like that 'functional' test should be split into several unit
> > tests that check particular things. See how this works with bootstd,
> > in test/boot - the Python sets things up and the unit tests cover
> > particular areas. The test seems to rely on things happening at
> > reboot, so create a command to do those things, to provide for
> > testability.
>
> The testing of the feature is being done on similar lines to how the
> capsule update feature is being tested -- in fact, the FWU feature
> relies on the capsule update for the underlying update functionality.
> I think it would be good to have a script to test the feature. If you
> want, I can see how I can add a test for the command, although I think
> it would be superfluous given that the command will be tested as part
> of the feature testing.

The uclass needs a sandbox test. The capsule-update thing seems to
rely on restarting the executable which is not a good thing for
debugging a test in gdb, as you can imagine. Please read through the
testing docs if you haven't already. We need a simple test that checks
that the uclass and sandbox driver does what it should.

Regards,
Simon


>
> -sughosh
>
> >
> > So for example 'ut boot fwu_prepare_update' could set up the update
> > and 'ut boot fwu_apply_update' could apply it.
> >
> > Regards,
> > Simon
> >
> >
> > >
> > > -sughosh
> > >
> > > [1] - https://lists.denx.de/pipermail/u-boot/2022-June/485992.html
> > >
> > > >
> > > > Regards,
> > > > Simon

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature
  2022-08-18  3:21   ` Simon Glass
@ 2022-08-23  8:24     ` Ilias Apalodimas
  0 siblings, 0 replies; 46+ messages in thread
From: Ilias Apalodimas @ 2022-08-23  8:24 UTC (permalink / raw)
  To: Simon Glass
  Cc: Sughosh Ganu, U-Boot Mailing List, Heinrich Schuchardt,
	Takahiro Akashi, Patrick Delaunay, Patrice Chotard, Bin Meng,
	Tom Rini, Etienne Carriere, Michal Simek, Jassi Brar

Hi Sughosh

On Thu, 18 Aug 2022 at 06:21, Simon Glass <sjg@chromium.org> wrote:
>
> On Wed, 17 Aug 2022 at 06:44, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
> >
> > Add documentattion for the FWU Multi Bank Update feature. The document
>
> spelling
>
> > describes the steps needed for setting up the platform for the
> > feature, as well as steps for enabling the feature on the platform.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> > Changes since V7:
> > * Handle the various review comments from Heinrich.
> >
> >  doc/develop/uefi/fwu_updates.rst | 165 +++++++++++++++++++++++++++++++
> >  doc/develop/uefi/index.rst       |   1 +
> >  doc/develop/uefi/uefi.rst        |   2 +
> >  3 files changed, 168 insertions(+)
> >  create mode 100644 doc/develop/uefi/fwu_updates.rst
>
> Reviewed-by: Simon Glass <sjg@chromium.org>

This looks ok now,

Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2022-08-23  8:25 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-17 12:43 [PATCH v8 00/13] FWU: Add FWU Multi Bank Update feature support Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 01/13] dt/bindings: Add bindings for GPT based FWU Metadata storage device Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 02/13] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
2022-08-18  1:13   ` Simon Glass
2022-08-18 11:03     ` Sughosh Ganu
2022-08-18 17:49       ` Simon Glass
2022-08-19 13:36         ` Sughosh Ganu
2022-08-19 15:23           ` Simon Glass
2022-08-19 16:18             ` Sughosh Ganu
2022-08-21  0:11               ` Simon Glass
2022-08-19 14:59         ` Jassi Brar
2022-08-19 15:24           ` Simon Glass
2022-08-19 16:09             ` Jassi Brar
2022-08-17 12:43 ` [PATCH v8 03/13] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
2022-08-18  3:21   ` Simon Glass
2022-08-18 11:38     ` Sughosh Ganu
2022-08-18 17:49       ` Simon Glass
2022-08-19  7:35         ` Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 04/13] stm32mp1: dk2: Add a node for the FWU metadata device Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 05/13] stm32mp1: dk2: Add image information for capsule updates Sughosh Ganu
2022-08-18  8:05   ` Yann Gautier
2022-08-18 12:06     ` Sughosh Ganu
2022-08-18 16:36       ` Yann Gautier
2022-08-17 12:43 ` [PATCH v8 06/13] FWU: Add helper functions for accessing FWU metadata Sughosh Ganu
2022-08-17 17:00   ` Jassi Brar
2022-08-17 17:55     ` Sughosh Ganu
2022-08-18 17:50   ` Simon Glass
2022-08-17 12:43 ` [PATCH v8 07/13] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 08/13] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
2022-08-18  3:21   ` Simon Glass
2022-08-18 11:41     ` Sughosh Ganu
2022-08-18 17:49       ` Simon Glass
2022-08-17 12:43 ` [PATCH v8 09/13] FWU: Add support for the FWU Multi Bank Update feature Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 10/13] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
2022-08-18  3:21   ` Simon Glass
2022-08-18 11:53     ` Sughosh Ganu
2022-08-18 17:49       ` Simon Glass
2022-08-19  7:41         ` Sughosh Ganu
2022-08-19 15:24           ` Simon Glass
2022-08-22  4:59             ` Sughosh Ganu
2022-08-22 16:39               ` Simon Glass
2022-08-17 12:43 ` [PATCH v8 11/13] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 12/13] mkeficapsule: Add support for setting OEM flags in capsule header Sughosh Ganu
2022-08-17 12:43 ` [PATCH v8 13/13] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
2022-08-18  3:21   ` Simon Glass
2022-08-23  8:24     ` Ilias Apalodimas

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.