All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature
@ 2022-02-07 18:19 Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
                   ` (11 more replies)
  0 siblings, 12 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere



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
board which boots a FIP image from a uSD card partitioned with the GPT
partioning scheme. This also requires changes in the previous stage of
bootloader, which parses the metadata and selects the bank to boot the
image(s) from. Support is 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's integration branch[3].

These patches are based on top of the series from Takahiro to add
Authentication support to mkeficapsule utility[4] and a couple of
other patches[5][6]

TODO's
------
* Add a unit test case for the newly added FWU_MDATA uclass. Some
  involved effort is needed on this since the host device interface on
  sandbox cannot be used with the UT framework.
* Add test case for the feature with the python test suite, along the
  lines of capsule update testing.

[1] - https://developer.arm.com/documentation/den0118/a
[2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
[3] - https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/log/?h=integration
[4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
[5] - https://patchwork.ozlabs.org/project/uboot/patch/164388019634.446835.18271480521485569016.stgit@localhost/
[6] - https://patchwork.ozlabs.org/project/uboot/patch/20220129192108.6618-1-sughosh.ganu@linaro.org/


Changes since V3:
* Move the FWU metadata access to driver model
* Get the storage device containing the metadata from a device tree
  property instead of a platform helper function
* Move the metadata access driver for GPT partitioned block devices
  under drivers/fwu-mdata/ directory, complying with driver model.
* Move functionality to get the active index under the common function
  instead of the GPT block device specific driver.
* Remove function for getting the storage device containing the
  metadata as the information is now obtained from the device tree.
* Define a weak function fill_image_type_guid_array for populating the
  image descriptor array with u-boot's raw and fit image GUIDs
* Define the function fill_image_type_guid_array for the ST DK2 board
  for GPT partitioned devices.
* Change the TrialStateCtr efi variable attribute to remove the
  runtime attribute
* Rebase the change on top of the patch from Masami to call
  efi_capsule_update_firmware directly.
* Put the FWU related checks which were earlier in efi_update_capsule
  function to separate functions fwu_empty_capsule and
  fwu_empty_capsule_process.
* Use the device model api uclass_get_device to probe and get the FWU
  Metadata device.
* Add related documentation for empty capsules in the mkeficapsule man
  page.
* Add separate usage for empty capsules, with corresponding valid
  options.
* Use ternary operators where possible.
* Put a exclusivity check for the empty capsule options.


Sughosh Ganu (11):
  FWU: Add FWU metadata structure and driver for accessing metadata
  FWU: Add FWU metadata access driver for GPT partitioned block devices
  FWU: stm32mp1: Add helper functions for accessing FWU metadata
  FWU: STM32MP1: Add support to read boot index from backup register
  EFI: FMP: Add provision to update image's ImageTypeId in image
    descriptor
  stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR
    array
  FWU: Add boot time checks as highlighted by the FWU specification
  FWU: Add support for FWU Multi Bank Update feature
  FWU: cmd: Add a command to read FWU metadata
  mkeficapsule: Add support for generating empty capsules
  FWU: doc: Add documentation for the FWU feature

 arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
 board/st/stm32mp1/stm32mp1.c                  | 178 +++++++
 cmd/Kconfig                                   |   7 +
 cmd/Makefile                                  |   1 +
 cmd/fwu_mdata.c                               |  74 +++
 common/board_r.c                              |   6 +
 doc/develop/uefi/fwu_updates.rst              | 142 +++++
 doc/develop/uefi/index.rst                    |   1 +
 doc/develop/uefi/uefi.rst                     |   2 +
 .../firmware/fwu-mdata.txt                    |  18 +
 doc/mkeficapsule.1                            |  23 +-
 drivers/Kconfig                               |   2 +
 drivers/Makefile                              |   1 +
 drivers/fwu-mdata/Kconfig                     |  16 +
 drivers/fwu-mdata/Makefile                    |   7 +
 drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 +++++++++++++++
 drivers/fwu-mdata/fwu_mdata_gpt_blk.c         | 501 ++++++++++++++++++
 include/dm/uclass-id.h                        |   1 +
 include/efi_loader.h                          |   2 +
 include/fwu.h                                 |  70 +++
 include/fwu_mdata.h                           |  67 +++
 lib/Kconfig                                   |   6 +
 lib/Makefile                                  |   1 +
 lib/efi_loader/efi_capsule.c                  | 221 +++++++-
 lib/efi_loader/efi_firmware.c                 |  71 ++-
 lib/efi_loader/efi_setup.c                    |   3 +-
 lib/fwu_updates/Kconfig                       |  31 ++
 lib/fwu_updates/Makefile                      |   6 +
 lib/fwu_updates/fwu.c                         | 204 +++++++
 tools/eficapsule.h                            |   8 +
 tools/mkeficapsule.c                          | 131 ++++-
 31 files changed, 2208 insertions(+), 34 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.txt
 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

-- 
2.17.1



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

* [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-08  9:33   ` Masami Hiramatsu
                     ` (2 more replies)
  2022-02-07 18:19 ` [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
                   ` (10 subsequent siblings)
  11 siblings, 3 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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.

A device tree node fwu-mdata has been added, which is used for
pointing to the storage device which contains the FWU metadata. The
fwu-mdata node is u-boot specific, and can be added the platform's
u-boot dtsi file.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---

Changes since V3:
* Move the FWU metadata access to driver model
* Get the storage device containing the metadata from a device tree
  property instead of a platform helper function

 arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
 .../firmware/fwu-mdata.txt                    |  18 +
 drivers/Kconfig                               |   2 +
 drivers/Makefile                              |   1 +
 drivers/fwu-mdata/Kconfig                     |   7 +
 drivers/fwu-mdata/Makefile                    |   6 +
 drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
 include/dm/uclass-id.h                        |   1 +
 include/fwu.h                                 |  51 ++
 include/fwu_mdata.h                           |  67 +++
 10 files changed, 594 insertions(+)
 create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
 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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
index 06ef3a4095..3bec6107f7 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";
+		fwu-mdata-store = <&sdmmc1>;
+	};
+};
diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
new file mode 100644
index 0000000000..c766b595ef
--- /dev/null
+++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
@@ -0,0 +1,18 @@
+FWU Metadata Access Devicetree Binding
+
+The FWU Multi Bank Update feature uses a metadata structure, stored on
+a separate partition for keeping information on the set of updatable
+images. The device tree node provides information on the storage
+device that contains the FWU metadata.
+
+Required properties :
+
+- compatible : "u-boot,fwu-mdata";
+- fwu-mdata-store : should point to the storage device which contains
+		    the FWU metadata partition.
+
+Example :
+	fwu-mdata {
+		compatible = "u-boot,fwu-mdata";
+		fwu-mdata-store = <&sdmmc1>;
+	};
diff --git a/drivers/Kconfig b/drivers/Kconfig
index b26ca8cf70..adc6079ecf 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -81,6 +81,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..7fec7171f4
--- /dev/null
+++ b/drivers/fwu-mdata/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# 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..64b3051ecf
--- /dev/null
+++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
@@ -0,0 +1,434 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#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;
+	void *buf;
+	struct fwu_mdata *mdata = NULL;
+
+	if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
+		log_err("Active index value to be updated is incorrect\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;
+
+	/*
+	 * 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));
+
+	/*
+	 * 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: 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;
+	const struct fwu_mdata_ops *ops = NULL;
+	struct udevice *dev = NULL;
+
+	ret = fwu_get_dev_ops(&dev, &ops);
+	if (ret)
+		return ret;
+
+	if (!ops->get_image_alt_num) {
+		log_err("get_image_alt_num() method not defined\n");
+		return -ENOSYS;
+	}
+
+	return ops->get_image_alt_num(dev, image_type_id,
+				      update_bank, alt_num);
+}
+
+/**
+ * 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;
+	void *buf;
+	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;
+
+	/*
+	 * 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));
+
+	/*
+	 * 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)
+{
+	void *buf;
+	int ret, i;
+	u32 nimages;
+	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;
+	}
+
+	nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
+	img_entry = &mdata->img_entry[0];
+	for (i = 0; i < nimages; 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;
+
+			buf = &mdata->version;
+			mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
+					     sizeof(u32));
+
+			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.
+ *
+ * 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.
+ *
+ * Return: 0 if OK, -ve on error
+ *
+ */
+int fwu_update_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->update_mdata) {
+		log_err("get_mdata() method not defined\n");
+		return -ENOSYS;
+	}
+
+	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 0e26e1d138..d0ab1c9235 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -54,6 +54,7 @@ enum uclass_id {
 	UCLASS_ETH_PHY,		/* Ethernet PHY device */
 	UCLASS_FIRMWARE,	/* Firmware */
 	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..5a99c579fc
--- /dev/null
+++ b/include/fwu.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 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;
+
+/**
+ * @get_image_alt_num: get the alt number to be used for the image
+ * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
+				 u32 update_bank, int *alt_num);
+
+	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);
+
+#endif /* _FWU_H_ */
diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
new file mode 100644
index 0000000000..701efbba03
--- /dev/null
+++ b/include/fwu_mdata.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 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.17.1


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

* [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-09  4:56   ` Masami Hiramatsu
  2022-02-07 18:19 ` [PATCH v4 03/11] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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>
---

Changes since V3:
* Move the metadata access driver for GPT partitioned block devices
  under drivers/fwu-mdata/ directory, complying with driver model.
* Move functionality to get the active index under the common function
  instead of the GPT block device specific driver.

 drivers/fwu-mdata/Kconfig             |   9 +
 drivers/fwu-mdata/Makefile            |   1 +
 drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 501 ++++++++++++++++++++++++++
 include/fwu.h                         |   2 +
 4 files changed, 513 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 7fec7171f4..12a5b4fe04 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..b3e0fcafb2
--- /dev/null
+++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
@@ -0,0 +1,501 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#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;
+
+	desc = dev_get_uclass_plat(dev_get_priv(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;
+
+	desc = dev_get_uclass_plat(dev_get_priv(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 gpt_get_image_alt_num(struct udevice *dev, struct blk_desc *desc,
+				 efi_guid_t image_type_id, u32 update_bank,
+				 int *alt_no)
+{
+	int ret, i;
+	u32 part;
+	struct fwu_mdata *mdata = NULL;
+	struct fwu_image_entry *img_entry;
+	struct fwu_image_bank_info *img_bank_info;
+	struct disk_partition info;
+	efi_guid_t unique_part_guid;
+	efi_guid_t image_guid = NULL_GUID;
+
+	ret = gpt_get_mdata(desc, &mdata);
+	if (ret < 0) {
+		log_err("Unable to read valid FWU metadata\n");
+		goto out;
+	}
+
+	/*
+	 * 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];
+			guidcpy(&image_guid, &img_bank_info->image_uuid);
+			break;
+		}
+	}
+
+	/*
+	 * Now read the GPT Partition Table Entries to find a matching
+	 * partition with UniquePartitionGuid value. We need to iterate
+	 * through all the GPT partitions since they might be in any
+	 * order
+	 */
+	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)) {
+			/* Found the partition */
+			part = i;
+			*alt_no = fwu_plat_get_alt_num(dev_get_priv(dev), &part);
+			if (*alt_no != -1)
+				log_info("alt_num %d for partition %pUl\n",
+					  *alt_no, &image_guid);
+			ret = 0;
+			break;
+		}
+	}
+
+	if (*alt_no == -1) {
+		log_err("alt_num not found for partition with GUID %pUl\n",
+			&image_guid);
+		ret = -EINVAL;
+	}
+
+	if (i == MAX_SEARCH_PARTITIONS) {
+		log_err("Partition with the image guid not found\n");
+		ret = -EINVAL;
+	}
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+int fwu_gpt_get_image_alt_num(struct udevice *dev, efi_guid_t image_type_id,
+			      u32 update_bank, int *alt_no)
+{
+	struct blk_desc *desc;
+
+	desc = dev_get_uclass_plat(dev_get_priv(dev));
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return gpt_get_image_alt_num(dev, desc, image_type_id, update_bank,
+				     alt_no);
+}
+
+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);
+}
+
+int fwu_gpt_get_mdata(struct udevice *dev, struct fwu_mdata **mdata)
+{
+	struct blk_desc *desc;
+
+	desc = dev_get_uclass_plat(dev_get_priv(dev));
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return gpt_get_mdata(desc, mdata);
+}
+
+int fwu_get_mdata_device(struct udevice **mdata_dev)
+{
+	u32 phandle;
+	int ret, size;
+	struct udevice *dev, *child;
+	ofnode fwu_mdata_node;
+	const fdt32_t *phandle_p = NULL;
+
+	fwu_mdata_node = ofnode_path("/fwu-mdata");
+	if (!ofnode_valid(fwu_mdata_node)) {
+		log_err("fwu-node not found\n");
+		return -ENOENT;
+	}
+
+	phandle_p = ofnode_get_property(fwu_mdata_node, "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),
+					  &dev);
+	if (ret)
+		return ret;
+
+	ret = -ENODEV;
+	for (device_find_first_child(dev, &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;
+
+	ret = fwu_get_mdata_device(&mdata_dev);
+	if (ret)
+		return ret;
+
+	dev_set_priv(dev, mdata_dev);
+
+	return 0;
+}
+
+static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
+	.get_image_alt_num = fwu_gpt_get_image_alt_num,
+	.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" },
+	{ }
+};
+
+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,
+};
diff --git a/include/fwu.h b/include/fwu.h
index 5a99c579fc..2c7db2dff9 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
+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.17.1


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

* [PATCH v4 03/11] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 04/11] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Sughosh Ganu

Add helper functions needed for accessing the FWU metadata which
contains information on the updatable images. These functions have
been added for the STM32MP157C-DK2 board which has the updatable
images on the uSD card, formatted as GPT partitions.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---

Changes since V3:
* Remove function for getting the storage device containing the
  metadata as the information is now obtained from the device tree.

 board/st/stm32mp1/stm32mp1.c | 78 ++++++++++++++++++++++++++++++++++++
 include/fwu.h                |  3 ++
 2 files changed, 81 insertions(+)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 84592677e4..5e8cb29067 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -7,10 +7,13 @@
 
 #include <common.h>
 #include <adc.h>
+#include <blk.h>
 #include <bootm.h>
 #include <clk.h>
 #include <config.h>
+#include <dfu.h>
 #include <dm.h>
+#include <efi_loader.h>
 #include <env.h>
 #include <env_internal.h>
 #include <fdt_support.h>
@@ -23,9 +26,11 @@
 #include <log.h>
 #include <malloc.h>
 #include <misc.h>
+#include <mmc.h>
 #include <mtd_node.h>
 #include <net.h>
 #include <netdev.h>
+#include <part.h>
 #include <phy.h>
 #include <remoteproc.h>
 #include <reset.h>
@@ -938,3 +943,76 @@ 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>
+#include <fwu_mdata.h>
+
+static int gpt_plat_get_alt_num(int dev_num, void *identifier)
+{
+	int i;
+	int ret = -1;
+	u32 part;
+	int alt_num = dfu_get_alt_number();
+	struct dfu_entity *dfu;
+
+	part = *(u32 *)identifier;
+	dfu_init_env_entities(NULL, NULL);
+
+	for (i = 0; i < alt_num; 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_MMC)
+			continue;
+
+		if (dfu->layout == DFU_RAW_ADDR &&
+		    dfu->data.mmc.dev_num == dev_num &&
+		    dfu->data.mmc.part == part) {
+			ret = dfu->alt;
+			break;
+		}
+	}
+
+	dfu_free_entities();
+
+	return ret;
+}
+
+int fwu_plat_get_alt_num(struct udevice *dev, void *identifier)
+{
+	struct blk_desc *desc;
+
+	desc = dev_get_uclass_plat(dev);
+	if (!desc) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return gpt_plat_get_alt_num(desc->devnum, identifier);
+}
+
+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;
+}
+
+#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
diff --git a/include/fwu.h b/include/fwu.h
index 2c7db2dff9..b746e616b2 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -50,4 +50,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);
 
+int fwu_plat_get_update_index(u32 *update_idx);
+int fwu_plat_get_alt_num(struct udevice *dev, void *identifier);
+
 #endif /* _FWU_H_ */
-- 
2.17.1


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

* [PATCH v4 04/11] FWU: STM32MP1: Add support to read boot index from backup register
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (2 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 03/11] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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>
---

Changes since V3: None

 board/st/stm32mp1/stm32mp1.c | 6 ++++++
 include/fwu.h                | 1 +
 2 files changed, 7 insertions(+)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 5e8cb29067..5525b69392 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -1015,4 +1015,10 @@ int fwu_plat_get_update_index(u32 *update_idx)
 	return ret;
 }
 
+void fwu_plat_get_bootidx(void *boot_idx)
+{
+	u32 *bootidx = boot_idx;
+
+	*bootidx = readl(TAMP_BOOTCOUNT);
+}
 #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
diff --git a/include/fwu.h b/include/fwu.h
index b746e616b2..90b8cd41e5 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -52,5 +52,6 @@ int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank);
 
 int fwu_plat_get_update_index(u32 *update_idx);
 int fwu_plat_get_alt_num(struct udevice *dev, void *identifier);
+void fwu_plat_get_bootidx(void *boot_idx);
 
 #endif /* _FWU_H_ */
-- 
2.17.1


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

* [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (3 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 04/11] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-10  2:48   ` AKASHI Takahiro
  2022-02-07 18:19 ` [PATCH v4 06/11] stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR array Sughosh Ganu
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Sughosh Ganu

The FWU Multi Banks Update feature allows updating different types of
updatable firmware images on the platform. These image types are
identified using the ImageTypeId GUID value. Add support in the
GetImageInfo function of the FMP protocol to get the GUID values for
the individual images and populate these in the image descriptor for
the corresponding images.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---

Changes since V3:
* Define a weak function fill_image_type_guid_array for populating the
  image descriptor array with u-boot's raw and fit image GUIDs

 include/efi_loader.h          |  2 +
 lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
 2 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index f4860e87fc..ae60de0be5 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
 efi_status_t efi_load_capsule_drivers(void);
 
 efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
+efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
+					efi_guid_t **part_guid_arr);
 #endif /* _EFI_LOADER_H */
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index a1b88dbfc2..5642be9f9a 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
+efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
+					       efi_guid_t **part_guid_arr)
+{
+	int i;
+	int dfu_num = 0;
+	efi_guid_t *guid_arr;
+	struct dfu_entity *dfu;
+	efi_status_t ret = EFI_SUCCESS;
+
+	dfu_init_env_entities(NULL, NULL);
+
+	dfu_num = 0;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		dfu_num++;
+	}
+
+	if (!dfu_num) {
+		log_warning("Probably dfu_alt_info not defined\n");
+		ret = EFI_NOT_READY;
+		goto out;
+	}
+
+	*part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
+	if (!*part_guid_arr) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	guid_arr = *part_guid_arr;
+	for (i = 0; i < dfu_num; i++) {
+		guidcpy(guid_arr, guid);
+		++guid_arr;
+	}
+
+out:
+	dfu_free_entities();
+
+	return ret;
+}
+
 /**
  * efi_get_dfu_info - return information about the current firmware image
  * @this:			Protocol instance
@@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
  * @descriptor_version:		Pointer to version number
  * @descriptor_count:		Pointer to number of descriptors
  * @descriptor_size:		Pointer to descriptor size
- * package_version:		Package version
- * package_version_name:	Package version's name
- * image_type:			Image type GUID
+ * @package_version:		Package version
+ * @package_version_name:	Package version's name
+ * @guid_array:			Image type GUID array
  *
  * Return information bout the current firmware image in @image_info.
  * @image_info will consist of a number of descriptors.
@@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
 	efi_uintn_t *descriptor_size,
 	u32 *package_version,
 	u16 **package_version_name,
-	const efi_guid_t *image_type)
+	const efi_guid_t *guid_array)
 {
 	struct dfu_entity *dfu;
 	size_t names_len, total_size;
@@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
 	next = name;
 	list_for_each_entry(dfu, &dfu_list, list) {
 		image_info[i].image_index = dfu->alt + 1;
-		image_info[i].image_type_id = *image_type;
+		image_info[i].image_type_id = guid_array[i];
 		image_info[i].image_id = dfu->alt;
 
 		/* copy the DFU entity name */
@@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
 	u16 **package_version_name)
 {
 	efi_status_t ret;
+	efi_guid_t *part_guid_arr = NULL;
 
 	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
 		  image_info_size, image_info,
@@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
 	     !descriptor_size || !package_version || !package_version_name))
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+	ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
+					 &part_guid_arr);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	ret = efi_get_dfu_info(image_info_size, image_info,
 			       descriptor_version, descriptor_count,
 			       descriptor_size,
 			       package_version, package_version_name,
-			       &efi_firmware_image_type_uboot_fit);
+			       part_guid_arr);
 
+out:
+	free(part_guid_arr);
 	return EFI_EXIT(ret);
 }
 
@@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	u16 **package_version_name)
 {
 	efi_status_t ret = EFI_SUCCESS;
+	efi_guid_t *part_guid_arr = NULL;
 
 	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
 		  image_info_size, image_info,
@@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	     !descriptor_size || !package_version || !package_version_name))
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+	ret = fill_image_type_guid_array(
+		&efi_firmware_image_type_uboot_raw,
+		&part_guid_arr);
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	ret = efi_get_dfu_info(image_info_size, image_info,
 			       descriptor_version, descriptor_count,
 			       descriptor_size,
 			       package_version, package_version_name,
-			       &efi_firmware_image_type_uboot_raw);
+			       part_guid_arr);
 
+out:
+	free(part_guid_arr);
 	return EFI_EXIT(ret);
 }
 
-- 
2.17.1


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

* [PATCH v4 06/11] stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR array
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (4 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Sughosh Ganu

The EFI_FIRMWARE_IMAGE_DESCRIPTOR array is returned by the Firmware
Management Protocol's(FMP) GetImageInfo function. The image descriptor
array contains the ImageTypeId which is a GUID identifying the
firmware images that are supported by the instance of the FMP. These
ImageTypeId values are compared against the value in the capsule to
identify the FMP instance to be used for the capsule.

Add a function for the GPT partitioned device based ST platforms for
filling up the image descriptor array with the ImageTypeId values. For
the GPT partitioned devices, the array can be populated by reading the
GPT header which contains the Partition Entry Array, where each entry
contains the PartitionTypeGUID for the corresponding image.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---

Changes since V3:
* Define the function fill_image_type_guid_array for the ST DK2 board
  for GPT partitioned devices.

 board/st/stm32mp1/stm32mp1.c | 94 ++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 5525b69392..fc14c9808b 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -1021,4 +1021,98 @@ void fwu_plat_get_bootidx(void *boot_idx)
 
 	*bootidx = readl(TAMP_BOOTCOUNT);
 }
+
+static int fill_gpt_partition_guids(struct blk_desc *desc,
+				    efi_guid_t **part_guid_arr)
+{
+	int i;
+	u32 part;
+	int alt_num;
+	struct dfu_entity *dfu;
+	struct disk_partition info;
+	efi_guid_t part_type_guid;
+	efi_guid_t null_guid = NULL_GUID;
+	efi_status_t ret = EFI_SUCCESS;
+
+	dfu_init_env_entities(NULL, NULL);
+
+	alt_num = 0;
+	list_for_each_entry(dfu, &dfu_list, list) {
+		++alt_num;
+	}
+
+	if (!alt_num) {
+		log_warning("Probably dfu_alt_info not defined\n");
+		ret = EFI_NOT_READY;
+		goto out;
+	}
+
+	*part_guid_arr = malloc(sizeof(efi_guid_t) * alt_num);
+	if (!*part_guid_arr) {
+		ret = EFI_OUT_OF_RESOURCES;
+		goto out;
+	}
+
+	for (i = 0; i < alt_num; i++)
+		guidcpy((*part_guid_arr + i), &null_guid);
+
+	for (i = 0, part = 1; i < alt_num; 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_MMC)
+			continue;
+
+		if (part_get_info(desc, part, &info)) {
+			part++;
+			continue;
+		}
+
+		uuid_str_to_bin(info.type_guid, part_type_guid.b,
+				UUID_STR_FORMAT_GUID);
+		guidcpy((*part_guid_arr + i), &part_type_guid);
+		part++;
+	}
+
+out:
+	dfu_free_entities();
+
+	return ret;
+}
+
+efi_status_t fill_image_type_guid_array(const efi_guid_t __always_unused
+					*default_guid,
+					efi_guid_t **part_guid_arr)
+{
+	int ret;
+	struct udevice *dev;
+	struct blk_desc *desc;
+
+	/*
+	 * Get the storage device on which the
+	 * FWU metadata has been stored
+	 */
+	ret = fwu_get_mdata_device(&dev);
+	if (ret) {
+		log_err("Unable to get FWU metadata device\n");
+		return EFI_DEVICE_ERROR;
+	}
+
+	desc = dev_get_uclass_plat(dev);
+	if (!desc) {
+		log_err("Block device not found\n");
+		return EFI_DEVICE_ERROR;
+	}
+
+	return fill_gpt_partition_guids(desc, part_guid_arr);
+}
+
 #endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
-- 
2.17.1


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

* [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (5 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 06/11] stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR array Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-08 10:53   ` Michal Simek
  2022-02-07 18:19 ` [PATCH v4 08/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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 V3:
* Change the TrialStateCtr efi variable attribute to remove the
  runtime attribute

 common/board_r.c      |   6 ++
 include/fwu.h         |   3 +
 lib/fwu_updates/fwu.c | 178 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+)
 create mode 100644 lib/fwu_updates/fwu.c

diff --git a/common/board_r.c b/common/board_r.c
index 31a59c585a..81678870b9 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -78,6 +78,9 @@
 #ifdef CONFIG_EFI_SETUP_EARLY
 #include <efi_loader.h>
 #endif
+#ifdef CONFIG_FWU_MULTI_BANK_UPDATE
+#include <fwu.h>
+#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -805,6 +808,9 @@ static init_fnc_t init_sequence_r[] = {
 #endif
 #ifdef CONFIG_EFI_SETUP_EARLY
 	(init_fnc_t)efi_init_obj_list,
+#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 90b8cd41e5..5a329d9ef7 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)
 
+int fwu_boottime_checks(void);
+u8 fwu_update_checks_pass(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
new file mode 100644
index 0000000000..86933123e7
--- /dev/null
+++ b/lib/fwu_updates/fwu.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, 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 = 0;
+static u8 boottime_check = 0;
+
+static int fwu_trial_state_check(void)
+{
+	int ret, i;
+	efi_status_t status;
+	efi_uintn_t var_size;
+	u16 trial_state_ctr;
+	u32 nimages, active_bank, var_attributes, active_idx;
+	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)
+		return ret;
+
+	ret = 0;
+	nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
+	active_bank = mdata->active_index;
+	img_entry = &mdata->img_entry[0];
+	for (i = 0; i < nimages; i++) {
+		img_bank_info = &img_entry[i].img_bank_info[active_bank];
+		if (!img_bank_info->accepted) {
+			trial_state = 1;
+			break;
+		}
+	}
+
+	if (trial_state) {
+		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(L"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 < 0) {
+				log_err("Unable to revert active_index\n");
+				goto out;
+			}
+
+			trial_state_ctr = 0;
+			status = efi_set_variable_int(L"TrialStateCtr",
+						      &efi_global_variable_guid,
+						      var_attributes,
+						      0,
+						      &trial_state_ctr, false);
+			if (status != EFI_SUCCESS) {
+				log_err("Unable to clear TrialStateCtr variable\n");
+				ret = -1;
+				goto out;
+			}
+		} else {
+			status = efi_set_variable_int(L"TrialStateCtr",
+						      &efi_global_variable_guid,
+						      var_attributes,
+						      var_size,
+						      &trial_state_ctr, false);
+			if (status != EFI_SUCCESS) {
+				log_err("Unable to increment TrialStateCtr variable\n");
+				ret = -1;
+				goto out;
+			} else {
+				ret = 0;
+			}
+		}
+	} else {
+		trial_state_ctr = 0;
+		ret = 0;
+		status = efi_set_variable_int(L"TrialStateCtr",
+					      &efi_global_variable_guid,
+					      0,
+					      0, &trial_state_ctr,
+					      NULL);
+	}
+
+out:
+	free(mdata);
+	return ret;
+}
+
+u8 fwu_update_checks_pass(void)
+{
+	return !trial_state && boottime_check;
+}
+
+int fwu_boottime_checks(void)
+{
+	int ret;
+	struct udevice *dev;
+	u32 boot_idx, active_idx;
+
+	if (uclass_get_device(UCLASS_FWU_MDATA, 0, &dev) || !dev) {
+		log_err("FWU Metadata device not found\n");
+		boottime_check = 0;
+		return 0;
+	}
+
+	ret = fwu_mdata_check();
+	if (ret < 0) {
+		boottime_check = 0;
+		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");
+		boottime_check = 0;
+		return 0;
+	}
+
+	ret = fwu_get_active_index(&active_idx);
+	if (ret < 0) {
+		log_err("Unable to read active_index\n");
+		boottime_check = 0;
+		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 < 0)
+			boottime_check = 0;
+		else
+			boottime_check = 1;
+
+		return 0;
+	}
+
+	ret = fwu_trial_state_check();
+	if (ret < 0)
+		boottime_check = 0;
+	else
+		boottime_check = 1;
+
+	return 0;
+}
-- 
2.17.1


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

* [PATCH v4 08/11] FWU: Add support for FWU Multi Bank Update feature
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (6 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-07 18:19 ` [PATCH v4 09/11] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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 V3:
* Rebase the change on top of the patch from Masami to call
  efi_capsule_update_firmware directly.
* Put the FWU related checks which were earlier in efi_update_capsule
  function to separate functions fwu_empty_capsule and
  fwu_empty_capsule_process.

 include/fwu.h                |  12 +-
 lib/Kconfig                  |   6 +
 lib/Makefile                 |   1 +
 lib/efi_loader/efi_capsule.c | 221 ++++++++++++++++++++++++++++++++++-
 lib/efi_loader/efi_setup.c   |   3 +-
 lib/fwu_updates/Kconfig      |  31 +++++
 lib/fwu_updates/Makefile     |   6 +
 lib/fwu_updates/fwu.c        |  26 +++++
 8 files changed, 301 insertions(+), 5 deletions(-)
 create mode 100644 lib/fwu_updates/Kconfig
 create mode 100644 lib/fwu_updates/Makefile

diff --git a/include/fwu.h b/include/fwu.h
index 5a329d9ef7..88dc4a4b9a 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)
 
-int fwu_boottime_checks(void);
+#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 807a4c6ade..d8ff672354 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -835,3 +835,9 @@ config PHANDLE_CHECK_SEQ
 	  When there are multiple device tree nodes with same name,
           enable this config option to distinguish them using
 	  phandles in fdtdec_get_alias_seq() function.
+
+menu "FWU Multi Bank Updates"
+
+source lib/fwu_updates/Kconfig
+
+endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 5ddbc77ed6..bc5c1e22fc 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_TIZEN) += tizen/
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 708668a5de..7292439106 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 <malloc.h>
 #include <mapmem.h>
 #include <sort.h>
@@ -30,6 +31,16 @@ 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;
 
 #ifdef CONFIG_EFI_CAPSULE_ON_DISK
 /* for file system access */
@@ -384,6 +395,88 @@ 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_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();
+		if (status < 0) {
+			log_err("Failed to revert the FWU boot index\n");
+			if (status == -ENODEV ||
+			    status == -ERANGE ||
+			    status == -EIO)
+				ret = EFI_DEVICE_ERROR;
+			else if (status == -EINVAL)
+				ret = EFI_INVALID_PARAMETER;
+			else if (status == -ENOMEM)
+				ret = EFI_OUT_OF_RESOURCES;
+		} else {
+			ret = EFI_SUCCESS;
+			log_err("Reverted the FWU active_index. Recommend rebooting the system\n");
+		}
+	} else if (!guidcmp(&capsule->capsule_guid,
+			    &fwu_guid_os_request_fw_accept)) {
+		/*
+		 * 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);
+		if (status < 0) {
+			log_err("Unable to get the active_index from the FWU metadata\n");
+			if (status == -ENODEV ||
+			    status == -ERANGE ||
+			    status == -EIO)
+				ret = EFI_DEVICE_ERROR;
+			else if (status == -EINVAL)
+				ret = EFI_INVALID_PARAMETER;
+			else if (status == -ENOMEM)
+				ret = EFI_OUT_OF_RESOURCES;
+
+			return ret;
+		}
+
+		status = fwu_accept_image(image_guid, active_idx);
+		if (status < 0) {
+			log_err("Unable to set the Accept bit for the image %pUl\n",
+				image_guid);
+			if (status == -ENODEV ||
+			    status == -ERANGE ||
+			    status == -EIO)
+				ret = EFI_DEVICE_ERROR;
+			else if (status == -EINVAL)
+				ret = EFI_INVALID_PARAMETER;
+			else if (status == -ENOMEM)
+				ret = EFI_OUT_OF_RESOURCES;
+		} else {
+			ret = EFI_SUCCESS;
+		}
+	}
+
+	return ret;
+}
 
 /**
  * efi_capsule_update_firmware - update firmware from capsule
@@ -403,10 +496,37 @@ 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;
+		}
+
+		/* 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;
+		}
+
+		if (fwu_empty_capsule(capsule_data)) {
+			capsule_update = false;
+			return fwu_empty_capsule_process(capsule_data);
+		} else {
+			capsule_update = true;
+		}
+
+		fw_accept_os = capsule_data->flags & FW_ACCEPT_OS ? 0x1 : 0x0;
+	}
 
 	/* sanity check */
 	if (capsule_data->header_size < sizeof(*capsule) ||
@@ -481,8 +601,36 @@ 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);
+			if (status < 0) {
+				log_err("Unable to get the alt no for the image type %pUl\n",
+					&image_type_id);
+				if (status == -ENODEV || status == -EIO)
+					ret = EFI_DEVICE_ERROR;
+				else if (status == -ENOMEM)
+					ret = EFI_OUT_OF_RESOURCES;
+				else if (status == -ERANGE || status == -EINVAL)
+					ret = EFI_INVALID_PARAMETER;
+				goto out;
+			}
+			log_debug("alt_no %u for Image Type Id %pUl\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,
@@ -493,6 +641,38 @@ 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);
+			}
+
+			if (status < 0) {
+				log_err("Unable to %s the accept bit for the image %pUl\n",
+					fw_accept_os ? "clear" : "set",
+					&image_type_id);
+				if (status == -ENODEV || status == -EIO)
+					ret = EFI_DEVICE_ERROR;
+				else if (status == -ENOMEM)
+					ret = EFI_OUT_OF_RESOURCES;
+				else if (status == -ERANGE || status == -EINVAL)
+					ret = EFI_INVALID_PARAMETER;
+				goto out;
+			}
+			log_debug("%s the accepted bit for Image %pUl\n",
+				  fw_accept_os ? "Cleared" : "Set",
+				  &image_type_id);
+		}
+
 	}
 
 out:
@@ -1090,8 +1270,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;
@@ -1119,9 +1301,11 @@ 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]);
+				update_status = false;
+			}
 
 			/* create CapsuleXXXX */
 			set_capsule_result(index, capsule, ret);
@@ -1129,6 +1313,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]);
@@ -1136,7 +1321,37 @@ 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);
+			if (status < 0) {
+				log_err("Failed to update FWU metadata index values\n");
+				if (status == -EINVAL || status == -ERANGE)
+					ret = EFI_INVALID_PARAMETER;
+				else if (status == -ENODEV || status == -EIO)
+					ret = EFI_DEVICE_ERROR;
+				else if (status == -ENOMEM)
+					ret = EFI_OUT_OF_RESOURCES;
+			} else {
+				log_debug("Successfully updated the active_index\n");
+				status = fwu_trial_state_ctr_start();
+				if (status < 0)
+					ret = EFI_DEVICE_ERROR;
+				else
+					ret = EFI_SUCCESS;
+			}
+		} 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 49172e3579..df41510340 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -302,7 +302,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/Makefile b/lib/fwu_updates/Makefile
new file mode 100644
index 0000000000..1b17051f32
--- /dev/null
+++ b/lib/fwu_updates/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2021, Linaro Limited
+#
+
+obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 86933123e7..ca3cf6b560 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -115,6 +115,32 @@ u8 fwu_update_checks_pass(void)
 	return !trial_state && boottime_check;
 }
 
+int fwu_trial_state_ctr_start(void)
+{
+	int ret;
+	u32 var_attributes;
+	efi_status_t status;
+	efi_uintn_t var_size;
+	u16 trial_state_ctr;
+
+	var_size = (efi_uintn_t)sizeof(trial_state_ctr);
+	var_attributes = EFI_VARIABLE_NON_VOLATILE |
+		EFI_VARIABLE_BOOTSERVICE_ACCESS;
+
+	trial_state_ctr = ret = 0;
+	status = efi_set_variable_int(L"TrialStateCtr",
+				      &efi_global_variable_guid,
+				      var_attributes,
+				      var_size,
+				      &trial_state_ctr, false);
+	if (status != EFI_SUCCESS) {
+		log_err("Unable to increment TrialStateCtr variable\n");
+		ret = -1;
+	}
+
+	return ret;
+}
+
 int fwu_boottime_checks(void)
 {
 	int ret;
-- 
2.17.1


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

* [PATCH v4 09/11] FWU: cmd: Add a command to read FWU metadata
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (7 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 08/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2022-02-07 18:19 ` Sughosh Ganu
  2022-02-07 18:20 ` [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:19 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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>
---

Changes since V3:
* Use the device model api uclass_get_device to probe and get the FWU
  Metadata device.

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

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 02c298fdbe..c8eb12e00f 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -137,6 +137,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 if FWU_MULTI_BANK_UPDATE
+	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 e31ac15ef7..b917527965 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -72,6 +72,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..bc20ca26a3
--- /dev/null
+++ b/cmd/fwu_mdata.c
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * 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;
+	u32 nimages, nbanks;
+
+	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);
+
+	nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
+	nbanks = CONFIG_FWU_NUM_BANKS;
+	printf("\tImage Info\n");
+	for (i = 0; i < nimages; 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 < nbanks; j++) {
+			img_info = &img_entry->img_bank_info[j];
+			printf("Image Guid:  %pUL\n", &img_info->image_uuid);
+			printf("Image Acceptance: %#x\n", img_info->accepted);
+		}
+	}
+}
+
+int do_fwu_mdata_read(struct cmd_tbl *cmdtp, int flag,
+		     int argc, char * const argv[])
+{
+	struct udevice *dev;
+	int ret = CMD_RET_SUCCESS;
+	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;
+	}
+
+	ret = fwu_get_mdata(&mdata);
+	if (ret < 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.17.1


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

* [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (8 preceding siblings ...)
  2022-02-07 18:19 ` [PATCH v4 09/11] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
@ 2022-02-07 18:20 ` Sughosh Ganu
  2022-02-09  3:05   ` AKASHI Takahiro
  2022-02-07 18:20 ` [PATCH v4 11/11] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
  2022-02-08 11:05 ` [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Michal Simek
  11 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:20 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Sughosh Ganu

The Dependable Boot specification 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.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---

Changes since V3:
* Add related documentation for empty capsules in the mkeficapsule man
  page.
* Add separate usage for empty capsules, with corresponding valid
  options.
* Use ternary operators where possible.
* Put a exclusivity check for the empty capsule options.

 doc/mkeficapsule.1   |  23 +++++++-
 tools/eficapsule.h   |   8 +++
 tools/mkeficapsule.c | 131 ++++++++++++++++++++++++++++++++++++-------
 3 files changed, 139 insertions(+), 23 deletions(-)

diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
index 8babb27ee8..75fc15906a 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.
@@ -43,7 +48,7 @@ specify a guid for the FMP driver.
 .SH "OPTIONS"
 One of
 .BR --fit ", " --raw " or " --guid
-option must be specified.
+option must be specified for non empty capsules.
 
 .TP
 .BR -f ", " --fit
@@ -69,6 +74,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 8c1560bb06..6001952bdc 100644
--- a/tools/eficapsule.h
+++ b/tools/eficapsule.h
@@ -50,6 +50,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 161affdd15..e5dbec3a92 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -29,6 +29,7 @@
 #include "eficapsule.h"
 
 static const char *tool_name = "mkeficapsule";
+unsigned char accept_fw_capsule, revert_fw_capsule, empty_capsule;
 
 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
 efi_guid_t efi_guid_image_type_uboot_fit =
@@ -38,9 +39,9 @@ efi_guid_t efi_guid_image_type_uboot_raw =
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 
 #ifdef CONFIG_TOOLS_LIBCRYPTO
-static const char *opts_short = "frg:i:I:v:p:c:m:dh";
+static const char *opts_short = "frg:i:I:v:p:c:m:dhAR";
 #else
-static const char *opts_short = "frg:i:I:v:h";
+static const char *opts_short = "frg:i:I:v:hAR";
 #endif
 
 static struct option options[] = {
@@ -55,28 +56,50 @@ static struct option options[] = {
 	{"monotonic-count", required_argument, NULL, 'm'},
 	{"dump-sig", no_argument, NULL, 'd'},
 #endif
+	{"fw-accept", no_argument, NULL, 'A'},
+	{"fw-revert", no_argument, NULL, 'R'},
 	{"help", no_argument, NULL, 'h'},
 	{NULL, 0, NULL, 0},
 };
 
 static void print_usage(void)
 {
-	fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n"
-		"Options:\n"
-
-		"\t-f, --fit                   FIT image type\n"
-		"\t-r, --raw                   raw image type\n"
-		"\t-g, --guid <guid string>    guid for image blob type\n"
-		"\t-i, --index <index>         update image index\n"
-		"\t-I, --instance <instance>   update hardware instance\n"
+	if (empty_capsule) {
+		if (accept_fw_capsule) {
+			fprintf(stderr, "Usage: %s [options] <output file>\n",
+				tool_name);
+			fprintf(stderr, "Options:\n"
+				"\t-A, --fw-accept          firmware accept capsule\n"
+				"\t-g, --guid <guid string>    guid for image blob type\n"
+				"\t-h, --help                  print a help message\n"
+				);
+		} else {
+			fprintf(stderr, "Usage: %s [options] <output file>\n",
+				tool_name);
+			fprintf(stderr, "Options:\n"
+				"\t-R, --fw-revert          firmware revert capsule\n"
+				"\t-h, --help                  print a help message\n"
+				);
+		}
+	} else {
+		fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
+			tool_name);
+		fprintf(stderr, "Options:\n"
+			"\t-f, --fit                   FIT image type\n"
+			"\t-r, --raw                   raw image type\n"
+			"\t-g, --guid <guid string>    guid for image blob type\n"
+			"\t-i, --index <index>         update image index\n"
+			"\t-I, --instance <instance>   update hardware instance\n"
 #ifdef CONFIG_TOOLS_LIBCRYPTO
-		"\t-p, --private-key <privkey file>  private key file\n"
-		"\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-p, --private-key <privkey file>  private key file\n"
+			"\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"
 #endif
-		"\t-h, --help                  print a help message\n",
-		tool_name);
+			"\t-A, --fw-accept          firmware accept capsule\n"
+			"\t-R, --fw-revert          firmware revert capsule\n"
+			"\t-h, --help                  print a help message\n");
+	}
 }
 
 /**
@@ -598,6 +621,50 @@ 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;
+	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 payload, 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) {
+		memcpy(&payload, guid, sizeof(efi_guid_t));
+		if (write_capsule_file(f, &payload, sizeof(payload),
+				       "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
@@ -625,6 +692,8 @@ int main(int argc, char **argv)
 	mcount = 0;
 	privkey_file = NULL;
 	cert_file = NULL;
+	accept_fw_capsule = 0;
+	revert_fw_capsule = 0;
 	dump_sig = 0;
 	for (;;) {
 		c = getopt_long(argc, argv, opts_short, options, &idx);
@@ -691,22 +760,44 @@ int main(int argc, char **argv)
 			dump_sig = 1;
 			break;
 #endif /* CONFIG_TOOLS_LIBCRYPTO */
+		case 'A':
+			accept_fw_capsule = 1;
+			break;
+		case 'R':
+			revert_fw_capsule = 1;
+			break;
 		case 'h':
 			print_usage();
 			exit(EXIT_SUCCESS);
 		}
 	}
 
+	if (accept_fw_capsule && revert_fw_capsule) {
+		fprintf(stderr,
+			"Select either of Accept or Revert capsule generation\n");
+		exit(EXIT_FAILURE);
+	}
+
+	empty_capsule = (accept_fw_capsule || revert_fw_capsule);
+
 	/* check necessary parameters */
-	if ((argc != optind + 2) || !guid ||
-	    ((privkey_file && !cert_file) ||
+	if ((!empty_capsule && argc != optind + 2) ||
+	    (empty_capsule && argc != optind + 1) ||
+	    (!revert_fw_capsule && !guid) || ((privkey_file && !cert_file) ||
 	     (!privkey_file && cert_file))) {
 		print_usage();
 		exit(EXIT_FAILURE);
 	}
 
-	if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
-			 mcount, privkey_file, cert_file) < 0) {
+	if (empty_capsule) {
+		if (create_empty_capsule(argv[argc - 1], guid,
+					 accept_fw_capsule ? 1 : 0) < 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.17.1


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

* [PATCH v4 11/11] FWU: doc: Add documentation for the FWU feature
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (9 preceding siblings ...)
  2022-02-07 18:20 ` [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
@ 2022-02-07 18:20 ` Sughosh Ganu
  2022-02-08 11:05 ` [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Michal Simek
  11 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-07 18:20 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, 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 V3: None

 doc/develop/uefi/fwu_updates.rst | 142 +++++++++++++++++++++++++++++++
 doc/develop/uefi/index.rst       |   1 +
 doc/develop/uefi/uefi.rst        |   2 +
 3 files changed, 145 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..68e1a2ac76
--- /dev/null
+++ b/doc/develop/uefi/fwu_updates.rst
@@ -0,0 +1,142 @@
+.. 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 generic 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.txt>`_ 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 configs 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, certain changes are
+required to be done on the storage device. 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 parititions 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.
+
+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.
+
+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:: console
+
+    $ 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 a1a2afd60b..ecfb6699c9 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.17.1


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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
@ 2022-02-08  9:33   ` Masami Hiramatsu
  2022-02-08 10:24     ` Sughosh Ganu
  2022-02-08 10:56   ` Michal Simek
  2022-02-08 11:31   ` Michal Simek
  2 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-08  9:33 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

Thanks for updating the series. I have some comment on this patch.

2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
[snip]
> +
> +/**
> + * 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;

Again, as we discussed previous series, please don't return unused
allocated memory if the function returns an error.
That is something like putting a burden on the callers. They always
needs to initialize the pointer before call and free it even if the
function is failed.

> +       }
> +
> +       /*
> +        * 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;
> +       void *buf;
> +       struct fwu_mdata *mdata = NULL;
> +
> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> +               log_err("Active index value to be updated is incorrect\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;
> +
> +       /*
> +        * 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));

I would like to suggest moving this crc32 calculation in the fwu_update_mdata().
If the crc32 is for detecting a broken metadata on the "storage
media", I think it should be calculated in the fwu_update_mdata() to
simplify the code and avoid unexpected bugs from mistakes. If the
crc32 is calculated right before updating metadata, we can ensure that
the crc32 is always sane except for someone breaking it on the storage
media.

Thank you,



-- 
Masami Hiramatsu

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08  9:33   ` Masami Hiramatsu
@ 2022-02-08 10:24     ` Sughosh Ganu
  2022-02-08 11:23       ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 10:24 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Tue, 8 Feb 2022 at 15:04, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> Thanks for updating the series. I have some comment on this patch.
>
> 2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
> [snip]
> > +
> > +/**
> > + * 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;
>
> Again, as we discussed previous series, please don't return unused
> allocated memory if the function returns an error.
> That is something like putting a burden on the callers. They always
> needs to initialize the pointer before call and free it even if the
> function is failed.

I would like to keep the convention consistent. The function that
declares the pointer will also be responsible for free'ing it up. I
find the alternative to be more confusing, where in some instances the
callee frees up the memory, while in some cases it is the caller that
frees it up. If there is no stated convention in u-boot which forbids
this style of memory handling, I would like to keep this as is. I
would say that this makes the implementation easier for the callee,
since it is the responsibility of the caller to free up the memory.

>
> > +       }
> > +
> > +       /*
> > +        * 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;
> > +       void *buf;
> > +       struct fwu_mdata *mdata = NULL;
> > +
> > +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> > +               log_err("Active index value to be updated is incorrect\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;
> > +
> > +       /*
> > +        * 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));
>
> I would like to suggest moving this crc32 calculation in the fwu_update_mdata().
> If the crc32 is for detecting a broken metadata on the "storage
> media", I think it should be calculated in the fwu_update_mdata() to
> simplify the code and avoid unexpected bugs from mistakes. If the
> crc32 is calculated right before updating metadata, we can ensure that
> the crc32 is always sane except for someone breaking it on the storage
> media.

Makes sense. I will make the change as you are suggesting. Thanks.

-sughosh

>
> Thank you,
>
>
>
> --
> Masami Hiramatsu

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

* Re: [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification
  2022-02-07 18:19 ` [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2022-02-08 10:53   ` Michal Simek
  2022-02-11 10:46     ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 10:53 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

po 7. 2. 2022 v 19:22 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>
> 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 V3:
> * Change the TrialStateCtr efi variable attribute to remove the
>   runtime attribute
>
>  common/board_r.c      |   6 ++
>  include/fwu.h         |   3 +
>  lib/fwu_updates/fwu.c | 178 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 187 insertions(+)
>  create mode 100644 lib/fwu_updates/fwu.c
>
> diff --git a/common/board_r.c b/common/board_r.c
> index 31a59c585a..81678870b9 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -78,6 +78,9 @@
>  #ifdef CONFIG_EFI_SETUP_EARLY
>  #include <efi_loader.h>
>  #endif
> +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE
> +#include <fwu.h>
> +#endif
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> @@ -805,6 +808,9 @@ static init_fnc_t init_sequence_r[] = {
>  #endif
>  #ifdef CONFIG_EFI_SETUP_EARLY
>         (init_fnc_t)efi_init_obj_list,
> +#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 90b8cd41e5..5a329d9ef7 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)
>
> +int fwu_boottime_checks(void);
> +u8 fwu_update_checks_pass(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
> new file mode 100644
> index 0000000000..86933123e7
> --- /dev/null
> +++ b/lib/fwu_updates/fwu.c
> @@ -0,0 +1,178 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2021, 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 = 0;
> +static u8 boottime_check = 0;

you don't need to initialize them to 0. They are in bss which is setup
to 0 already.

> +
> +static int fwu_trial_state_check(void)
> +{
> +       int ret, i;
> +       efi_status_t status;
> +       efi_uintn_t var_size;
> +       u16 trial_state_ctr;
> +       u32 nimages, active_bank, var_attributes, active_idx;
> +       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)

Isn't it easier to have if (ret) here?

> +               return ret;
> +
> +       ret = 0;

Then you can remove this and the whole ret handling below is weird.


> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> +       active_bank = mdata->active_index;
> +       img_entry = &mdata->img_entry[0];
> +       for (i = 0; i < nimages; i++) {
> +               img_bank_info = &img_entry[i].img_bank_info[active_bank];
> +               if (!img_bank_info->accepted) {
> +                       trial_state = 1;
> +                       break;
> +               }
> +       }
> +
> +       if (trial_state) {
> +               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(L"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;

Any reason not to use standard return macros? The same I see below too.

> +                       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 < 0) {

I would use if (ret) here.

> +                               log_err("Unable to revert active_index\n");
> +                               goto out;
> +                       }
> +
> +                       trial_state_ctr = 0;
> +                       status = efi_set_variable_int(L"TrialStateCtr",
> +                                                     &efi_global_variable_guid,
> +                                                     var_attributes,
> +                                                     0,
> +                                                     &trial_state_ctr, false);
> +                       if (status != EFI_SUCCESS) {
> +                               log_err("Unable to clear TrialStateCtr variable\n");
> +                               ret = -1;
> +                               goto out;
> +                       }
> +               } else {
> +                       status = efi_set_variable_int(L"TrialStateCtr",
> +                                                     &efi_global_variable_guid,
> +                                                     var_attributes,
> +                                                     var_size,
> +                                                     &trial_state_ctr, false);
> +                       if (status != EFI_SUCCESS) {
> +                               log_err("Unable to increment TrialStateCtr variable\n");
> +                               ret = -1;
> +                               goto out;
> +                       } else {
> +                               ret = 0;

Why do you need this? ret should be 0 when you get here.

> +                       }
> +               }
> +       } else {
> +               trial_state_ctr = 0;
> +               ret = 0;

the same here. You have ret=0 above that's why I think this is just an
additional line here.

> +               status = efi_set_variable_int(L"TrialStateCtr",
> +                                             &efi_global_variable_guid,
> +                                             0,
> +                                             0, &trial_state_ctr,
> +                                             NULL);
> +       }
> +
> +out:
> +       free(mdata);
> +       return ret;
> +}
> +
> +u8 fwu_update_checks_pass(void)
> +{
> +       return !trial_state && boottime_check;
> +}
> +
> +int fwu_boottime_checks(void)
> +{
> +       int ret;
> +       struct udevice *dev;
> +       u32 boot_idx, active_idx;
> +
> +       if (uclass_get_device(UCLASS_FWU_MDATA, 0, &dev) || !dev) {
> +               log_err("FWU Metadata device not found\n");
> +               boottime_check = 0;

All these boottime_check initialization to 0 seems to me useless.

> +               return 0;
> +       }
> +
> +       ret = fwu_mdata_check();
> +       if (ret < 0) {

up to you but I would also use if (ret) here.

> +               boottime_check = 0;

It is zero already when you get here that's why all these = 0 lines
should be IMHO removed.

> +               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");
> +               boottime_check = 0;

ditto.

> +               return 0;
> +       }
> +
> +       ret = fwu_get_active_index(&active_idx);
> +       if (ret < 0) {

ditto.

> +               log_err("Unable to read active_index\n");
> +               boottime_check = 0;

ditto.

> +               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 < 0)

ditto.

> +                       boottime_check = 0;

ditto

> +               else
> +                       boottime_check = 1;
> +
> +               return 0;
> +       }
> +
> +       ret = fwu_trial_state_check();
> +       if (ret < 0)

ditto

> +               boottime_check = 0;

ditto.

> +       else
> +               boottime_check = 1;
> +
> +       return 0;
> +}
> --
> 2.17.1
>

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
  2022-02-08  9:33   ` Masami Hiramatsu
@ 2022-02-08 10:56   ` Michal Simek
  2022-02-08 11:35     ` Sughosh Ganu
  2022-02-08 11:31   ` Michal Simek
  2 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 10:56 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Michal Simek

po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>
> 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.
>
> A device tree node fwu-mdata has been added, which is used for
> pointing to the storage device which contains the FWU metadata. The
> fwu-mdata node is u-boot specific, and can be added the platform's
> u-boot dtsi file.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>
> Changes since V3:
> * Move the FWU metadata access to driver model
> * Get the storage device containing the metadata from a device tree
>   property instead of a platform helper function
>
>  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>  .../firmware/fwu-mdata.txt                    |  18 +
>  drivers/Kconfig                               |   2 +
>  drivers/Makefile                              |   1 +
>  drivers/fwu-mdata/Kconfig                     |   7 +
>  drivers/fwu-mdata/Makefile                    |   6 +
>  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>  include/dm/uclass-id.h                        |   1 +
>  include/fwu.h                                 |  51 ++
>  include/fwu_mdata.h                           |  67 +++
>  10 files changed, 594 insertions(+)
>  create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>  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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> index 06ef3a4095..3bec6107f7 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";
> +               fwu-mdata-store = <&sdmmc1>;
> +       };
> +};
> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> new file mode 100644
> index 0000000000..c766b595ef
> --- /dev/null
> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> @@ -0,0 +1,18 @@
> +FWU Metadata Access Devicetree Binding
> +
> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> +a separate partition for keeping information on the set of updatable
> +images. The device tree node provides information on the storage
> +device that contains the FWU metadata.
> +
> +Required properties :
> +
> +- compatible : "u-boot,fwu-mdata";
> +- fwu-mdata-store : should point to the storage device which contains
> +                   the FWU metadata partition.

In 0/11 you are describing GPT partitions but I don't think this
binding is generic enough to describe
other cases. It is saying device but not where exactly it is.
I didn't read the whole series yet but arm spec recommends GPT but dt
binding should be generic enough to describe
also other cases.
We are saving this structure to qspi for example but current binding
can't be used for it.

> +
> +Example :
> +       fwu-mdata {
> +               compatible = "u-boot,fwu-mdata";
> +               fwu-mdata-store = <&sdmmc1>;
> +       };

I don't think this is aligned with getting these u-boot nodes to any
standard locations.
Simon had that discussion with Rob some time ago. Was there any
outcome from this discussion where u-boot nodes should go?

Thanks,
Michal

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

* Re: [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature
  2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (10 preceding siblings ...)
  2022-02-07 18:20 ` [PATCH v4 11/11] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
@ 2022-02-08 11:05 ` Michal Simek
  2022-02-08 12:09   ` Sughosh Ganu
  11 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 11:05 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>
>
>
> 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
> board which boots a FIP image from a uSD card partitioned with the GPT
> partioning scheme. This also requires changes in the previous stage of
> bootloader, which parses the metadata and selects the bank to boot the
> image(s) from. Support is 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's integration branch[3].
>
> These patches are based on top of the series from Takahiro to add
> Authentication support to mkeficapsule utility[4] and a couple of
> other patches[5][6]
>
> TODO's
> ------
> * Add a unit test case for the newly added FWU_MDATA uclass. Some
>   involved effort is needed on this since the host device interface on
>   sandbox cannot be used with the UT framework.
> * Add test case for the feature with the python test suite, along the
>   lines of capsule update testing.
>
> [1] - https://developer.arm.com/documentation/den0118/a
> [2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
> [3] - https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/log/?h=integration
> [4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> [5] - https://patchwork.ozlabs.org/project/uboot/patch/164388019634.446835.18271480521485569016.stgit@localhost/
> [6] - https://patchwork.ozlabs.org/project/uboot/patch/20220129192108.6618-1-sughosh.ganu@linaro.org/
>
>
> Changes since V3:
> * Move the FWU metadata access to driver model
> * Get the storage device containing the metadata from a device tree
>   property instead of a platform helper function
> * Move the metadata access driver for GPT partitioned block devices
>   under drivers/fwu-mdata/ directory, complying with driver model.
> * Move functionality to get the active index under the common function
>   instead of the GPT block device specific driver.
> * Remove function for getting the storage device containing the
>   metadata as the information is now obtained from the device tree.
> * Define a weak function fill_image_type_guid_array for populating the
>   image descriptor array with u-boot's raw and fit image GUIDs
> * Define the function fill_image_type_guid_array for the ST DK2 board
>   for GPT partitioned devices.
> * Change the TrialStateCtr efi variable attribute to remove the
>   runtime attribute
> * Rebase the change on top of the patch from Masami to call
>   efi_capsule_update_firmware directly.
> * Put the FWU related checks which were earlier in efi_update_capsule
>   function to separate functions fwu_empty_capsule and
>   fwu_empty_capsule_process.
> * Use the device model api uclass_get_device to probe and get the FWU
>   Metadata device.
> * Add related documentation for empty capsules in the mkeficapsule man
>   page.
> * Add separate usage for empty capsules, with corresponding valid
>   options.
> * Use ternary operators where possible.
> * Put a exclusivity check for the empty capsule options.
>
>
> Sughosh Ganu (11):
>   FWU: Add FWU metadata structure and driver for accessing metadata
>   FWU: Add FWU metadata access driver for GPT partitioned block devices
>   FWU: stm32mp1: Add helper functions for accessing FWU metadata
>   FWU: STM32MP1: Add support to read boot index from backup register
>   EFI: FMP: Add provision to update image's ImageTypeId in image
>     descriptor
>   stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR
>     array
>   FWU: Add boot time checks as highlighted by the FWU specification
>   FWU: Add support for FWU Multi Bank Update feature
>   FWU: cmd: Add a command to read FWU metadata
>   mkeficapsule: Add support for generating empty capsules
>   FWU: doc: Add documentation for the FWU feature
>
>  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>  board/st/stm32mp1/stm32mp1.c                  | 178 +++++++
>  cmd/Kconfig                                   |   7 +
>  cmd/Makefile                                  |   1 +
>  cmd/fwu_mdata.c                               |  74 +++
>  common/board_r.c                              |   6 +
>  doc/develop/uefi/fwu_updates.rst              | 142 +++++
>  doc/develop/uefi/index.rst                    |   1 +
>  doc/develop/uefi/uefi.rst                     |   2 +
>  .../firmware/fwu-mdata.txt                    |  18 +
>  doc/mkeficapsule.1                            |  23 +-
>  drivers/Kconfig                               |   2 +
>  drivers/Makefile                              |   1 +
>  drivers/fwu-mdata/Kconfig                     |  16 +
>  drivers/fwu-mdata/Makefile                    |   7 +
>  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 +++++++++++++++
>  drivers/fwu-mdata/fwu_mdata_gpt_blk.c         | 501 ++++++++++++++++++
>  include/dm/uclass-id.h                        |   1 +
>  include/efi_loader.h                          |   2 +
>  include/fwu.h                                 |  70 +++
>  include/fwu_mdata.h                           |  67 +++
>  lib/Kconfig                                   |   6 +
>  lib/Makefile                                  |   1 +
>  lib/efi_loader/efi_capsule.c                  | 221 +++++++-
>  lib/efi_loader/efi_firmware.c                 |  71 ++-
>  lib/efi_loader/efi_setup.c                    |   3 +-
>  lib/fwu_updates/Kconfig                       |  31 ++
>  lib/fwu_updates/Makefile                      |   6 +
>  lib/fwu_updates/fwu.c                         | 204 +++++++
>  tools/eficapsule.h                            |   8 +
>  tools/mkeficapsule.c                          | 131 ++++-
>  31 files changed, 2208 insertions(+), 34 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.txt
>  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
>
> --
> 2.17.1
>
>

What's the git base you use for this series?

Thanks,
Michal

-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 10:24     ` Sughosh Ganu
@ 2022-02-08 11:23       ` Masami Hiramatsu
  0 siblings, 0 replies; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-08 11:23 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

[-- Attachment #1: Type: text/plain, Size: 2957 bytes --]

Hi Sughosh,

2022年2月8日(火) 19:24 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> hi Masami,
>
> On Tue, 8 Feb 2022 at 15:04, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > Thanks for updating the series. I have some comment on this patch.
> >
> > 2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > [snip]
> > > +
> > > +/**
> > > + * 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;
> >
> > Again, as we discussed previous series, please don't return unused
> > allocated memory if the function returns an error.
> > That is something like putting a burden on the callers. They always
> > needs to initialize the pointer before call and free it even if the
> > function is failed.
>
> I would like to keep the convention consistent. The function that
> declares the pointer will also be responsible for free'ing it up. I
> find the alternative to be more confusing, where in some instances the
> callee frees up the memory, while in some cases it is the caller that
> frees it up. If there is no stated convention in u-boot which forbids
> this style of memory handling, I would like to keep this as is. I
> would say that this makes the implementation easier for the callee,
> since it is the responsibility of the caller to free up the memory.

Hmm, ... I'm not convinced yet. Please give me the last chance to argue.
I think the pointer is the pointer, that is not the resource itself.

Please see `man asprintf` for example.
Usually, if the function, which allocates any resource including
memory, returns an error, the resource pointer is undefined.
Of course, there is no need to unallocate the memory for
undefined address.
That is I think the standard way to handle the resource
allocation.

And actually, the callee implementation isn't simplified. In my
case, it forces me to re-initialize the pointer to NULL if an error
occurs. additional 1-line is needed :-) (maybe I need more
comment lines to explain why this NULL setting is required)

BTW, I attached a patch to change this code. You can see
the gpt_get_mdata() is refined into 2 gpt_get_mdata_part()
and many gotos are removed.
This shows how both of callee and caller can be simplified
with the convention which I suggested.

Thank you,

-- 
Masami Hiramatsu

[-- Attachment #2: 0001-FWU-Free-metadata-copy-if-gpt_get_mdata-failed.patch --]
[-- Type: text/x-patch, Size: 5099 bytes --]

From 695b4276283654bcf0440889cf214b887174345d Mon Sep 17 00:00:00 2001
From: Masami Hiramatsu <masami.hiramatsu@linaro.org>
Date: Thu, 20 Jan 2022 15:41:49 +0900
Subject: [PATCH] FWU: Free metadata copy if gpt_get_mdata() failed

It is better if a function which returns an error then release
all allocated memory resources. This simplifies the mind model
and less chance to forgot to free memory and double free.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu@linaro.org>
---
 drivers/fwu-mdata/fwu-mdata-uclass.c  | 24 +++++--------
 drivers/fwu-mdata/fwu_mdata_gpt_blk.c | 49 +++++++++++++++------------
 2 files changed, 36 insertions(+), 37 deletions(-)

diff --git a/drivers/fwu-mdata/fwu-mdata-uclass.c b/drivers/fwu-mdata/fwu-mdata-uclass.c
index fad44b25d1..512ce157e9 100644
--- a/drivers/fwu-mdata/fwu-mdata-uclass.c
+++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
@@ -79,12 +79,12 @@ int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part)
 int fwu_get_active_index(u32 *active_idx)
 {
 	int ret;
-	struct fwu_mdata *mdata = NULL;
+	struct fwu_mdata *mdata;
 
 	ret = fwu_get_mdata(&mdata);
 	if (ret < 0) {
 		log_err("Unable to get valid FWU metadata\n");
-		goto out;
+		return ret;
 	}
 
 	/*
@@ -96,8 +96,6 @@ int fwu_get_active_index(u32 *active_idx)
 		log_err("Active index value read is incorrect\n");
 		ret = -EINVAL;
 	}
-
-out:
 	free(mdata);
 
 	return ret;
@@ -115,17 +113,17 @@ out:
 int fwu_update_active_index(u32 active_idx)
 {
 	int ret;
-	struct fwu_mdata *mdata = NULL;
+	struct fwu_mdata *mdata;
 
 	if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
 		log_err("Active index value to be updated is incorrect\n");
-		return -1;
+		return -EINVAL;
 	}
 
 	ret = fwu_get_mdata(&mdata);
 	if (ret < 0) {
 		log_err("Unable to get valid FWU metadata\n");
-		goto out;
+		return ret;
 	}
 
 	/*
@@ -144,8 +142,6 @@ int fwu_update_active_index(u32 active_idx)
 		log_err("Failed to update FWU metadata partitions\n");
 		ret = -EIO;
 	}
-
-out:
 	free(mdata);
 
 	return ret;
@@ -225,12 +221,12 @@ int fwu_revert_boot_index(void)
 {
 	int ret;
 	u32 cur_active_index;
-	struct fwu_mdata *mdata = NULL;
+	struct fwu_mdata *mdata;
 
 	ret = fwu_get_mdata(&mdata);
 	if (ret < 0) {
 		log_err("Unable to get valid FWU metadata\n");
-		goto out;
+		return ret;
 	}
 
 	/*
@@ -250,8 +246,6 @@ int fwu_revert_boot_index(void)
 		log_err("Failed to update FWU metadata partitions\n");
 		ret = -EIO;
 	}
-
-out:
 	free(mdata);
 
 	return ret;
@@ -277,14 +271,14 @@ static int fwu_set_clear_image_accept(efi_guid_t *img_type_id,
 {
 	int ret, i;
 	u32 nimages;
-	struct fwu_mdata *mdata = NULL;
+	struct fwu_mdata *mdata;
 	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;
+		return ret;
 	}
 
 	nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
diff --git a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
index 9170c3f6af..a32195db2e 100644
--- a/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
+++ b/drivers/fwu-mdata/fwu_mdata_gpt_blk.c
@@ -177,18 +177,9 @@ static int fwu_gpt_update_mdata(struct udevice * dev, struct fwu_mdata *mdata)
 	return 0;
 }
 
-static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata)
+static int gpt_get_mdata_part(struct blk_desc *desc, struct fwu_mdata **mdata, u16 part)
 {
 	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) {
@@ -196,28 +187,42 @@ static int gpt_get_mdata(struct blk_desc *desc, struct fwu_mdata **mdata)
 		return -ENOMEM;
 	}
 
-	ret = gpt_read_mdata(desc, *mdata, primary_mpart);
+	ret = gpt_read_mdata(desc, *mdata, part);
 	if (ret < 0) {
 		log_err("Failed to read the FWU metadata from the device\n");
-		return -EIO;
+		ret = -EIO;
+	} else {
+		ret = fwu_verify_mdata(*mdata, 1);
+		if (!ret)
+			return 0;
 	}
+	free(*mdata);
+
+	return ret;
+}
 
-	ret = fwu_verify_mdata(*mdata, 1);
+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;
+	}
+
+	ret = gpt_get_mdata_part(desc, mdata, primary_mpart);
 	if (!ret)
 		return 0;
 
 	/*
-	 * Verification of the primary FWU metadata copy failed.
+	 * Reading 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);
+	ret = gpt_get_mdata_part(desc, mdata, secondary_mpart);
 	if (!ret)
 		return 0;
 
-- 
2.25.1


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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
  2022-02-08  9:33   ` Masami Hiramatsu
  2022-02-08 10:56   ` Michal Simek
@ 2022-02-08 11:31   ` Michal Simek
  2022-02-08 11:38     ` Sughosh Ganu
  2 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 11:31 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>
> 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.
>
> A device tree node fwu-mdata has been added, which is used for
> pointing to the storage device which contains the FWU metadata. The
> fwu-mdata node is u-boot specific, and can be added the platform's
> u-boot dtsi file.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>
> Changes since V3:
> * Move the FWU metadata access to driver model
> * Get the storage device containing the metadata from a device tree
>   property instead of a platform helper function
>
>  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>  .../firmware/fwu-mdata.txt                    |  18 +
>  drivers/Kconfig                               |   2 +
>  drivers/Makefile                              |   1 +
>  drivers/fwu-mdata/Kconfig                     |   7 +
>  drivers/fwu-mdata/Makefile                    |   6 +
>  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>  include/dm/uclass-id.h                        |   1 +
>  include/fwu.h                                 |  51 ++
>  include/fwu_mdata.h                           |  67 +++
>  10 files changed, 594 insertions(+)
>  create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>  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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> index 06ef3a4095..3bec6107f7 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";
> +               fwu-mdata-store = <&sdmmc1>;
> +       };
> +};
> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> new file mode 100644
> index 0000000000..c766b595ef
> --- /dev/null
> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> @@ -0,0 +1,18 @@
> +FWU Metadata Access Devicetree Binding
> +
> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> +a separate partition for keeping information on the set of updatable
> +images. The device tree node provides information on the storage
> +device that contains the FWU metadata.
> +
> +Required properties :
> +
> +- compatible : "u-boot,fwu-mdata";
> +- fwu-mdata-store : should point to the storage device which contains
> +                   the FWU metadata partition.
> +
> +Example :
> +       fwu-mdata {
> +               compatible = "u-boot,fwu-mdata";
> +               fwu-mdata-store = <&sdmmc1>;
> +       };
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index b26ca8cf70..adc6079ecf 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -81,6 +81,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..7fec7171f4
> --- /dev/null
> +++ b/drivers/fwu-mdata/Makefile
> @@ -0,0 +1,6 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +# 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..64b3051ecf
> --- /dev/null
> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> @@ -0,0 +1,434 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2022, Linaro Limited
> + */
> +
> +#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;
> +       void *buf;
> +       struct fwu_mdata *mdata = NULL;
> +
> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> +               log_err("Active index value to be updated is incorrect\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;
> +
> +       /*
> +        * 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));
> +
> +       /*
> +        * 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: 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;
> +       const struct fwu_mdata_ops *ops = NULL;
> +       struct udevice *dev = NULL;
> +
> +       ret = fwu_get_dev_ops(&dev, &ops);
> +       if (ret)
> +               return ret;
> +
> +       if (!ops->get_image_alt_num) {
> +               log_err("get_image_alt_num() method not defined\n");
> +               return -ENOSYS;
> +       }
> +
> +       return ops->get_image_alt_num(dev, image_type_id,
> +                                     update_bank, alt_num);
> +}
> +
> +/**
> + * 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;
> +       void *buf;
> +       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;
> +
> +       /*
> +        * 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));
> +
> +       /*
> +        * 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)
> +{
> +       void *buf;
> +       int ret, i;
> +       u32 nimages;
> +       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;
> +       }
> +
> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> +       img_entry = &mdata->img_entry[0];
> +       for (i = 0; i < nimages; 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;
> +
> +                       buf = &mdata->version;
> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
> +                                            sizeof(u32));
> +
> +                       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.
> + *
> + * 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.
> + *
> + * Return: 0 if OK, -ve on error
> + *
> + */
> +int fwu_update_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->update_mdata) {
> +               log_err("get_mdata() method not defined\n");
> +               return -ENOSYS;
> +       }
> +
> +       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 0e26e1d138..d0ab1c9235 100644
> --- a/include/dm/uclass-id.h
> +++ b/include/dm/uclass-id.h
> @@ -54,6 +54,7 @@ enum uclass_id {
>         UCLASS_ETH_PHY,         /* Ethernet PHY device */
>         UCLASS_FIRMWARE,        /* Firmware */
>         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..5a99c579fc
> --- /dev/null
> +++ b/include/fwu.h
> @@ -0,0 +1,51 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * 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;
> +
> +/**
> + * @get_image_alt_num: get the alt number to be used for the image
> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
> +                                u32 update_bank, int *alt_num);
> +
> +       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);
> +
> +#endif /* _FWU_H_ */
> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> new file mode 100644
> index 0000000000..701efbba03
> --- /dev/null
> +++ b/include/fwu_mdata.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * 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.17.1
>

One more thing. run kernel-doc to validate your description.
[u-boot](eeee)$ ./scripts/kernel-doc -v -man
drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
fwu_get_active_index
drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
fwu_update_active_index
drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
fwu_get_image_alt_num
drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
fwu_revert_boot_index
drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
fwu_set_clear_image_accept
drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
fwu_accept_image
drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
fwu_clear_accept_image
drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
fwu_update_mdata
2 warnings

when I run buildman over this series it is visible that it is not
bisectable at all.
CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
much later.
Please make sure every single patch is bisectable.

And also I would separate dt binding, board dt update from actual feature.

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 10:56   ` Michal Simek
@ 2022-02-08 11:35     ` Sughosh Ganu
  2022-02-08 11:39       ` Michal Simek
  2022-02-08 13:36       ` Masami Hiramatsu
  0 siblings, 2 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 11:35 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Michal Simek

On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
>
> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >
> > 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.
> >
> > A device tree node fwu-mdata has been added, which is used for
> > pointing to the storage device which contains the FWU metadata. The
> > fwu-mdata node is u-boot specific, and can be added the platform's
> > u-boot dtsi file.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >
> > Changes since V3:
> > * Move the FWU metadata access to driver model
> > * Get the storage device containing the metadata from a device tree
> >   property instead of a platform helper function
> >
> >  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >  .../firmware/fwu-mdata.txt                    |  18 +
> >  drivers/Kconfig                               |   2 +
> >  drivers/Makefile                              |   1 +
> >  drivers/fwu-mdata/Kconfig                     |   7 +
> >  drivers/fwu-mdata/Makefile                    |   6 +
> >  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >  include/dm/uclass-id.h                        |   1 +
> >  include/fwu.h                                 |  51 ++
> >  include/fwu_mdata.h                           |  67 +++
> >  10 files changed, 594 insertions(+)
> >  create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >  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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> > index 06ef3a4095..3bec6107f7 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";
> > +               fwu-mdata-store = <&sdmmc1>;
> > +       };
> > +};
> > diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> > new file mode 100644
> > index 0000000000..c766b595ef
> > --- /dev/null
> > +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> > @@ -0,0 +1,18 @@
> > +FWU Metadata Access Devicetree Binding
> > +
> > +The FWU Multi Bank Update feature uses a metadata structure, stored on
> > +a separate partition for keeping information on the set of updatable
> > +images. The device tree node provides information on the storage
> > +device that contains the FWU metadata.
> > +
> > +Required properties :
> > +
> > +- compatible : "u-boot,fwu-mdata";
> > +- fwu-mdata-store : should point to the storage device which contains
> > +                   the FWU metadata partition.
>
> In 0/11 you are describing GPT partitions but I don't think this
> binding is generic enough to describe
> other cases. It is saying device but not where exactly it is.
> I didn't read the whole series yet but arm spec recommends GPT but dt
> binding should be generic enough to describe
> also other cases.
> We are saving this structure to qspi for example but current binding
> can't be used for it.

I would wait to see Masami's implementation of this feature. If I am
not wrong, his platform too is enabling this feature with a spi as the
storage device. Maybe we can instead put a list of <device partition>
tuples which can then list the device and partition number of the
metadata partitions.

-sughosh

 >
> > +
> > +Example :
> > +       fwu-mdata {
> > +               compatible = "u-boot,fwu-mdata";
> > +               fwu-mdata-store = <&sdmmc1>;
> > +       };
>
> I don't think this is aligned with getting these u-boot nodes to any
> standard locations.
> Simon had that discussion with Rob some time ago. Was there any
> outcome from this discussion where u-boot nodes should go?
>
> Thanks,
> Michal

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:31   ` Michal Simek
@ 2022-02-08 11:38     ` Sughosh Ganu
  2022-02-08 11:44       ` Michal Simek
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 11:38 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
>
> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >
> > 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.
> >
> > A device tree node fwu-mdata has been added, which is used for
> > pointing to the storage device which contains the FWU metadata. The
> > fwu-mdata node is u-boot specific, and can be added the platform's
> > u-boot dtsi file.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >
> > Changes since V3:
> > * Move the FWU metadata access to driver model
> > * Get the storage device containing the metadata from a device tree
> >   property instead of a platform helper function
> >
> >  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >  .../firmware/fwu-mdata.txt                    |  18 +
> >  drivers/Kconfig                               |   2 +
> >  drivers/Makefile                              |   1 +
> >  drivers/fwu-mdata/Kconfig                     |   7 +
> >  drivers/fwu-mdata/Makefile                    |   6 +
> >  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >  include/dm/uclass-id.h                        |   1 +
> >  include/fwu.h                                 |  51 ++
> >  include/fwu_mdata.h                           |  67 +++
> >  10 files changed, 594 insertions(+)
> >  create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >  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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> > index 06ef3a4095..3bec6107f7 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";
> > +               fwu-mdata-store = <&sdmmc1>;
> > +       };
> > +};
> > diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> > new file mode 100644
> > index 0000000000..c766b595ef
> > --- /dev/null
> > +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> > @@ -0,0 +1,18 @@
> > +FWU Metadata Access Devicetree Binding
> > +
> > +The FWU Multi Bank Update feature uses a metadata structure, stored on
> > +a separate partition for keeping information on the set of updatable
> > +images. The device tree node provides information on the storage
> > +device that contains the FWU metadata.
> > +
> > +Required properties :
> > +
> > +- compatible : "u-boot,fwu-mdata";
> > +- fwu-mdata-store : should point to the storage device which contains
> > +                   the FWU metadata partition.
> > +
> > +Example :
> > +       fwu-mdata {
> > +               compatible = "u-boot,fwu-mdata";
> > +               fwu-mdata-store = <&sdmmc1>;
> > +       };
> > diff --git a/drivers/Kconfig b/drivers/Kconfig
> > index b26ca8cf70..adc6079ecf 100644
> > --- a/drivers/Kconfig
> > +++ b/drivers/Kconfig
> > @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
> > --- a/drivers/Makefile
> > +++ b/drivers/Makefile
> > @@ -81,6 +81,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..7fec7171f4
> > --- /dev/null
> > +++ b/drivers/fwu-mdata/Makefile
> > @@ -0,0 +1,6 @@
> > +# SPDX-License-Identifier: GPL-2.0+
> > +#
> > +# 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..64b3051ecf
> > --- /dev/null
> > +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> > @@ -0,0 +1,434 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2022, Linaro Limited
> > + */
> > +
> > +#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;
> > +       void *buf;
> > +       struct fwu_mdata *mdata = NULL;
> > +
> > +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> > +               log_err("Active index value to be updated is incorrect\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;
> > +
> > +       /*
> > +        * 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));
> > +
> > +       /*
> > +        * 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: 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;
> > +       const struct fwu_mdata_ops *ops = NULL;
> > +       struct udevice *dev = NULL;
> > +
> > +       ret = fwu_get_dev_ops(&dev, &ops);
> > +       if (ret)
> > +               return ret;
> > +
> > +       if (!ops->get_image_alt_num) {
> > +               log_err("get_image_alt_num() method not defined\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       return ops->get_image_alt_num(dev, image_type_id,
> > +                                     update_bank, alt_num);
> > +}
> > +
> > +/**
> > + * 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;
> > +       void *buf;
> > +       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;
> > +
> > +       /*
> > +        * 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));
> > +
> > +       /*
> > +        * 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)
> > +{
> > +       void *buf;
> > +       int ret, i;
> > +       u32 nimages;
> > +       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;
> > +       }
> > +
> > +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> > +       img_entry = &mdata->img_entry[0];
> > +       for (i = 0; i < nimages; 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;
> > +
> > +                       buf = &mdata->version;
> > +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
> > +                                            sizeof(u32));
> > +
> > +                       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.
> > + *
> > + * 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.
> > + *
> > + * Return: 0 if OK, -ve on error
> > + *
> > + */
> > +int fwu_update_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->update_mdata) {
> > +               log_err("get_mdata() method not defined\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       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 0e26e1d138..d0ab1c9235 100644
> > --- a/include/dm/uclass-id.h
> > +++ b/include/dm/uclass-id.h
> > @@ -54,6 +54,7 @@ enum uclass_id {
> >         UCLASS_ETH_PHY,         /* Ethernet PHY device */
> >         UCLASS_FIRMWARE,        /* Firmware */
> >         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..5a99c579fc
> > --- /dev/null
> > +++ b/include/fwu.h
> > @@ -0,0 +1,51 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * 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;
> > +
> > +/**
> > + * @get_image_alt_num: get the alt number to be used for the image
> > + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
> > +                                u32 update_bank, int *alt_num);
> > +
> > +       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);
> > +
> > +#endif /* _FWU_H_ */
> > diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> > new file mode 100644
> > index 0000000000..701efbba03
> > --- /dev/null
> > +++ b/include/fwu_mdata.h
> > @@ -0,0 +1,67 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * 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.17.1
> >
>
> One more thing. run kernel-doc to validate your description.
> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
> fwu_get_active_index
> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
> fwu_update_active_index
> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
> fwu_get_image_alt_num
> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
> fwu_revert_boot_index
> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
> fwu_set_clear_image_accept
> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
> fwu_accept_image
> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
> fwu_clear_accept_image
> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
> fwu_update_mdata
> 2 warnings
>
> when I run buildman over this series it is visible that it is not
> bisectable at all.
> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
> much later.
> Please make sure every single patch is bisectable.


But how is this driver getting built in the first place -- the driver
is not enabling the config symbol which would result in the code
getting built. The idea is to add support for the driver and the
feature, and enable the functionality in the final patch. I have added
each patch separately and built for the qemu arm64 platform without
any issues.

>
> And also I would separate dt binding, board dt update from actual feature.

Okay.

-sughosh

>
> Thanks,
> Michal
>
>
> --
> Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
> w: www.monstr.eu p: +42-0-721842854
> Maintainer of Linux kernel - Xilinx Microblaze
> Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
> U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:35     ` Sughosh Ganu
@ 2022-02-08 11:39       ` Michal Simek
  2022-02-08 13:36       ` Masami Hiramatsu
  1 sibling, 0 replies; 64+ messages in thread
From: Michal Simek @ 2022-02-08 11:39 UTC (permalink / raw)
  To: Sughosh Ganu, Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Michal Simek



On 2/8/22 12:35, Sughosh Ganu wrote:
> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
>>
>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>
>>> 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.
>>>
>>> A device tree node fwu-mdata has been added, which is used for
>>> pointing to the storage device which contains the FWU metadata. The
>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>> u-boot dtsi file.
>>>
>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>> ---
>>>
>>> Changes since V3:
>>> * Move the FWU metadata access to driver model
>>> * Get the storage device containing the metadata from a device tree
>>>    property instead of a platform helper function
>>>
>>>   arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>   .../firmware/fwu-mdata.txt                    |  18 +
>>>   drivers/Kconfig                               |   2 +
>>>   drivers/Makefile                              |   1 +
>>>   drivers/fwu-mdata/Kconfig                     |   7 +
>>>   drivers/fwu-mdata/Makefile                    |   6 +
>>>   drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>   include/dm/uclass-id.h                        |   1 +
>>>   include/fwu.h                                 |  51 ++
>>>   include/fwu_mdata.h                           |  67 +++
>>>   10 files changed, 594 insertions(+)
>>>   create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>   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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>> index 06ef3a4095..3bec6107f7 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";
>>> +               fwu-mdata-store = <&sdmmc1>;
>>> +       };
>>> +};
>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>> new file mode 100644
>>> index 0000000000..c766b595ef
>>> --- /dev/null
>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>> @@ -0,0 +1,18 @@
>>> +FWU Metadata Access Devicetree Binding
>>> +
>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>> +a separate partition for keeping information on the set of updatable
>>> +images. The device tree node provides information on the storage
>>> +device that contains the FWU metadata.
>>> +
>>> +Required properties :
>>> +
>>> +- compatible : "u-boot,fwu-mdata";
>>> +- fwu-mdata-store : should point to the storage device which contains
>>> +                   the FWU metadata partition.
>>
>> In 0/11 you are describing GPT partitions but I don't think this
>> binding is generic enough to describe
>> other cases. It is saying device but not where exactly it is.
>> I didn't read the whole series yet but arm spec recommends GPT but dt
>> binding should be generic enough to describe
>> also other cases.
>> We are saving this structure to qspi for example but current binding
>> can't be used for it.
> 
> I would wait to see Masami's implementation of this feature. If I am
> not wrong, his platform too is enabling this feature with a spi as the
> storage device. Maybe we can instead put a list of <device partition>
> tuples which can then list the device and partition number of the
> metadata partitions.

I think you should list all possible devices which can be used to have generic 
description for it. It is sort of the same list of devices which could be used 
for storing u-boot internal variables.
That's why the same description can be used for it too.

Thanks,
Michal



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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:38     ` Sughosh Ganu
@ 2022-02-08 11:44       ` Michal Simek
  2022-02-08 11:54         ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 11:44 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere



On 2/8/22 12:38, Sughosh Ganu wrote:
> On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
>>
>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>
>>> 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.
>>>
>>> A device tree node fwu-mdata has been added, which is used for
>>> pointing to the storage device which contains the FWU metadata. The
>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>> u-boot dtsi file.
>>>
>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>> ---
>>>
>>> Changes since V3:
>>> * Move the FWU metadata access to driver model
>>> * Get the storage device containing the metadata from a device tree
>>>    property instead of a platform helper function
>>>
>>>   arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>   .../firmware/fwu-mdata.txt                    |  18 +
>>>   drivers/Kconfig                               |   2 +
>>>   drivers/Makefile                              |   1 +
>>>   drivers/fwu-mdata/Kconfig                     |   7 +
>>>   drivers/fwu-mdata/Makefile                    |   6 +
>>>   drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>   include/dm/uclass-id.h                        |   1 +
>>>   include/fwu.h                                 |  51 ++
>>>   include/fwu_mdata.h                           |  67 +++
>>>   10 files changed, 594 insertions(+)
>>>   create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>   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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>> index 06ef3a4095..3bec6107f7 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";
>>> +               fwu-mdata-store = <&sdmmc1>;
>>> +       };
>>> +};
>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>> new file mode 100644
>>> index 0000000000..c766b595ef
>>> --- /dev/null
>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>> @@ -0,0 +1,18 @@
>>> +FWU Metadata Access Devicetree Binding
>>> +
>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>> +a separate partition for keeping information on the set of updatable
>>> +images. The device tree node provides information on the storage
>>> +device that contains the FWU metadata.
>>> +
>>> +Required properties :
>>> +
>>> +- compatible : "u-boot,fwu-mdata";
>>> +- fwu-mdata-store : should point to the storage device which contains
>>> +                   the FWU metadata partition.
>>> +
>>> +Example :
>>> +       fwu-mdata {
>>> +               compatible = "u-boot,fwu-mdata";
>>> +               fwu-mdata-store = <&sdmmc1>;
>>> +       };
>>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>>> index b26ca8cf70..adc6079ecf 100644
>>> --- a/drivers/Kconfig
>>> +++ b/drivers/Kconfig
>>> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
>>> --- a/drivers/Makefile
>>> +++ b/drivers/Makefile
>>> @@ -81,6 +81,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..7fec7171f4
>>> --- /dev/null
>>> +++ b/drivers/fwu-mdata/Makefile
>>> @@ -0,0 +1,6 @@
>>> +# SPDX-License-Identifier: GPL-2.0+
>>> +#
>>> +# 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..64b3051ecf
>>> --- /dev/null
>>> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
>>> @@ -0,0 +1,434 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Copyright (c) 2022, Linaro Limited
>>> + */
>>> +
>>> +#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;
>>> +       void *buf;
>>> +       struct fwu_mdata *mdata = NULL;
>>> +
>>> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
>>> +               log_err("Active index value to be updated is incorrect\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;
>>> +
>>> +       /*
>>> +        * 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));
>>> +
>>> +       /*
>>> +        * 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: 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;
>>> +       const struct fwu_mdata_ops *ops = NULL;
>>> +       struct udevice *dev = NULL;
>>> +
>>> +       ret = fwu_get_dev_ops(&dev, &ops);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       if (!ops->get_image_alt_num) {
>>> +               log_err("get_image_alt_num() method not defined\n");
>>> +               return -ENOSYS;
>>> +       }
>>> +
>>> +       return ops->get_image_alt_num(dev, image_type_id,
>>> +                                     update_bank, alt_num);
>>> +}
>>> +
>>> +/**
>>> + * 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;
>>> +       void *buf;
>>> +       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;
>>> +
>>> +       /*
>>> +        * 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));
>>> +
>>> +       /*
>>> +        * 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)
>>> +{
>>> +       void *buf;
>>> +       int ret, i;
>>> +       u32 nimages;
>>> +       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;
>>> +       }
>>> +
>>> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
>>> +       img_entry = &mdata->img_entry[0];
>>> +       for (i = 0; i < nimages; 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;
>>> +
>>> +                       buf = &mdata->version;
>>> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
>>> +                                            sizeof(u32));
>>> +
>>> +                       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.
>>> + *
>>> + * 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.
>>> + *
>>> + * Return: 0 if OK, -ve on error
>>> + *
>>> + */
>>> +int fwu_update_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->update_mdata) {
>>> +               log_err("get_mdata() method not defined\n");
>>> +               return -ENOSYS;
>>> +       }
>>> +
>>> +       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 0e26e1d138..d0ab1c9235 100644
>>> --- a/include/dm/uclass-id.h
>>> +++ b/include/dm/uclass-id.h
>>> @@ -54,6 +54,7 @@ enum uclass_id {
>>>          UCLASS_ETH_PHY,         /* Ethernet PHY device */
>>>          UCLASS_FIRMWARE,        /* Firmware */
>>>          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..5a99c579fc
>>> --- /dev/null
>>> +++ b/include/fwu.h
>>> @@ -0,0 +1,51 @@
>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>> +/*
>>> + * 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;
>>> +
>>> +/**
>>> + * @get_image_alt_num: get the alt number to be used for the image
>>> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
>>> +                                u32 update_bank, int *alt_num);
>>> +
>>> +       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);
>>> +
>>> +#endif /* _FWU_H_ */
>>> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
>>> new file mode 100644
>>> index 0000000000..701efbba03
>>> --- /dev/null
>>> +++ b/include/fwu_mdata.h
>>> @@ -0,0 +1,67 @@
>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>> +/*
>>> + * 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.17.1
>>>
>>
>> One more thing. run kernel-doc to validate your description.
>> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
>> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
>> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
>> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
>> fwu_get_active_index
>> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
>> fwu_update_active_index
>> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
>> fwu_get_image_alt_num
>> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
>> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
>> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
>> fwu_revert_boot_index
>> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
>> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
>> fwu_set_clear_image_accept
>> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
>> fwu_accept_image
>> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
>> fwu_clear_accept_image
>> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
>> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
>> fwu_update_mdata
>> 2 warnings
>>
>> when I run buildman over this series it is visible that it is not
>> bisectable at all.
>> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
>> much later.
>> Please make sure every single patch is bisectable.
> 
> 
> But how is this driver getting built in the first place -- the driver
> is not enabling the config symbol which would result in the code
> getting built. The idea is to add support for the driver and the
> feature, and enable the functionality in the final patch. I have added
> each patch separately and built for the qemu arm64 platform without
> any issues.

first of all I wasn't able to apply all patches because this series is not there.
https://patchwork.ozlabs.org/project/uboot/list/?series=281549
(better would be to use links to lore which are much easier to download)

That's why 2 patches weren't applied.

And I just enabled configs which land in the tree for zynqmp virt and rebase 
this patch to be the first one. That's why all the time all existing Kconfigs 
were enabled when buildman build them.
It is not that far from using the same defconfig with bisicting tree.
You can definitely avoid it in your series.

Thanks,
Michal


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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:44       ` Michal Simek
@ 2022-02-08 11:54         ` Sughosh Ganu
  2022-02-08 11:59           ` Michal Simek
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 11:54 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Tue, 8 Feb 2022 at 17:15, Michal Simek <michal.simek@xilinx.com> wrote:
>
>
>
> On 2/8/22 12:38, Sughosh Ganu wrote:
> > On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
> >>
> >> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >>>
> >>> 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.
> >>>
> >>> A device tree node fwu-mdata has been added, which is used for
> >>> pointing to the storage device which contains the FWU metadata. The
> >>> fwu-mdata node is u-boot specific, and can be added the platform's
> >>> u-boot dtsi file.
> >>>
> >>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> >>> ---
> >>>
> >>> Changes since V3:
> >>> * Move the FWU metadata access to driver model
> >>> * Get the storage device containing the metadata from a device tree
> >>>    property instead of a platform helper function
> >>>
> >>>   arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >>>   .../firmware/fwu-mdata.txt                    |  18 +
> >>>   drivers/Kconfig                               |   2 +
> >>>   drivers/Makefile                              |   1 +
> >>>   drivers/fwu-mdata/Kconfig                     |   7 +
> >>>   drivers/fwu-mdata/Makefile                    |   6 +
> >>>   drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >>>   include/dm/uclass-id.h                        |   1 +
> >>>   include/fwu.h                                 |  51 ++
> >>>   include/fwu_mdata.h                           |  67 +++
> >>>   10 files changed, 594 insertions(+)
> >>>   create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>   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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> >>> index 06ef3a4095..3bec6107f7 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";
> >>> +               fwu-mdata-store = <&sdmmc1>;
> >>> +       };
> >>> +};
> >>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>> new file mode 100644
> >>> index 0000000000..c766b595ef
> >>> --- /dev/null
> >>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>> @@ -0,0 +1,18 @@
> >>> +FWU Metadata Access Devicetree Binding
> >>> +
> >>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> >>> +a separate partition for keeping information on the set of updatable
> >>> +images. The device tree node provides information on the storage
> >>> +device that contains the FWU metadata.
> >>> +
> >>> +Required properties :
> >>> +
> >>> +- compatible : "u-boot,fwu-mdata";
> >>> +- fwu-mdata-store : should point to the storage device which contains
> >>> +                   the FWU metadata partition.
> >>> +
> >>> +Example :
> >>> +       fwu-mdata {
> >>> +               compatible = "u-boot,fwu-mdata";
> >>> +               fwu-mdata-store = <&sdmmc1>;
> >>> +       };
> >>> diff --git a/drivers/Kconfig b/drivers/Kconfig
> >>> index b26ca8cf70..adc6079ecf 100644
> >>> --- a/drivers/Kconfig
> >>> +++ b/drivers/Kconfig
> >>> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
> >>> --- a/drivers/Makefile
> >>> +++ b/drivers/Makefile
> >>> @@ -81,6 +81,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..7fec7171f4
> >>> --- /dev/null
> >>> +++ b/drivers/fwu-mdata/Makefile
> >>> @@ -0,0 +1,6 @@
> >>> +# SPDX-License-Identifier: GPL-2.0+
> >>> +#
> >>> +# 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..64b3051ecf
> >>> --- /dev/null
> >>> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> >>> @@ -0,0 +1,434 @@
> >>> +// SPDX-License-Identifier: GPL-2.0+
> >>> +/*
> >>> + * Copyright (c) 2022, Linaro Limited
> >>> + */
> >>> +
> >>> +#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;
> >>> +       void *buf;
> >>> +       struct fwu_mdata *mdata = NULL;
> >>> +
> >>> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> >>> +               log_err("Active index value to be updated is incorrect\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;
> >>> +
> >>> +       /*
> >>> +        * 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));
> >>> +
> >>> +       /*
> >>> +        * 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: 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;
> >>> +       const struct fwu_mdata_ops *ops = NULL;
> >>> +       struct udevice *dev = NULL;
> >>> +
> >>> +       ret = fwu_get_dev_ops(&dev, &ops);
> >>> +       if (ret)
> >>> +               return ret;
> >>> +
> >>> +       if (!ops->get_image_alt_num) {
> >>> +               log_err("get_image_alt_num() method not defined\n");
> >>> +               return -ENOSYS;
> >>> +       }
> >>> +
> >>> +       return ops->get_image_alt_num(dev, image_type_id,
> >>> +                                     update_bank, alt_num);
> >>> +}
> >>> +
> >>> +/**
> >>> + * 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;
> >>> +       void *buf;
> >>> +       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;
> >>> +
> >>> +       /*
> >>> +        * 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));
> >>> +
> >>> +       /*
> >>> +        * 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)
> >>> +{
> >>> +       void *buf;
> >>> +       int ret, i;
> >>> +       u32 nimages;
> >>> +       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;
> >>> +       }
> >>> +
> >>> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> >>> +       img_entry = &mdata->img_entry[0];
> >>> +       for (i = 0; i < nimages; 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;
> >>> +
> >>> +                       buf = &mdata->version;
> >>> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
> >>> +                                            sizeof(u32));
> >>> +
> >>> +                       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.
> >>> + *
> >>> + * 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.
> >>> + *
> >>> + * Return: 0 if OK, -ve on error
> >>> + *
> >>> + */
> >>> +int fwu_update_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->update_mdata) {
> >>> +               log_err("get_mdata() method not defined\n");
> >>> +               return -ENOSYS;
> >>> +       }
> >>> +
> >>> +       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 0e26e1d138..d0ab1c9235 100644
> >>> --- a/include/dm/uclass-id.h
> >>> +++ b/include/dm/uclass-id.h
> >>> @@ -54,6 +54,7 @@ enum uclass_id {
> >>>          UCLASS_ETH_PHY,         /* Ethernet PHY device */
> >>>          UCLASS_FIRMWARE,        /* Firmware */
> >>>          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..5a99c579fc
> >>> --- /dev/null
> >>> +++ b/include/fwu.h
> >>> @@ -0,0 +1,51 @@
> >>> +/* SPDX-License-Identifier: GPL-2.0+ */
> >>> +/*
> >>> + * 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;
> >>> +
> >>> +/**
> >>> + * @get_image_alt_num: get the alt number to be used for the image
> >>> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
> >>> +                                u32 update_bank, int *alt_num);
> >>> +
> >>> +       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);
> >>> +
> >>> +#endif /* _FWU_H_ */
> >>> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> >>> new file mode 100644
> >>> index 0000000000..701efbba03
> >>> --- /dev/null
> >>> +++ b/include/fwu_mdata.h
> >>> @@ -0,0 +1,67 @@
> >>> +/* SPDX-License-Identifier: GPL-2.0+ */
> >>> +/*
> >>> + * 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.17.1
> >>>
> >>
> >> One more thing. run kernel-doc to validate your description.
> >> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
> >> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
> >> fwu_get_active_index
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
> >> fwu_update_active_index
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
> >> fwu_get_image_alt_num
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
> >> fwu_revert_boot_index
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
> >> fwu_set_clear_image_accept
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
> >> fwu_accept_image
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
> >> fwu_clear_accept_image
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
> >> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
> >> fwu_update_mdata
> >> 2 warnings
> >>
> >> when I run buildman over this series it is visible that it is not
> >> bisectable at all.
> >> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
> >> much later.
> >> Please make sure every single patch is bisectable.
> >
> >
> > But how is this driver getting built in the first place -- the driver
> > is not enabling the config symbol which would result in the code
> > getting built. The idea is to add support for the driver and the
> > feature, and enable the functionality in the final patch. I have added
> > each patch separately and built for the qemu arm64 platform without
> > any issues.
>
> first of all I wasn't able to apply all patches because this series is not there.
> https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> (better would be to use links to lore which are much easier to download)

You can download the mkeficapsule series from linaro's patchwork[1].
>
> That's why 2 patches weren't applied.
>
> And I just enabled configs which land in the tree for zynqmp virt and rebase
> this patch to be the first one. That's why all the time all existing Kconfigs
> were enabled when buildman build them.

Okay my understanding of a patch being bisectable was if the build
does not break after applying a patch. Please note that on top of my
series, you will need to define CONFIG_FWU_NUM_BANKS and
CONFIG_FWU_NUM_IMAGES_PER_BANK. I did not define that on purpose since
each platform would have it's own specific values.

-sughosh

[1] - https://patches.linaro.org/project/u-boot/list/?series=166236


> It is not that far from using the same defconfig with bisicting tree.
> You can definitely avoid it in your series.
>
> Thanks,
> Michal
>

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:54         ` Sughosh Ganu
@ 2022-02-08 11:59           ` Michal Simek
  2022-02-08 12:07             ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 11:59 UTC (permalink / raw)
  To: Sughosh Ganu, Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere



On 2/8/22 12:54, Sughosh Ganu wrote:
> On Tue, 8 Feb 2022 at 17:15, Michal Simek <michal.simek@xilinx.com> wrote:
>>
>>
>>
>> On 2/8/22 12:38, Sughosh Ganu wrote:
>>> On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
>>>>
>>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>>>
>>>>> 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.
>>>>>
>>>>> A device tree node fwu-mdata has been added, which is used for
>>>>> pointing to the storage device which contains the FWU metadata. The
>>>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>>>> u-boot dtsi file.
>>>>>
>>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>>>> ---
>>>>>
>>>>> Changes since V3:
>>>>> * Move the FWU metadata access to driver model
>>>>> * Get the storage device containing the metadata from a device tree
>>>>>     property instead of a platform helper function
>>>>>
>>>>>    arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>>>    .../firmware/fwu-mdata.txt                    |  18 +
>>>>>    drivers/Kconfig                               |   2 +
>>>>>    drivers/Makefile                              |   1 +
>>>>>    drivers/fwu-mdata/Kconfig                     |   7 +
>>>>>    drivers/fwu-mdata/Makefile                    |   6 +
>>>>>    drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>>>    include/dm/uclass-id.h                        |   1 +
>>>>>    include/fwu.h                                 |  51 ++
>>>>>    include/fwu_mdata.h                           |  67 +++
>>>>>    10 files changed, 594 insertions(+)
>>>>>    create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>    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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>>>> index 06ef3a4095..3bec6107f7 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";
>>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>>> +       };
>>>>> +};
>>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>> new file mode 100644
>>>>> index 0000000000..c766b595ef
>>>>> --- /dev/null
>>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>> @@ -0,0 +1,18 @@
>>>>> +FWU Metadata Access Devicetree Binding
>>>>> +
>>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>>>> +a separate partition for keeping information on the set of updatable
>>>>> +images. The device tree node provides information on the storage
>>>>> +device that contains the FWU metadata.
>>>>> +
>>>>> +Required properties :
>>>>> +
>>>>> +- compatible : "u-boot,fwu-mdata";
>>>>> +- fwu-mdata-store : should point to the storage device which contains
>>>>> +                   the FWU metadata partition.
>>>>> +
>>>>> +Example :
>>>>> +       fwu-mdata {
>>>>> +               compatible = "u-boot,fwu-mdata";
>>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>>> +       };
>>>>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>>>>> index b26ca8cf70..adc6079ecf 100644
>>>>> --- a/drivers/Kconfig
>>>>> +++ b/drivers/Kconfig
>>>>> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
>>>>> --- a/drivers/Makefile
>>>>> +++ b/drivers/Makefile
>>>>> @@ -81,6 +81,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..7fec7171f4
>>>>> --- /dev/null
>>>>> +++ b/drivers/fwu-mdata/Makefile
>>>>> @@ -0,0 +1,6 @@
>>>>> +# SPDX-License-Identifier: GPL-2.0+
>>>>> +#
>>>>> +# 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..64b3051ecf
>>>>> --- /dev/null
>>>>> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
>>>>> @@ -0,0 +1,434 @@
>>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>>> +/*
>>>>> + * Copyright (c) 2022, Linaro Limited
>>>>> + */
>>>>> +
>>>>> +#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;
>>>>> +       void *buf;
>>>>> +       struct fwu_mdata *mdata = NULL;
>>>>> +
>>>>> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
>>>>> +               log_err("Active index value to be updated is incorrect\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;
>>>>> +
>>>>> +       /*
>>>>> +        * 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));
>>>>> +
>>>>> +       /*
>>>>> +        * 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: 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;
>>>>> +       const struct fwu_mdata_ops *ops = NULL;
>>>>> +       struct udevice *dev = NULL;
>>>>> +
>>>>> +       ret = fwu_get_dev_ops(&dev, &ops);
>>>>> +       if (ret)
>>>>> +               return ret;
>>>>> +
>>>>> +       if (!ops->get_image_alt_num) {
>>>>> +               log_err("get_image_alt_num() method not defined\n");
>>>>> +               return -ENOSYS;
>>>>> +       }
>>>>> +
>>>>> +       return ops->get_image_alt_num(dev, image_type_id,
>>>>> +                                     update_bank, alt_num);
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * 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;
>>>>> +       void *buf;
>>>>> +       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;
>>>>> +
>>>>> +       /*
>>>>> +        * 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));
>>>>> +
>>>>> +       /*
>>>>> +        * 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)
>>>>> +{
>>>>> +       void *buf;
>>>>> +       int ret, i;
>>>>> +       u32 nimages;
>>>>> +       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;
>>>>> +       }
>>>>> +
>>>>> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
>>>>> +       img_entry = &mdata->img_entry[0];
>>>>> +       for (i = 0; i < nimages; 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;
>>>>> +
>>>>> +                       buf = &mdata->version;
>>>>> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
>>>>> +                                            sizeof(u32));
>>>>> +
>>>>> +                       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.
>>>>> + *
>>>>> + * 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.
>>>>> + *
>>>>> + * Return: 0 if OK, -ve on error
>>>>> + *
>>>>> + */
>>>>> +int fwu_update_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->update_mdata) {
>>>>> +               log_err("get_mdata() method not defined\n");
>>>>> +               return -ENOSYS;
>>>>> +       }
>>>>> +
>>>>> +       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 0e26e1d138..d0ab1c9235 100644
>>>>> --- a/include/dm/uclass-id.h
>>>>> +++ b/include/dm/uclass-id.h
>>>>> @@ -54,6 +54,7 @@ enum uclass_id {
>>>>>           UCLASS_ETH_PHY,         /* Ethernet PHY device */
>>>>>           UCLASS_FIRMWARE,        /* Firmware */
>>>>>           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..5a99c579fc
>>>>> --- /dev/null
>>>>> +++ b/include/fwu.h
>>>>> @@ -0,0 +1,51 @@
>>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>>>> +/*
>>>>> + * 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;
>>>>> +
>>>>> +/**
>>>>> + * @get_image_alt_num: get the alt number to be used for the image
>>>>> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
>>>>> +                                u32 update_bank, int *alt_num);
>>>>> +
>>>>> +       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);
>>>>> +
>>>>> +#endif /* _FWU_H_ */
>>>>> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
>>>>> new file mode 100644
>>>>> index 0000000000..701efbba03
>>>>> --- /dev/null
>>>>> +++ b/include/fwu_mdata.h
>>>>> @@ -0,0 +1,67 @@
>>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>>>> +/*
>>>>> + * 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.17.1
>>>>>
>>>>
>>>> One more thing. run kernel-doc to validate your description.
>>>> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
>>>> fwu_get_active_index
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
>>>> fwu_update_active_index
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
>>>> fwu_get_image_alt_num
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
>>>> fwu_revert_boot_index
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
>>>> fwu_set_clear_image_accept
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
>>>> fwu_accept_image
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
>>>> fwu_clear_accept_image
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
>>>> fwu_update_mdata
>>>> 2 warnings
>>>>
>>>> when I run buildman over this series it is visible that it is not
>>>> bisectable at all.
>>>> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
>>>> much later.
>>>> Please make sure every single patch is bisectable.
>>>
>>>
>>> But how is this driver getting built in the first place -- the driver
>>> is not enabling the config symbol which would result in the code
>>> getting built. The idea is to add support for the driver and the
>>> feature, and enable the functionality in the final patch. I have added
>>> each patch separately and built for the qemu arm64 platform without
>>> any issues.
>>
>> first of all I wasn't able to apply all patches because this series is not there.
>> https://patchwork.ozlabs.org/project/uboot/list/?series=281549
>> (better would be to use links to lore which are much easier to download)
> 
> You can download the mkeficapsule series from linaro's patchwork[1].

you depend on 3 series. Much easier is to create a branch and push it somewhere.

>>
>> That's why 2 patches weren't applied.
>>
>> And I just enabled configs which land in the tree for zynqmp virt and rebase
>> this patch to be the first one. That's why all the time all existing Kconfigs
>> were enabled when buildman build them.
> 
> Okay my understanding of a patch being bisectable was if the build
> does not break after applying a patch. Please note that on top of my
> series, you will need to define CONFIG_FWU_NUM_BANKS and
> CONFIG_FWU_NUM_IMAGES_PER_BANK. I did not define that on purpose since
> each platform would have it's own specific values.

Even if this is true you can't use in any patch a macro/value which is not 
defined and it is not clear what it is. I apply patch 1 and review patch 1 and 
not looking at patch 8 to get what that values are for.

Define them as reasonable default for common case or your usecase. Platform can 
set them up when they adopt this approach and they are not happy with your defaults.

Thanks,
Michal



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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:59           ` Michal Simek
@ 2022-02-08 12:07             ` Sughosh Ganu
  2022-02-08 12:14               ` Michal Simek
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 12:07 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Tue, 8 Feb 2022 at 17:29, Michal Simek <michal.simek@xilinx.com> wrote:
>
>
>
> On 2/8/22 12:54, Sughosh Ganu wrote:
> > On Tue, 8 Feb 2022 at 17:15, Michal Simek <michal.simek@xilinx.com> wrote:
> >>
> >>
> >>
> >> On 2/8/22 12:38, Sughosh Ganu wrote:
> >>> On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
> >>>>
> >>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >>>>>
> >>>>> 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.
> >>>>>
> >>>>> A device tree node fwu-mdata has been added, which is used for
> >>>>> pointing to the storage device which contains the FWU metadata. The
> >>>>> fwu-mdata node is u-boot specific, and can be added the platform's
> >>>>> u-boot dtsi file.
> >>>>>
> >>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> >>>>> ---
> >>>>>
> >>>>> Changes since V3:
> >>>>> * Move the FWU metadata access to driver model
> >>>>> * Get the storage device containing the metadata from a device tree
> >>>>>     property instead of a platform helper function
> >>>>>
> >>>>>    arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >>>>>    .../firmware/fwu-mdata.txt                    |  18 +
> >>>>>    drivers/Kconfig                               |   2 +
> >>>>>    drivers/Makefile                              |   1 +
> >>>>>    drivers/fwu-mdata/Kconfig                     |   7 +
> >>>>>    drivers/fwu-mdata/Makefile                    |   6 +
> >>>>>    drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >>>>>    include/dm/uclass-id.h                        |   1 +
> >>>>>    include/fwu.h                                 |  51 ++
> >>>>>    include/fwu_mdata.h                           |  67 +++
> >>>>>    10 files changed, 594 insertions(+)
> >>>>>    create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>    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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> >>>>> index 06ef3a4095..3bec6107f7 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";
> >>>>> +               fwu-mdata-store = <&sdmmc1>;
> >>>>> +       };
> >>>>> +};
> >>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>> new file mode 100644
> >>>>> index 0000000000..c766b595ef
> >>>>> --- /dev/null
> >>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>> @@ -0,0 +1,18 @@
> >>>>> +FWU Metadata Access Devicetree Binding
> >>>>> +
> >>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> >>>>> +a separate partition for keeping information on the set of updatable
> >>>>> +images. The device tree node provides information on the storage
> >>>>> +device that contains the FWU metadata.
> >>>>> +
> >>>>> +Required properties :
> >>>>> +
> >>>>> +- compatible : "u-boot,fwu-mdata";
> >>>>> +- fwu-mdata-store : should point to the storage device which contains
> >>>>> +                   the FWU metadata partition.
> >>>>> +
> >>>>> +Example :
> >>>>> +       fwu-mdata {
> >>>>> +               compatible = "u-boot,fwu-mdata";
> >>>>> +               fwu-mdata-store = <&sdmmc1>;
> >>>>> +       };
> >>>>> diff --git a/drivers/Kconfig b/drivers/Kconfig
> >>>>> index b26ca8cf70..adc6079ecf 100644
> >>>>> --- a/drivers/Kconfig
> >>>>> +++ b/drivers/Kconfig
> >>>>> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
> >>>>> --- a/drivers/Makefile
> >>>>> +++ b/drivers/Makefile
> >>>>> @@ -81,6 +81,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..7fec7171f4
> >>>>> --- /dev/null
> >>>>> +++ b/drivers/fwu-mdata/Makefile
> >>>>> @@ -0,0 +1,6 @@
> >>>>> +# SPDX-License-Identifier: GPL-2.0+
> >>>>> +#
> >>>>> +# 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..64b3051ecf
> >>>>> --- /dev/null
> >>>>> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> >>>>> @@ -0,0 +1,434 @@
> >>>>> +// SPDX-License-Identifier: GPL-2.0+
> >>>>> +/*
> >>>>> + * Copyright (c) 2022, Linaro Limited
> >>>>> + */
> >>>>> +
> >>>>> +#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;
> >>>>> +       void *buf;
> >>>>> +       struct fwu_mdata *mdata = NULL;
> >>>>> +
> >>>>> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> >>>>> +               log_err("Active index value to be updated is incorrect\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;
> >>>>> +
> >>>>> +       /*
> >>>>> +        * 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));
> >>>>> +
> >>>>> +       /*
> >>>>> +        * 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: 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;
> >>>>> +       const struct fwu_mdata_ops *ops = NULL;
> >>>>> +       struct udevice *dev = NULL;
> >>>>> +
> >>>>> +       ret = fwu_get_dev_ops(&dev, &ops);
> >>>>> +       if (ret)
> >>>>> +               return ret;
> >>>>> +
> >>>>> +       if (!ops->get_image_alt_num) {
> >>>>> +               log_err("get_image_alt_num() method not defined\n");
> >>>>> +               return -ENOSYS;
> >>>>> +       }
> >>>>> +
> >>>>> +       return ops->get_image_alt_num(dev, image_type_id,
> >>>>> +                                     update_bank, alt_num);
> >>>>> +}
> >>>>> +
> >>>>> +/**
> >>>>> + * 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;
> >>>>> +       void *buf;
> >>>>> +       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;
> >>>>> +
> >>>>> +       /*
> >>>>> +        * 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));
> >>>>> +
> >>>>> +       /*
> >>>>> +        * 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)
> >>>>> +{
> >>>>> +       void *buf;
> >>>>> +       int ret, i;
> >>>>> +       u32 nimages;
> >>>>> +       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;
> >>>>> +       }
> >>>>> +
> >>>>> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> >>>>> +       img_entry = &mdata->img_entry[0];
> >>>>> +       for (i = 0; i < nimages; 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;
> >>>>> +
> >>>>> +                       buf = &mdata->version;
> >>>>> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
> >>>>> +                                            sizeof(u32));
> >>>>> +
> >>>>> +                       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.
> >>>>> + *
> >>>>> + * 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.
> >>>>> + *
> >>>>> + * Return: 0 if OK, -ve on error
> >>>>> + *
> >>>>> + */
> >>>>> +int fwu_update_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->update_mdata) {
> >>>>> +               log_err("get_mdata() method not defined\n");
> >>>>> +               return -ENOSYS;
> >>>>> +       }
> >>>>> +
> >>>>> +       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 0e26e1d138..d0ab1c9235 100644
> >>>>> --- a/include/dm/uclass-id.h
> >>>>> +++ b/include/dm/uclass-id.h
> >>>>> @@ -54,6 +54,7 @@ enum uclass_id {
> >>>>>           UCLASS_ETH_PHY,         /* Ethernet PHY device */
> >>>>>           UCLASS_FIRMWARE,        /* Firmware */
> >>>>>           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..5a99c579fc
> >>>>> --- /dev/null
> >>>>> +++ b/include/fwu.h
> >>>>> @@ -0,0 +1,51 @@
> >>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
> >>>>> +/*
> >>>>> + * 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;
> >>>>> +
> >>>>> +/**
> >>>>> + * @get_image_alt_num: get the alt number to be used for the image
> >>>>> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
> >>>>> +                                u32 update_bank, int *alt_num);
> >>>>> +
> >>>>> +       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);
> >>>>> +
> >>>>> +#endif /* _FWU_H_ */
> >>>>> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> >>>>> new file mode 100644
> >>>>> index 0000000000..701efbba03
> >>>>> --- /dev/null
> >>>>> +++ b/include/fwu_mdata.h
> >>>>> @@ -0,0 +1,67 @@
> >>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
> >>>>> +/*
> >>>>> + * 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.17.1
> >>>>>
> >>>>
> >>>> One more thing. run kernel-doc to validate your description.
> >>>> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
> >>>> fwu_get_active_index
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
> >>>> fwu_update_active_index
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
> >>>> fwu_get_image_alt_num
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
> >>>> fwu_revert_boot_index
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
> >>>> fwu_set_clear_image_accept
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
> >>>> fwu_accept_image
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
> >>>> fwu_clear_accept_image
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
> >>>> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
> >>>> fwu_update_mdata
> >>>> 2 warnings
> >>>>
> >>>> when I run buildman over this series it is visible that it is not
> >>>> bisectable at all.
> >>>> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
> >>>> much later.
> >>>> Please make sure every single patch is bisectable.
> >>>
> >>>
> >>> But how is this driver getting built in the first place -- the driver
> >>> is not enabling the config symbol which would result in the code
> >>> getting built. The idea is to add support for the driver and the
> >>> feature, and enable the functionality in the final patch. I have added
> >>> each patch separately and built for the qemu arm64 platform without
> >>> any issues.
> >>
> >> first of all I wasn't able to apply all patches because this series is not there.
> >> https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> >> (better would be to use links to lore which are much easier to download)
> >
> > You can download the mkeficapsule series from linaro's patchwork[1].
>
> you depend on 3 series. Much easier is to create a branch and push it somewhere.
>
> >>
> >> That's why 2 patches weren't applied.
> >>
> >> And I just enabled configs which land in the tree for zynqmp virt and rebase
> >> this patch to be the first one. That's why all the time all existing Kconfigs
> >> were enabled when buildman build them.
> >
> > Okay my understanding of a patch being bisectable was if the build
> > does not break after applying a patch. Please note that on top of my
> > series, you will need to define CONFIG_FWU_NUM_BANKS and
> > CONFIG_FWU_NUM_IMAGES_PER_BANK. I did not define that on purpose since
> > each platform would have it's own specific values.
>
> Even if this is true you can't use in any patch a macro/value which is not
> defined and it is not clear what it is. I apply patch 1 and review patch 1 and
> not looking at patch 8 to get what that values are for.

My point was that I have not defined these values at all. These will
have to be defined on a per platform level. But if you insist, I will
define default values, but in my opinion it is better to get a build
failure and then set correct values, rather than the build going
through with some values which are incorrect for the platform.

If you apply the patches as they are, they should not result in any
build failures.

-sughosh

>
> Define them as reasonable default for common case or your usecase. Platform can
> set them up when they adopt this approach and they are not happy with your defaults.
>
> Thanks,
> Michal
>
>

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

* Re: [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature
  2022-02-08 11:05 ` [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Michal Simek
@ 2022-02-08 12:09   ` Sughosh Ganu
  0 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 12:09 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Tue, 8 Feb 2022 at 16:36, Michal Simek <monstr@monstr.eu> wrote:
>
> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >
> >
> >
> > 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
> > board which boots a FIP image from a uSD card partitioned with the GPT
> > partioning scheme. This also requires changes in the previous stage of
> > bootloader, which parses the metadata and selects the bank to boot the
> > image(s) from. Support is 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's integration branch[3].
> >
> > These patches are based on top of the series from Takahiro to add
> > Authentication support to mkeficapsule utility[4] and a couple of
> > other patches[5][6]
> >
> > TODO's
> > ------
> > * Add a unit test case for the newly added FWU_MDATA uclass. Some
> >   involved effort is needed on this since the host device interface on
> >   sandbox cannot be used with the UT framework.
> > * Add test case for the feature with the python test suite, along the
> >   lines of capsule update testing.
> >
> > [1] - https://developer.arm.com/documentation/den0118/a
> > [2] - https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf
> > [3] - https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/log/?h=integration
> > [4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> > [5] - https://patchwork.ozlabs.org/project/uboot/patch/164388019634.446835.18271480521485569016.stgit@localhost/
> > [6] - https://patchwork.ozlabs.org/project/uboot/patch/20220129192108.6618-1-sughosh.ganu@linaro.org/
> >
> >
> > Changes since V3:
> > * Move the FWU metadata access to driver model
> > * Get the storage device containing the metadata from a device tree
> >   property instead of a platform helper function
> > * Move the metadata access driver for GPT partitioned block devices
> >   under drivers/fwu-mdata/ directory, complying with driver model.
> > * Move functionality to get the active index under the common function
> >   instead of the GPT block device specific driver.
> > * Remove function for getting the storage device containing the
> >   metadata as the information is now obtained from the device tree.
> > * Define a weak function fill_image_type_guid_array for populating the
> >   image descriptor array with u-boot's raw and fit image GUIDs
> > * Define the function fill_image_type_guid_array for the ST DK2 board
> >   for GPT partitioned devices.
> > * Change the TrialStateCtr efi variable attribute to remove the
> >   runtime attribute
> > * Rebase the change on top of the patch from Masami to call
> >   efi_capsule_update_firmware directly.
> > * Put the FWU related checks which were earlier in efi_update_capsule
> >   function to separate functions fwu_empty_capsule and
> >   fwu_empty_capsule_process.
> > * Use the device model api uclass_get_device to probe and get the FWU
> >   Metadata device.
> > * Add related documentation for empty capsules in the mkeficapsule man
> >   page.
> > * Add separate usage for empty capsules, with corresponding valid
> >   options.
> > * Use ternary operators where possible.
> > * Put a exclusivity check for the empty capsule options.
> >
> >
> > Sughosh Ganu (11):
> >   FWU: Add FWU metadata structure and driver for accessing metadata
> >   FWU: Add FWU metadata access driver for GPT partitioned block devices
> >   FWU: stm32mp1: Add helper functions for accessing FWU metadata
> >   FWU: STM32MP1: Add support to read boot index from backup register
> >   EFI: FMP: Add provision to update image's ImageTypeId in image
> >     descriptor
> >   stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR
> >     array
> >   FWU: Add boot time checks as highlighted by the FWU specification
> >   FWU: Add support for FWU Multi Bank Update feature
> >   FWU: cmd: Add a command to read FWU metadata
> >   mkeficapsule: Add support for generating empty capsules
> >   FWU: doc: Add documentation for the FWU feature
> >
> >  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >  board/st/stm32mp1/stm32mp1.c                  | 178 +++++++
> >  cmd/Kconfig                                   |   7 +
> >  cmd/Makefile                                  |   1 +
> >  cmd/fwu_mdata.c                               |  74 +++
> >  common/board_r.c                              |   6 +
> >  doc/develop/uefi/fwu_updates.rst              | 142 +++++
> >  doc/develop/uefi/index.rst                    |   1 +
> >  doc/develop/uefi/uefi.rst                     |   2 +
> >  .../firmware/fwu-mdata.txt                    |  18 +
> >  doc/mkeficapsule.1                            |  23 +-
> >  drivers/Kconfig                               |   2 +
> >  drivers/Makefile                              |   1 +
> >  drivers/fwu-mdata/Kconfig                     |  16 +
> >  drivers/fwu-mdata/Makefile                    |   7 +
> >  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 +++++++++++++++
> >  drivers/fwu-mdata/fwu_mdata_gpt_blk.c         | 501 ++++++++++++++++++
> >  include/dm/uclass-id.h                        |   1 +
> >  include/efi_loader.h                          |   2 +
> >  include/fwu.h                                 |  70 +++
> >  include/fwu_mdata.h                           |  67 +++
> >  lib/Kconfig                                   |   6 +
> >  lib/Makefile                                  |   1 +
> >  lib/efi_loader/efi_capsule.c                  | 221 +++++++-
> >  lib/efi_loader/efi_firmware.c                 |  71 ++-
> >  lib/efi_loader/efi_setup.c                    |   3 +-
> >  lib/fwu_updates/Kconfig                       |  31 ++
> >  lib/fwu_updates/Makefile                      |   6 +
> >  lib/fwu_updates/fwu.c                         | 204 +++++++
> >  tools/eficapsule.h                            |   8 +
> >  tools/mkeficapsule.c                          | 131 ++++-
> >  31 files changed, 2208 insertions(+), 34 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.txt
> >  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
> >
> > --
> > 2.17.1
> >
> >
>
> What's the git base you use for this series?

You can clone my linaro git repo branch[1] to get the entire series.

-sughosh

[1] - https://git.linaro.org/people/sughosh.ganu/u-boot.git/log/?h=non_rfc_v1_mdata_dm
>
> Thanks,
> Michal
>
> --
> Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
> w: www.monstr.eu p: +42-0-721842854
> Maintainer of Linux kernel - Xilinx Microblaze
> Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
> U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 12:07             ` Sughosh Ganu
@ 2022-02-08 12:14               ` Michal Simek
  2022-02-08 12:49                 ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 12:14 UTC (permalink / raw)
  To: Sughosh Ganu, Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere



On 2/8/22 13:07, Sughosh Ganu wrote:
> On Tue, 8 Feb 2022 at 17:29, Michal Simek <michal.simek@xilinx.com> wrote:
>>
>>
>>
>> On 2/8/22 12:54, Sughosh Ganu wrote:
>>> On Tue, 8 Feb 2022 at 17:15, Michal Simek <michal.simek@xilinx.com> wrote:
>>>>
>>>>
>>>>
>>>> On 2/8/22 12:38, Sughosh Ganu wrote:
>>>>> On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
>>>>>>
>>>>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>>>>>
>>>>>>> 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.
>>>>>>>
>>>>>>> A device tree node fwu-mdata has been added, which is used for
>>>>>>> pointing to the storage device which contains the FWU metadata. The
>>>>>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>>>>>> u-boot dtsi file.
>>>>>>>
>>>>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>>>>>> ---
>>>>>>>
>>>>>>> Changes since V3:
>>>>>>> * Move the FWU metadata access to driver model
>>>>>>> * Get the storage device containing the metadata from a device tree
>>>>>>>      property instead of a platform helper function
>>>>>>>
>>>>>>>     arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>>>>>     .../firmware/fwu-mdata.txt                    |  18 +
>>>>>>>     drivers/Kconfig                               |   2 +
>>>>>>>     drivers/Makefile                              |   1 +
>>>>>>>     drivers/fwu-mdata/Kconfig                     |   7 +
>>>>>>>     drivers/fwu-mdata/Makefile                    |   6 +
>>>>>>>     drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>>>>>     include/dm/uclass-id.h                        |   1 +
>>>>>>>     include/fwu.h                                 |  51 ++
>>>>>>>     include/fwu_mdata.h                           |  67 +++
>>>>>>>     10 files changed, 594 insertions(+)
>>>>>>>     create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>>     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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>>>>>> index 06ef3a4095..3bec6107f7 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";
>>>>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>>>>> +       };
>>>>>>> +};
>>>>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>> new file mode 100644
>>>>>>> index 0000000000..c766b595ef
>>>>>>> --- /dev/null
>>>>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>> @@ -0,0 +1,18 @@
>>>>>>> +FWU Metadata Access Devicetree Binding
>>>>>>> +
>>>>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>>>>>> +a separate partition for keeping information on the set of updatable
>>>>>>> +images. The device tree node provides information on the storage
>>>>>>> +device that contains the FWU metadata.
>>>>>>> +
>>>>>>> +Required properties :
>>>>>>> +
>>>>>>> +- compatible : "u-boot,fwu-mdata";
>>>>>>> +- fwu-mdata-store : should point to the storage device which contains
>>>>>>> +                   the FWU metadata partition.
>>>>>>> +
>>>>>>> +Example :
>>>>>>> +       fwu-mdata {
>>>>>>> +               compatible = "u-boot,fwu-mdata";
>>>>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>>>>> +       };
>>>>>>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>>>>>>> index b26ca8cf70..adc6079ecf 100644
>>>>>>> --- a/drivers/Kconfig
>>>>>>> +++ b/drivers/Kconfig
>>>>>>> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
>>>>>>> --- a/drivers/Makefile
>>>>>>> +++ b/drivers/Makefile
>>>>>>> @@ -81,6 +81,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..7fec7171f4
>>>>>>> --- /dev/null
>>>>>>> +++ b/drivers/fwu-mdata/Makefile
>>>>>>> @@ -0,0 +1,6 @@
>>>>>>> +# SPDX-License-Identifier: GPL-2.0+
>>>>>>> +#
>>>>>>> +# 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..64b3051ecf
>>>>>>> --- /dev/null
>>>>>>> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
>>>>>>> @@ -0,0 +1,434 @@
>>>>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>>>>> +/*
>>>>>>> + * Copyright (c) 2022, Linaro Limited
>>>>>>> + */
>>>>>>> +
>>>>>>> +#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;
>>>>>>> +       void *buf;
>>>>>>> +       struct fwu_mdata *mdata = NULL;
>>>>>>> +
>>>>>>> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
>>>>>>> +               log_err("Active index value to be updated is incorrect\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;
>>>>>>> +
>>>>>>> +       /*
>>>>>>> +        * 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));
>>>>>>> +
>>>>>>> +       /*
>>>>>>> +        * 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: 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;
>>>>>>> +       const struct fwu_mdata_ops *ops = NULL;
>>>>>>> +       struct udevice *dev = NULL;
>>>>>>> +
>>>>>>> +       ret = fwu_get_dev_ops(&dev, &ops);
>>>>>>> +       if (ret)
>>>>>>> +               return ret;
>>>>>>> +
>>>>>>> +       if (!ops->get_image_alt_num) {
>>>>>>> +               log_err("get_image_alt_num() method not defined\n");
>>>>>>> +               return -ENOSYS;
>>>>>>> +       }
>>>>>>> +
>>>>>>> +       return ops->get_image_alt_num(dev, image_type_id,
>>>>>>> +                                     update_bank, alt_num);
>>>>>>> +}
>>>>>>> +
>>>>>>> +/**
>>>>>>> + * 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;
>>>>>>> +       void *buf;
>>>>>>> +       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;
>>>>>>> +
>>>>>>> +       /*
>>>>>>> +        * 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));
>>>>>>> +
>>>>>>> +       /*
>>>>>>> +        * 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)
>>>>>>> +{
>>>>>>> +       void *buf;
>>>>>>> +       int ret, i;
>>>>>>> +       u32 nimages;
>>>>>>> +       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;
>>>>>>> +       }
>>>>>>> +
>>>>>>> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
>>>>>>> +       img_entry = &mdata->img_entry[0];
>>>>>>> +       for (i = 0; i < nimages; 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;
>>>>>>> +
>>>>>>> +                       buf = &mdata->version;
>>>>>>> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
>>>>>>> +                                            sizeof(u32));
>>>>>>> +
>>>>>>> +                       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.
>>>>>>> + *
>>>>>>> + * 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.
>>>>>>> + *
>>>>>>> + * Return: 0 if OK, -ve on error
>>>>>>> + *
>>>>>>> + */
>>>>>>> +int fwu_update_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->update_mdata) {
>>>>>>> +               log_err("get_mdata() method not defined\n");
>>>>>>> +               return -ENOSYS;
>>>>>>> +       }
>>>>>>> +
>>>>>>> +       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 0e26e1d138..d0ab1c9235 100644
>>>>>>> --- a/include/dm/uclass-id.h
>>>>>>> +++ b/include/dm/uclass-id.h
>>>>>>> @@ -54,6 +54,7 @@ enum uclass_id {
>>>>>>>            UCLASS_ETH_PHY,         /* Ethernet PHY device */
>>>>>>>            UCLASS_FIRMWARE,        /* Firmware */
>>>>>>>            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..5a99c579fc
>>>>>>> --- /dev/null
>>>>>>> +++ b/include/fwu.h
>>>>>>> @@ -0,0 +1,51 @@
>>>>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>>>>>> +/*
>>>>>>> + * 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;
>>>>>>> +
>>>>>>> +/**
>>>>>>> + * @get_image_alt_num: get the alt number to be used for the image
>>>>>>> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
>>>>>>> +                                u32 update_bank, int *alt_num);
>>>>>>> +
>>>>>>> +       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);
>>>>>>> +
>>>>>>> +#endif /* _FWU_H_ */
>>>>>>> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
>>>>>>> new file mode 100644
>>>>>>> index 0000000000..701efbba03
>>>>>>> --- /dev/null
>>>>>>> +++ b/include/fwu_mdata.h
>>>>>>> @@ -0,0 +1,67 @@
>>>>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
>>>>>>> +/*
>>>>>>> + * 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.17.1
>>>>>>>
>>>>>>
>>>>>> One more thing. run kernel-doc to validate your description.
>>>>>> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
>>>>>> fwu_get_active_index
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
>>>>>> fwu_update_active_index
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
>>>>>> fwu_get_image_alt_num
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
>>>>>> fwu_revert_boot_index
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
>>>>>> fwu_set_clear_image_accept
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
>>>>>> fwu_accept_image
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
>>>>>> fwu_clear_accept_image
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
>>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
>>>>>> fwu_update_mdata
>>>>>> 2 warnings
>>>>>>
>>>>>> when I run buildman over this series it is visible that it is not
>>>>>> bisectable at all.
>>>>>> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
>>>>>> much later.
>>>>>> Please make sure every single patch is bisectable.
>>>>>
>>>>>
>>>>> But how is this driver getting built in the first place -- the driver
>>>>> is not enabling the config symbol which would result in the code
>>>>> getting built. The idea is to add support for the driver and the
>>>>> feature, and enable the functionality in the final patch. I have added
>>>>> each patch separately and built for the qemu arm64 platform without
>>>>> any issues.
>>>>
>>>> first of all I wasn't able to apply all patches because this series is not there.
>>>> https://patchwork.ozlabs.org/project/uboot/list/?series=281549
>>>> (better would be to use links to lore which are much easier to download)
>>>
>>> You can download the mkeficapsule series from linaro's patchwork[1].
>>
>> you depend on 3 series. Much easier is to create a branch and push it somewhere.
>>
>>>>
>>>> That's why 2 patches weren't applied.
>>>>
>>>> And I just enabled configs which land in the tree for zynqmp virt and rebase
>>>> this patch to be the first one. That's why all the time all existing Kconfigs
>>>> were enabled when buildman build them.
>>>
>>> Okay my understanding of a patch being bisectable was if the build
>>> does not break after applying a patch. Please note that on top of my
>>> series, you will need to define CONFIG_FWU_NUM_BANKS and
>>> CONFIG_FWU_NUM_IMAGES_PER_BANK. I did not define that on purpose since
>>> each platform would have it's own specific values.
>>
>> Even if this is true you can't use in any patch a macro/value which is not
>> defined and it is not clear what it is. I apply patch 1 and review patch 1 and
>> not looking at patch 8 to get what that values are for.
> 
> My point was that I have not defined these values at all. These will
> have to be defined on a per platform level. But if you insist, I will
> define default values, but in my opinion it is better to get a build
> failure and then set correct values, rather than the build going
> through with some values which are incorrect for the platform.
> 
> If you apply the patches as they are, they should not result in any
> build failures.

This code should be enabled for at least one platform. It means I expect you 
define that values at least for one platform which you use for testing.
I don't agree that it is better to get build error. Feature will be disabled by 
default for other platforms and when developer enables it should check all these 
settings before enablement happens.

Thanks,
Michal


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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 12:14               ` Michal Simek
@ 2022-02-08 12:49                 ` Sughosh Ganu
  0 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-08 12:49 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Tue, 8 Feb 2022 at 17:44, Michal Simek <michal.simek@xilinx.com> wrote:
>
>
>
> On 2/8/22 13:07, Sughosh Ganu wrote:
> > On Tue, 8 Feb 2022 at 17:29, Michal Simek <michal.simek@xilinx.com> wrote:
> >>
> >>
> >>
> >> On 2/8/22 12:54, Sughosh Ganu wrote:
> >>> On Tue, 8 Feb 2022 at 17:15, Michal Simek <michal.simek@xilinx.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 2/8/22 12:38, Sughosh Ganu wrote:
> >>>>> On Tue, 8 Feb 2022 at 17:01, Michal Simek <monstr@monstr.eu> wrote:
> >>>>>>
> >>>>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >>>>>>>
> >>>>>>> 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.
> >>>>>>>
> >>>>>>> A device tree node fwu-mdata has been added, which is used for
> >>>>>>> pointing to the storage device which contains the FWU metadata. The
> >>>>>>> fwu-mdata node is u-boot specific, and can be added the platform's
> >>>>>>> u-boot dtsi file.
> >>>>>>>
> >>>>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> >>>>>>> ---
> >>>>>>>
> >>>>>>> Changes since V3:
> >>>>>>> * Move the FWU metadata access to driver model
> >>>>>>> * Get the storage device containing the metadata from a device tree
> >>>>>>>      property instead of a platform helper function
> >>>>>>>
> >>>>>>>     arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >>>>>>>     .../firmware/fwu-mdata.txt                    |  18 +
> >>>>>>>     drivers/Kconfig                               |   2 +
> >>>>>>>     drivers/Makefile                              |   1 +
> >>>>>>>     drivers/fwu-mdata/Kconfig                     |   7 +
> >>>>>>>     drivers/fwu-mdata/Makefile                    |   6 +
> >>>>>>>     drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >>>>>>>     include/dm/uclass-id.h                        |   1 +
> >>>>>>>     include/fwu.h                                 |  51 ++
> >>>>>>>     include/fwu_mdata.h                           |  67 +++
> >>>>>>>     10 files changed, 594 insertions(+)
> >>>>>>>     create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>>>     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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> >>>>>>> index 06ef3a4095..3bec6107f7 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";
> >>>>>>> +               fwu-mdata-store = <&sdmmc1>;
> >>>>>>> +       };
> >>>>>>> +};
> >>>>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>>> new file mode 100644
> >>>>>>> index 0000000000..c766b595ef
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>>> @@ -0,0 +1,18 @@
> >>>>>>> +FWU Metadata Access Devicetree Binding
> >>>>>>> +
> >>>>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> >>>>>>> +a separate partition for keeping information on the set of updatable
> >>>>>>> +images. The device tree node provides information on the storage
> >>>>>>> +device that contains the FWU metadata.
> >>>>>>> +
> >>>>>>> +Required properties :
> >>>>>>> +
> >>>>>>> +- compatible : "u-boot,fwu-mdata";
> >>>>>>> +- fwu-mdata-store : should point to the storage device which contains
> >>>>>>> +                   the FWU metadata partition.
> >>>>>>> +
> >>>>>>> +Example :
> >>>>>>> +       fwu-mdata {
> >>>>>>> +               compatible = "u-boot,fwu-mdata";
> >>>>>>> +               fwu-mdata-store = <&sdmmc1>;
> >>>>>>> +       };
> >>>>>>> diff --git a/drivers/Kconfig b/drivers/Kconfig
> >>>>>>> index b26ca8cf70..adc6079ecf 100644
> >>>>>>> --- a/drivers/Kconfig
> >>>>>>> +++ b/drivers/Kconfig
> >>>>>>> @@ -42,6 +42,8 @@ source "drivers/firmware/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 4e7cf28440..56f0f04874 100644
> >>>>>>> --- a/drivers/Makefile
> >>>>>>> +++ b/drivers/Makefile
> >>>>>>> @@ -81,6 +81,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..7fec7171f4
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/drivers/fwu-mdata/Makefile
> >>>>>>> @@ -0,0 +1,6 @@
> >>>>>>> +# SPDX-License-Identifier: GPL-2.0+
> >>>>>>> +#
> >>>>>>> +# 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..64b3051ecf
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/drivers/fwu-mdata/fwu-mdata-uclass.c
> >>>>>>> @@ -0,0 +1,434 @@
> >>>>>>> +// SPDX-License-Identifier: GPL-2.0+
> >>>>>>> +/*
> >>>>>>> + * Copyright (c) 2022, Linaro Limited
> >>>>>>> + */
> >>>>>>> +
> >>>>>>> +#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;
> >>>>>>> +       void *buf;
> >>>>>>> +       struct fwu_mdata *mdata = NULL;
> >>>>>>> +
> >>>>>>> +       if (active_idx > CONFIG_FWU_NUM_BANKS - 1) {
> >>>>>>> +               log_err("Active index value to be updated is incorrect\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;
> >>>>>>> +
> >>>>>>> +       /*
> >>>>>>> +        * 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));
> >>>>>>> +
> >>>>>>> +       /*
> >>>>>>> +        * 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: 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;
> >>>>>>> +       const struct fwu_mdata_ops *ops = NULL;
> >>>>>>> +       struct udevice *dev = NULL;
> >>>>>>> +
> >>>>>>> +       ret = fwu_get_dev_ops(&dev, &ops);
> >>>>>>> +       if (ret)
> >>>>>>> +               return ret;
> >>>>>>> +
> >>>>>>> +       if (!ops->get_image_alt_num) {
> >>>>>>> +               log_err("get_image_alt_num() method not defined\n");
> >>>>>>> +               return -ENOSYS;
> >>>>>>> +       }
> >>>>>>> +
> >>>>>>> +       return ops->get_image_alt_num(dev, image_type_id,
> >>>>>>> +                                     update_bank, alt_num);
> >>>>>>> +}
> >>>>>>> +
> >>>>>>> +/**
> >>>>>>> + * 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;
> >>>>>>> +       void *buf;
> >>>>>>> +       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;
> >>>>>>> +
> >>>>>>> +       /*
> >>>>>>> +        * 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));
> >>>>>>> +
> >>>>>>> +       /*
> >>>>>>> +        * 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)
> >>>>>>> +{
> >>>>>>> +       void *buf;
> >>>>>>> +       int ret, i;
> >>>>>>> +       u32 nimages;
> >>>>>>> +       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;
> >>>>>>> +       }
> >>>>>>> +
> >>>>>>> +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> >>>>>>> +       img_entry = &mdata->img_entry[0];
> >>>>>>> +       for (i = 0; i < nimages; 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;
> >>>>>>> +
> >>>>>>> +                       buf = &mdata->version;
> >>>>>>> +                       mdata->crc32 = crc32(0, buf, sizeof(*mdata) -
> >>>>>>> +                                            sizeof(u32));
> >>>>>>> +
> >>>>>>> +                       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.
> >>>>>>> + *
> >>>>>>> + * 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.
> >>>>>>> + *
> >>>>>>> + * Return: 0 if OK, -ve on error
> >>>>>>> + *
> >>>>>>> + */
> >>>>>>> +int fwu_update_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->update_mdata) {
> >>>>>>> +               log_err("get_mdata() method not defined\n");
> >>>>>>> +               return -ENOSYS;
> >>>>>>> +       }
> >>>>>>> +
> >>>>>>> +       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 0e26e1d138..d0ab1c9235 100644
> >>>>>>> --- a/include/dm/uclass-id.h
> >>>>>>> +++ b/include/dm/uclass-id.h
> >>>>>>> @@ -54,6 +54,7 @@ enum uclass_id {
> >>>>>>>            UCLASS_ETH_PHY,         /* Ethernet PHY device */
> >>>>>>>            UCLASS_FIRMWARE,        /* Firmware */
> >>>>>>>            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..5a99c579fc
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/include/fwu.h
> >>>>>>> @@ -0,0 +1,51 @@
> >>>>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
> >>>>>>> +/*
> >>>>>>> + * 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;
> >>>>>>> +
> >>>>>>> +/**
> >>>>>>> + * @get_image_alt_num: get the alt number to be used for the image
> >>>>>>> + * @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 (*get_image_alt_num)(struct udevice *dev, efi_guid_t image_type_id,
> >>>>>>> +                                u32 update_bank, int *alt_num);
> >>>>>>> +
> >>>>>>> +       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);
> >>>>>>> +
> >>>>>>> +#endif /* _FWU_H_ */
> >>>>>>> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> >>>>>>> new file mode 100644
> >>>>>>> index 0000000000..701efbba03
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/include/fwu_mdata.h
> >>>>>>> @@ -0,0 +1,67 @@
> >>>>>>> +/* SPDX-License-Identifier: GPL-2.0+ */
> >>>>>>> +/*
> >>>>>>> + * 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.17.1
> >>>>>>>
> >>>>>>
> >>>>>> One more thing. run kernel-doc to validate your description.
> >>>>>> [u-boot](eeee)$ ./scripts/kernel-doc -v -man
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c 1>/dev/null
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:41: info: Scanning doc for fwu_verify_mdata
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:70: info: Scanning doc for
> >>>>>> fwu_get_active_index
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:107: info: Scanning doc for
> >>>>>> fwu_update_active_index
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:164: info: Scanning doc for
> >>>>>> fwu_get_image_alt_num
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:197: info: Scanning doc for fwu_mdata_check
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:202: warning: contents before sections
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:224: info: Scanning doc for
> >>>>>> fwu_revert_boot_index
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:230: warning: contents before sections
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:279: info: Scanning doc for
> >>>>>> fwu_set_clear_image_accept
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:338: info: Scanning doc for
> >>>>>> fwu_accept_image
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:357: info: Scanning doc for
> >>>>>> fwu_clear_accept_image
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:377: info: Scanning doc for fwu_get_mdata
> >>>>>> drivers/fwu-mdata/fwu-mdata-uclass.c:404: info: Scanning doc for
> >>>>>> fwu_update_mdata
> >>>>>> 2 warnings
> >>>>>>
> >>>>>> when I run buildman over this series it is visible that it is not
> >>>>>> bisectable at all.
> >>>>>> CONFIG_FWU_NUM_BANKS is defined in this patch but the symbol is added
> >>>>>> much later.
> >>>>>> Please make sure every single patch is bisectable.
> >>>>>
> >>>>>
> >>>>> But how is this driver getting built in the first place -- the driver
> >>>>> is not enabling the config symbol which would result in the code
> >>>>> getting built. The idea is to add support for the driver and the
> >>>>> feature, and enable the functionality in the final patch. I have added
> >>>>> each patch separately and built for the qemu arm64 platform without
> >>>>> any issues.
> >>>>
> >>>> first of all I wasn't able to apply all patches because this series is not there.
> >>>> https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> >>>> (better would be to use links to lore which are much easier to download)
> >>>
> >>> You can download the mkeficapsule series from linaro's patchwork[1].
> >>
> >> you depend on 3 series. Much easier is to create a branch and push it somewhere.
> >>
> >>>>
> >>>> That's why 2 patches weren't applied.
> >>>>
> >>>> And I just enabled configs which land in the tree for zynqmp virt and rebase
> >>>> this patch to be the first one. That's why all the time all existing Kconfigs
> >>>> were enabled when buildman build them.
> >>>
> >>> Okay my understanding of a patch being bisectable was if the build
> >>> does not break after applying a patch. Please note that on top of my
> >>> series, you will need to define CONFIG_FWU_NUM_BANKS and
> >>> CONFIG_FWU_NUM_IMAGES_PER_BANK. I did not define that on purpose since
> >>> each platform would have it's own specific values.
> >>
> >> Even if this is true you can't use in any patch a macro/value which is not
> >> defined and it is not clear what it is. I apply patch 1 and review patch 1 and
> >> not looking at patch 8 to get what that values are for.
> >
> > My point was that I have not defined these values at all. These will
> > have to be defined on a per platform level. But if you insist, I will
> > define default values, but in my opinion it is better to get a build
> > failure and then set correct values, rather than the build going
> > through with some values which are incorrect for the platform.
> >
> > If you apply the patches as they are, they should not result in any
> > build failures.
>
> This code should be enabled for at least one platform. It means I expect you
> define that values at least for one platform which you use for testing.
> I don't agree that it is better to get build error. Feature will be disabled by
> default for other platforms and when developer enables it should check all these
> settings before enablement happens.

I will leave this to the ST maintainers on whether they want me to
define some default values. If they do, I will add a patch doing so.

-sughosh

>
> Thanks,
> Michal
>

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 11:35     ` Sughosh Ganu
  2022-02-08 11:39       ` Michal Simek
@ 2022-02-08 13:36       ` Masami Hiramatsu
  2022-02-08 13:45         ` Michal Simek
  1 sibling, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-08 13:36 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Michal Simek, U-Boot, Heinrich Schuchardt, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Michal Simek

2022年2月8日(火) 20:35 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
> >
> > po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> > >
> > > 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.
> > >
> > > A device tree node fwu-mdata has been added, which is used for
> > > pointing to the storage device which contains the FWU metadata. The
> > > fwu-mdata node is u-boot specific, and can be added the platform's
> > > u-boot dtsi file.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > ---
> > >
> > > Changes since V3:
> > > * Move the FWU metadata access to driver model
> > > * Get the storage device containing the metadata from a device tree
> > >   property instead of a platform helper function
> > >
> > >  arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> > >  .../firmware/fwu-mdata.txt                    |  18 +
> > >  drivers/Kconfig                               |   2 +
> > >  drivers/Makefile                              |   1 +
> > >  drivers/fwu-mdata/Kconfig                     |   7 +
> > >  drivers/fwu-mdata/Makefile                    |   6 +
> > >  drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> > >  include/dm/uclass-id.h                        |   1 +
> > >  include/fwu.h                                 |  51 ++
> > >  include/fwu_mdata.h                           |  67 +++
> > >  10 files changed, 594 insertions(+)
> > >  create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> > >  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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> > > index 06ef3a4095..3bec6107f7 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";
> > > +               fwu-mdata-store = <&sdmmc1>;
> > > +       };
> > > +};
> > > diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> > > new file mode 100644
> > > index 0000000000..c766b595ef
> > > --- /dev/null
> > > +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> > > @@ -0,0 +1,18 @@
> > > +FWU Metadata Access Devicetree Binding
> > > +
> > > +The FWU Multi Bank Update feature uses a metadata structure, stored on
> > > +a separate partition for keeping information on the set of updatable
> > > +images. The device tree node provides information on the storage
> > > +device that contains the FWU metadata.
> > > +
> > > +Required properties :
> > > +
> > > +- compatible : "u-boot,fwu-mdata";
> > > +- fwu-mdata-store : should point to the storage device which contains
> > > +                   the FWU metadata partition.
> >
> > In 0/11 you are describing GPT partitions but I don't think this
> > binding is generic enough to describe
> > other cases. It is saying device but not where exactly it is.
> > I didn't read the whole series yet but arm spec recommends GPT but dt
> > binding should be generic enough to describe
> > also other cases.
> > We are saving this structure to qspi for example but current binding
> > can't be used for it.
>
> I would wait to see Masami's implementation of this feature. If I am
> not wrong, his platform too is enabling this feature with a spi as the
> storage device. Maybe we can instead put a list of <device partition>
> tuples which can then list the device and partition number of the
> metadata partitions.

Yes, I would like to define new compatible for sf backend, e.g.
"u-boot,fwu-mdata-sf".
It will have the fwu-mdata-store to point the SPI flash device, and
will have a list of offset information for the metadata.

Thank you,



>
> -sughosh
>
>  >
> > > +
> > > +Example :
> > > +       fwu-mdata {
> > > +               compatible = "u-boot,fwu-mdata";
> > > +               fwu-mdata-store = <&sdmmc1>;
> > > +       };
> >
> > I don't think this is aligned with getting these u-boot nodes to any
> > standard locations.
> > Simon had that discussion with Rob some time ago. Was there any
> > outcome from this discussion where u-boot nodes should go?
> >
> > Thanks,
> > Michal



--
Masami Hiramatsu

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 13:36       ` Masami Hiramatsu
@ 2022-02-08 13:45         ` Michal Simek
  2022-02-08 14:14           ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 13:45 UTC (permalink / raw)
  To: Masami Hiramatsu, Sughosh Ganu
  Cc: Michal Simek, U-Boot, Heinrich Schuchardt, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, Michal Simek



On 2/8/22 14:36, Masami Hiramatsu wrote:
> 2022年2月8日(火) 20:35 Sughosh Ganu <sughosh.ganu@linaro.org>:
>>
>> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
>>>
>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>>
>>>> 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.
>>>>
>>>> A device tree node fwu-mdata has been added, which is used for
>>>> pointing to the storage device which contains the FWU metadata. The
>>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>>> u-boot dtsi file.
>>>>
>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>>> ---
>>>>
>>>> Changes since V3:
>>>> * Move the FWU metadata access to driver model
>>>> * Get the storage device containing the metadata from a device tree
>>>>    property instead of a platform helper function
>>>>
>>>>   arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>>   .../firmware/fwu-mdata.txt                    |  18 +
>>>>   drivers/Kconfig                               |   2 +
>>>>   drivers/Makefile                              |   1 +
>>>>   drivers/fwu-mdata/Kconfig                     |   7 +
>>>>   drivers/fwu-mdata/Makefile                    |   6 +
>>>>   drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>>   include/dm/uclass-id.h                        |   1 +
>>>>   include/fwu.h                                 |  51 ++
>>>>   include/fwu_mdata.h                           |  67 +++
>>>>   10 files changed, 594 insertions(+)
>>>>   create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>   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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>>> index 06ef3a4095..3bec6107f7 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";
>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>> +       };
>>>> +};
>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>> new file mode 100644
>>>> index 0000000000..c766b595ef
>>>> --- /dev/null
>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>> @@ -0,0 +1,18 @@
>>>> +FWU Metadata Access Devicetree Binding
>>>> +
>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>>> +a separate partition for keeping information on the set of updatable
>>>> +images. The device tree node provides information on the storage
>>>> +device that contains the FWU metadata.
>>>> +
>>>> +Required properties :
>>>> +
>>>> +- compatible : "u-boot,fwu-mdata";
>>>> +- fwu-mdata-store : should point to the storage device which contains
>>>> +                   the FWU metadata partition.
>>>
>>> In 0/11 you are describing GPT partitions but I don't think this
>>> binding is generic enough to describe
>>> other cases. It is saying device but not where exactly it is.
>>> I didn't read the whole series yet but arm spec recommends GPT but dt
>>> binding should be generic enough to describe
>>> also other cases.
>>> We are saving this structure to qspi for example but current binding
>>> can't be used for it.
>>
>> I would wait to see Masami's implementation of this feature. If I am
>> not wrong, his platform too is enabling this feature with a spi as the
>> storage device. Maybe we can instead put a list of <device partition>
>> tuples which can then list the device and partition number of the
>> metadata partitions.
> 
> Yes, I would like to define new compatible for sf backend, e.g.
> "u-boot,fwu-mdata-sf".

backend is fine. What does this compatible string have to do with it?
I didn't see any fwu-mdata-gpt in this series.

> It will have the fwu-mdata-store to point the SPI flash device, and
> will have a list of offset information for the metadata.

Can you describe it?

Something like for raw accesses?
fwu-mdta-store = <&qspi 0 XXXX>;

Thanks,
Michal

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 13:45         ` Michal Simek
@ 2022-02-08 14:14           ` Masami Hiramatsu
  2022-02-08 14:27             ` Michal Simek
  0 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-08 14:14 UTC (permalink / raw)
  To: Michal Simek
  Cc: Sughosh Ganu, Michal Simek, U-Boot, Heinrich Schuchardt,
	Patrick Delaunay, Patrice Chotard, Alexander Graf,
	AKASHI Takahiro, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

2022年2月8日(火) 22:45 Michal Simek <michal.simek@xilinx.com>:
>
>
>
> On 2/8/22 14:36, Masami Hiramatsu wrote:
> > 2022年2月8日(火) 20:35 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >>
> >> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
> >>>
> >>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >>>>
> >>>> 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.
> >>>>
> >>>> A device tree node fwu-mdata has been added, which is used for
> >>>> pointing to the storage device which contains the FWU metadata. The
> >>>> fwu-mdata node is u-boot specific, and can be added the platform's
> >>>> u-boot dtsi file.
> >>>>
> >>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> >>>> ---
> >>>>
> >>>> Changes since V3:
> >>>> * Move the FWU metadata access to driver model
> >>>> * Get the storage device containing the metadata from a device tree
> >>>>    property instead of a platform helper function
> >>>>
> >>>>   arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >>>>   .../firmware/fwu-mdata.txt                    |  18 +
> >>>>   drivers/Kconfig                               |   2 +
> >>>>   drivers/Makefile                              |   1 +
> >>>>   drivers/fwu-mdata/Kconfig                     |   7 +
> >>>>   drivers/fwu-mdata/Makefile                    |   6 +
> >>>>   drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >>>>   include/dm/uclass-id.h                        |   1 +
> >>>>   include/fwu.h                                 |  51 ++
> >>>>   include/fwu_mdata.h                           |  67 +++
> >>>>   10 files changed, 594 insertions(+)
> >>>>   create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>   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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> >>>> index 06ef3a4095..3bec6107f7 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";
> >>>> +               fwu-mdata-store = <&sdmmc1>;
> >>>> +       };
> >>>> +};
> >>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>> new file mode 100644
> >>>> index 0000000000..c766b595ef
> >>>> --- /dev/null
> >>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>> @@ -0,0 +1,18 @@
> >>>> +FWU Metadata Access Devicetree Binding
> >>>> +
> >>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> >>>> +a separate partition for keeping information on the set of updatable
> >>>> +images. The device tree node provides information on the storage
> >>>> +device that contains the FWU metadata.
> >>>> +
> >>>> +Required properties :
> >>>> +
> >>>> +- compatible : "u-boot,fwu-mdata";
> >>>> +- fwu-mdata-store : should point to the storage device which contains
> >>>> +                   the FWU metadata partition.
> >>>
> >>> In 0/11 you are describing GPT partitions but I don't think this
> >>> binding is generic enough to describe
> >>> other cases. It is saying device but not where exactly it is.
> >>> I didn't read the whole series yet but arm spec recommends GPT but dt
> >>> binding should be generic enough to describe
> >>> also other cases.
> >>> We are saving this structure to qspi for example but current binding
> >>> can't be used for it.
> >>
> >> I would wait to see Masami's implementation of this feature. If I am
> >> not wrong, his platform too is enabling this feature with a spi as the
> >> storage device. Maybe we can instead put a list of <device partition>
> >> tuples which can then list the device and partition number of the
> >> metadata partitions.
> >
> > Yes, I would like to define new compatible for sf backend, e.g.
> > "u-boot,fwu-mdata-sf".
>
> backend is fine. What does this compatible string have to do with it?
> I didn't see any fwu-mdata-gpt in this series.

Sughosh made it "fwu-mdata" but I think it should be "fwu-mdata-gpt"
if the required parameters are different.

>
> > It will have the fwu-mdata-store to point the SPI flash device, and
> > will have a list of offset information for the metadata.
>
> Can you describe it?
>
> Something like for raw accesses?
> fwu-mdta-store = <&qspi 0 XXXX>;

I'm still not sure what is the best way. What I thought was,

fwu-mdata-store = <&spi-flash>;
fwu-mdata-offsets = <500000, 520000>;

Thanks,


>
> Thanks,
> Michal



-- 
Masami Hiramatsu

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 14:14           ` Masami Hiramatsu
@ 2022-02-08 14:27             ` Michal Simek
  2022-02-08 23:39               ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Michal Simek @ 2022-02-08 14:27 UTC (permalink / raw)
  To: Masami Hiramatsu, Michal Simek
  Cc: Sughosh Ganu, Michal Simek, U-Boot, Heinrich Schuchardt,
	Patrick Delaunay, Patrice Chotard, Alexander Graf,
	AKASHI Takahiro, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere



On 2/8/22 15:14, Masami Hiramatsu wrote:
> 2022年2月8日(火) 22:45 Michal Simek <michal.simek@xilinx.com>:
>>
>>
>>
>> On 2/8/22 14:36, Masami Hiramatsu wrote:
>>> 2022年2月8日(火) 20:35 Sughosh Ganu <sughosh.ganu@linaro.org>:
>>>>
>>>> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
>>>>>
>>>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>>>>
>>>>>> 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.
>>>>>>
>>>>>> A device tree node fwu-mdata has been added, which is used for
>>>>>> pointing to the storage device which contains the FWU metadata. The
>>>>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>>>>> u-boot dtsi file.
>>>>>>
>>>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>>>>> ---
>>>>>>
>>>>>> Changes since V3:
>>>>>> * Move the FWU metadata access to driver model
>>>>>> * Get the storage device containing the metadata from a device tree
>>>>>>     property instead of a platform helper function
>>>>>>
>>>>>>    arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>>>>    .../firmware/fwu-mdata.txt                    |  18 +
>>>>>>    drivers/Kconfig                               |   2 +
>>>>>>    drivers/Makefile                              |   1 +
>>>>>>    drivers/fwu-mdata/Kconfig                     |   7 +
>>>>>>    drivers/fwu-mdata/Makefile                    |   6 +
>>>>>>    drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>>>>    include/dm/uclass-id.h                        |   1 +
>>>>>>    include/fwu.h                                 |  51 ++
>>>>>>    include/fwu_mdata.h                           |  67 +++
>>>>>>    10 files changed, 594 insertions(+)
>>>>>>    create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>    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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>>>>> index 06ef3a4095..3bec6107f7 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";
>>>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>>>> +       };
>>>>>> +};
>>>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>> new file mode 100644
>>>>>> index 0000000000..c766b595ef
>>>>>> --- /dev/null
>>>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>> @@ -0,0 +1,18 @@
>>>>>> +FWU Metadata Access Devicetree Binding
>>>>>> +
>>>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>>>>> +a separate partition for keeping information on the set of updatable
>>>>>> +images. The device tree node provides information on the storage
>>>>>> +device that contains the FWU metadata.
>>>>>> +
>>>>>> +Required properties :
>>>>>> +
>>>>>> +- compatible : "u-boot,fwu-mdata";
>>>>>> +- fwu-mdata-store : should point to the storage device which contains
>>>>>> +                   the FWU metadata partition.
>>>>>
>>>>> In 0/11 you are describing GPT partitions but I don't think this
>>>>> binding is generic enough to describe
>>>>> other cases. It is saying device but not where exactly it is.
>>>>> I didn't read the whole series yet but arm spec recommends GPT but dt
>>>>> binding should be generic enough to describe
>>>>> also other cases.
>>>>> We are saving this structure to qspi for example but current binding
>>>>> can't be used for it.
>>>>
>>>> I would wait to see Masami's implementation of this feature. If I am
>>>> not wrong, his platform too is enabling this feature with a spi as the
>>>> storage device. Maybe we can instead put a list of <device partition>
>>>> tuples which can then list the device and partition number of the
>>>> metadata partitions.
>>>
>>> Yes, I would like to define new compatible for sf backend, e.g.
>>> "u-boot,fwu-mdata-sf".
>>
>> backend is fine. What does this compatible string have to do with it?
>> I didn't see any fwu-mdata-gpt in this series.
> 
> Sughosh made it "fwu-mdata" but I think it should be "fwu-mdata-gpt"
> if the required parameters are different.
> 
>>
>>> It will have the fwu-mdata-store to point the SPI flash device, and
>>> will have a list of offset information for the metadata.
>>
>> Can you describe it?
>>
>> Something like for raw accesses?
>> fwu-mdta-store = <&qspi 0 XXXX>;
> 
> I'm still not sure what is the best way. What I thought was,
> 
> fwu-mdata-store = <&spi-flash>;
> fwu-mdata-offsets = <500000, 520000>;

as I said. Before this is applied I think we should work on generic proposal how 
to describe it. Because the same way can be used for u-boot variables and maybe 
others.
Definitely I would prefer to ask Rob for helping with this and get this to yaml 
to be able to use the whole infrastructure to check it.

Thanks,
Michal

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 14:27             ` Michal Simek
@ 2022-02-08 23:39               ` Masami Hiramatsu
  2022-02-09  7:21                 ` Michal Simek
  0 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-08 23:39 UTC (permalink / raw)
  To: Michal Simek
  Cc: Sughosh Ganu, Michal Simek, U-Boot, Heinrich Schuchardt,
	Patrick Delaunay, Patrice Chotard, Alexander Graf,
	AKASHI Takahiro, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

Hi Michal,

2022年2月8日(火) 23:27 Michal Simek <michal.simek@xilinx.com>:
>
>
>
> On 2/8/22 15:14, Masami Hiramatsu wrote:
> > 2022年2月8日(火) 22:45 Michal Simek <michal.simek@xilinx.com>:
> >>
> >>
> >>
> >> On 2/8/22 14:36, Masami Hiramatsu wrote:
> >>> 2022年2月8日(火) 20:35 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >>>>
> >>>> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
> >>>>>
> >>>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >>>>>>
> >>>>>> 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.
> >>>>>>
> >>>>>> A device tree node fwu-mdata has been added, which is used for
> >>>>>> pointing to the storage device which contains the FWU metadata. The
> >>>>>> fwu-mdata node is u-boot specific, and can be added the platform's
> >>>>>> u-boot dtsi file.
> >>>>>>
> >>>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> >>>>>> ---
> >>>>>>
> >>>>>> Changes since V3:
> >>>>>> * Move the FWU metadata access to driver model
> >>>>>> * Get the storage device containing the metadata from a device tree
> >>>>>>     property instead of a platform helper function
> >>>>>>
> >>>>>>    arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
> >>>>>>    .../firmware/fwu-mdata.txt                    |  18 +
> >>>>>>    drivers/Kconfig                               |   2 +
> >>>>>>    drivers/Makefile                              |   1 +
> >>>>>>    drivers/fwu-mdata/Kconfig                     |   7 +
> >>>>>>    drivers/fwu-mdata/Makefile                    |   6 +
> >>>>>>    drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
> >>>>>>    include/dm/uclass-id.h                        |   1 +
> >>>>>>    include/fwu.h                                 |  51 ++
> >>>>>>    include/fwu_mdata.h                           |  67 +++
> >>>>>>    10 files changed, 594 insertions(+)
> >>>>>>    create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>>    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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
> >>>>>> index 06ef3a4095..3bec6107f7 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";
> >>>>>> +               fwu-mdata-store = <&sdmmc1>;
> >>>>>> +       };
> >>>>>> +};
> >>>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>> new file mode 100644
> >>>>>> index 0000000000..c766b595ef
> >>>>>> --- /dev/null
> >>>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
> >>>>>> @@ -0,0 +1,18 @@
> >>>>>> +FWU Metadata Access Devicetree Binding
> >>>>>> +
> >>>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
> >>>>>> +a separate partition for keeping information on the set of updatable
> >>>>>> +images. The device tree node provides information on the storage
> >>>>>> +device that contains the FWU metadata.
> >>>>>> +
> >>>>>> +Required properties :
> >>>>>> +
> >>>>>> +- compatible : "u-boot,fwu-mdata";
> >>>>>> +- fwu-mdata-store : should point to the storage device which contains
> >>>>>> +                   the FWU metadata partition.
> >>>>>
> >>>>> In 0/11 you are describing GPT partitions but I don't think this
> >>>>> binding is generic enough to describe
> >>>>> other cases. It is saying device but not where exactly it is.
> >>>>> I didn't read the whole series yet but arm spec recommends GPT but dt
> >>>>> binding should be generic enough to describe
> >>>>> also other cases.
> >>>>> We are saving this structure to qspi for example but current binding
> >>>>> can't be used for it.
> >>>>
> >>>> I would wait to see Masami's implementation of this feature. If I am
> >>>> not wrong, his platform too is enabling this feature with a spi as the
> >>>> storage device. Maybe we can instead put a list of <device partition>
> >>>> tuples which can then list the device and partition number of the
> >>>> metadata partitions.
> >>>
> >>> Yes, I would like to define new compatible for sf backend, e.g.
> >>> "u-boot,fwu-mdata-sf".
> >>
> >> backend is fine. What does this compatible string have to do with it?
> >> I didn't see any fwu-mdata-gpt in this series.
> >
> > Sughosh made it "fwu-mdata" but I think it should be "fwu-mdata-gpt"
> > if the required parameters are different.
> >
> >>
> >>> It will have the fwu-mdata-store to point the SPI flash device, and
> >>> will have a list of offset information for the metadata.
> >>
> >> Can you describe it?
> >>
> >> Something like for raw accesses?
> >> fwu-mdta-store = <&qspi 0 XXXX>;
> >
> > I'm still not sure what is the best way. What I thought was,
> >
> > fwu-mdata-store = <&spi-flash>;
> > fwu-mdata-offsets = <500000, 520000>;
>
> as I said. Before this is applied I think we should work on generic proposal how
> to describe it. Because the same way can be used for u-boot variables and maybe
> others.

Agreed. This also reminds me the dfu_alt_info. Currently the dfu_alt_info
is passed via u-boot variables, but this should be a (important) part of
firmware information. I think it should be defined in the devicetree too.
(actually, stm32 builds dfu_alt_info from the device information already)

> Definitely I would prefer to ask Rob for helping with this and get this to yaml
> to be able to use the whole infrastructure to check it.

Yeah, and at first we should define what information should be in the
devicetree.

Thank you,


>
> Thanks,
> Michal



-- 
Masami Hiramatsu

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

* Re: [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules
  2022-02-07 18:20 ` [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
@ 2022-02-09  3:05   ` AKASHI Takahiro
  2022-02-10  1:27     ` AKASHI Takahiro
  2022-02-11 13:25     ` Sughosh Ganu
  0 siblings, 2 replies; 64+ messages in thread
From: AKASHI Takahiro @ 2022-02-09  3:05 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

On Mon, Feb 07, 2022 at 11:50:00PM +0530, Sughosh Ganu wrote:
> The Dependable Boot specification describes the structure of the

What is this specification? Please specify the link to the doc.

> 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.
> 
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> 
> Changes since V3:
> * Add related documentation for empty capsules in the mkeficapsule man
>   page.
> * Add separate usage for empty capsules, with corresponding valid
>   options.
> * Use ternary operators where possible.
> * Put a exclusivity check for the empty capsule options.
> 
>  doc/mkeficapsule.1   |  23 +++++++-
>  tools/eficapsule.h   |   8 +++
>  tools/mkeficapsule.c | 131 ++++++++++++++++++++++++++++++++++++-------
>  3 files changed, 139 insertions(+), 23 deletions(-)
> 
> diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> index 8babb27ee8..75fc15906a 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

With this formatting, "capsule-file" will get italic.

=> .RI [ options "] [" image-blob "] " capsule-file

Right?

Furthermore, I think we can describe the command syntax of the two
different cases (normal or empty capsule) more specifically.

>  
>  .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.
> @@ -43,7 +48,7 @@ specify a guid for the FMP driver.
>  .SH "OPTIONS"
>  One of
>  .BR --fit ", " --raw " or " --guid
> -option must be specified.
> +option must be specified for non empty capsules.
>  
>  .TP
>  .BR -f ", " --fit
> @@ -69,6 +74,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

I don't still understand why we need GUID for accept empty capsule.
We should have only one choice, whether all the new firmware be
permanently applied or completely reverted.

That's A/B update, isn't it?

> +.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 8c1560bb06..6001952bdc 100644
> --- a/tools/eficapsule.h
> +++ b/tools/eficapsule.h
> @@ -50,6 +50,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 161affdd15..e5dbec3a92 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,6 +29,7 @@
>  #include "eficapsule.h"
>  
>  static const char *tool_name = "mkeficapsule";
> +unsigned char accept_fw_capsule, revert_fw_capsule, empty_capsule;

Bool? but those variables are redundant.

As Ilias suggested, introducing a new enum type here can
simplify the code in the following code.
enum {
        CAPSULE_NORMAL_BLOB = 0,
        CAPSULE_ACCEPT,
        CAPSULE_REVERT,
} capsule_type;


>  
>  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
>  efi_guid_t efi_guid_image_type_uboot_fit =
> @@ -38,9 +39,9 @@ efi_guid_t efi_guid_image_type_uboot_raw =
>  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>  
>  #ifdef CONFIG_TOOLS_LIBCRYPTO

Please rebase your patch to my v10 or later.
I have already removed the dependency on openssl library.

> -static const char *opts_short = "frg:i:I:v:p:c:m:dh";
> +static const char *opts_short = "frg:i:I:v:p:c:m:dhAR";
>  #else
> -static const char *opts_short = "frg:i:I:v:h";
> +static const char *opts_short = "frg:i:I:v:hAR";
>  #endif
>  
>  static struct option options[] = {
> @@ -55,28 +56,50 @@ static struct option options[] = {
>  	{"monotonic-count", required_argument, NULL, 'm'},
>  	{"dump-sig", no_argument, NULL, 'd'},
>  #endif
> +	{"fw-accept", no_argument, NULL, 'A'},
> +	{"fw-revert", no_argument, NULL, 'R'},
>  	{"help", no_argument, NULL, 'h'},
>  	{NULL, 0, NULL, 0},
>  };
>  
>  static void print_usage(void)
>  {
> -	fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n"
> -		"Options:\n"
> -
> -		"\t-f, --fit                   FIT image type\n"
> -		"\t-r, --raw                   raw image type\n"
> -		"\t-g, --guid <guid string>    guid for image blob type\n"
> -		"\t-i, --index <index>         update image index\n"
> -		"\t-I, --instance <instance>   update hardware instance\n"
> +	if (empty_capsule) {
> +		if (accept_fw_capsule) {
> +			fprintf(stderr, "Usage: %s [options] <output file>\n",
> +				tool_name);
> +			fprintf(stderr, "Options:\n"
> +				"\t-A, --fw-accept          firmware accept capsule\n"
> +				"\t-g, --guid <guid string>    guid for image blob type\n"

While I doubt the necessity of "--guid,"
why not accept "-f" or "-r" as a guid of image blob type?
(It seems that your actual code does.)

> +				"\t-h, --help                  print a help message\n"
> +				);
> +		} else {
> +			fprintf(stderr, "Usage: %s [options] <output file>\n",
> +				tool_name);
> +			fprintf(stderr, "Options:\n"
> +				"\t-R, --fw-revert          firmware revert capsule\n"
> +				"\t-h, --help                  print a help message\n"
> +				);
> +		}
> +	} else {
> +		fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> +			tool_name);
> +		fprintf(stderr, "Options:\n"
> +			"\t-f, --fit                   FIT image type\n"
> +			"\t-r, --raw                   raw image type\n"
> +			"\t-g, --guid <guid string>    guid for image blob type\n"
> +			"\t-i, --index <index>         update image index\n"
> +			"\t-I, --instance <instance>   update hardware instance\n"
>  #ifdef CONFIG_TOOLS_LIBCRYPTO
> -		"\t-p, --private-key <privkey file>  private key file\n"
> -		"\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-p, --private-key <privkey file>  private key file\n"
> +			"\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"
>  #endif
> -		"\t-h, --help                  print a help message\n",
> -		tool_name);
> +			"\t-A, --fw-accept          firmware accept capsule\n"
> +			"\t-R, --fw-revert          firmware revert capsule\n"
> +			"\t-h, --help                  print a help message\n");
> +	}
>  }
>  
>  /**
> @@ -598,6 +621,50 @@ 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;
> +	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 payload, 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) {
> +		memcpy(&payload, guid, sizeof(efi_guid_t));
> +		if (write_capsule_file(f, &payload, sizeof(payload),
> +				       "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
> @@ -625,6 +692,8 @@ int main(int argc, char **argv)
>  	mcount = 0;
>  	privkey_file = NULL;
>  	cert_file = NULL;
> +	accept_fw_capsule = 0;
> +	revert_fw_capsule = 0;
>  	dump_sig = 0;
>  	for (;;) {
>  		c = getopt_long(argc, argv, opts_short, options, &idx);
> @@ -691,22 +760,44 @@ int main(int argc, char **argv)
>  			dump_sig = 1;
>  			break;
>  #endif /* CONFIG_TOOLS_LIBCRYPTO */
> +		case 'A':
> +			accept_fw_capsule = 1;
> +			break;
> +		case 'R':
> +			revert_fw_capsule = 1;
> +			break;
>  		case 'h':
>  			print_usage();
>  			exit(EXIT_SUCCESS);
>  		}
>  	}
>  
> +	if (accept_fw_capsule && revert_fw_capsule) {
> +		fprintf(stderr,
> +			"Select either of Accept or Revert capsule generation\n");
> +		exit(EXIT_FAILURE);
> +	}
> +
> +	empty_capsule = (accept_fw_capsule || revert_fw_capsule);
> +
>  	/* check necessary parameters */
> -	if ((argc != optind + 2) || !guid ||
> -	    ((privkey_file && !cert_file) ||
> +	if ((!empty_capsule && argc != optind + 2) ||
> +	    (empty_capsule && argc != optind + 1) ||
> +	    (!revert_fw_capsule && !guid) || ((privkey_file && !cert_file) ||
>  	     (!privkey_file && cert_file))) {

Well, the error condition looks complicated due to mixing two cases
and can be hard to maintain in the future. How about
	if (!empty_capsule &&
                ((argc != optind + 2) || !guid ||
                 ((privkey_file && !cert_file) ||
                  (!privkey_file && cert_file))) ||
            empty_capsule &&
                ((argc != optind + 1) ||
                 (accept_fw_capsule && revert_fw_capsule) ||
                 (accept_fw_capsule && !guid))  # arguable as mentioned above
                 (revert_fw_capsule && 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 (empty_capsule) {
> +		if (create_empty_capsule(argv[argc - 1], guid,
> +					 accept_fw_capsule ? 1 : 0) < 0) {

The third argument can be simplified to "accept_fw_capsule".

-Takahiro Akashi

> +			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.17.1
> 

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-07 18:19 ` [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
@ 2022-02-09  4:56   ` Masami Hiramatsu
  2022-02-09  9:03     ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-09  4:56 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

While porting mdata-sf driver, I'm confusing on the devicetree
usage.

2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:

> +int fwu_get_mdata_device(struct udevice **mdata_dev)
> +{
> +       u32 phandle;
> +       int ret, size;
> +       struct udevice *dev, *child;
> +       ofnode fwu_mdata_node;
> +       const fdt32_t *phandle_p = NULL;
> +
> +       fwu_mdata_node = ofnode_path("/fwu-mdata");
> +       if (!ofnode_valid(fwu_mdata_node)) {
> +               log_err("fwu-node not found\n");
> +               return -ENOENT;
> +       }

So this seems to get the udevice from path, but I think fwu-mdata node
has "u-boot,fwu-mdata" compatible property, in that case probe function
already gets the node. Why would you search it again by path?

> +
> +       phandle_p = ofnode_get_property(fwu_mdata_node, "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),
> +                                         &dev);
> +       if (ret)
> +               return ret;
> +
> +       ret = -ENODEV;
> +       for (device_find_first_child(dev, &child); child;
> +            device_find_next_child(&child)) {
> +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> +                       *mdata_dev = child;

I thought that the blk device node directly passed by the
"fwu-mdata-store" property. Would we need to search it from
children nodes?

BTW, if we can use the devicetree, can we define the number of banks
and the number of images can be described too?
Of course as I said in the other thread, I would like to put the
dfu_alt_info like information in the devicetree too.
(But it maybe different from this discussion)

Thank you,


> +                       ret = 0;
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> +{
> +       int ret;
> +       struct udevice *mdata_dev = NULL;
> +
> +       ret = fwu_get_mdata_device(&mdata_dev);
> +       if (ret)
> +               return ret;
> +
> +       dev_set_priv(dev, mdata_dev);
> +
> +       return 0;
> +}
> +
> +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> +       .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" },

> +       { }
> +};
> +
> +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,
> +};
> diff --git a/include/fwu.h b/include/fwu.h
> index 5a99c579fc..2c7db2dff9 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> +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.17.1
>


--
Masami Hiramatsu

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

* Re: [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata
  2022-02-08 23:39               ` Masami Hiramatsu
@ 2022-02-09  7:21                 ` Michal Simek
  0 siblings, 0 replies; 64+ messages in thread
From: Michal Simek @ 2022-02-09  7:21 UTC (permalink / raw)
  To: Masami Hiramatsu, Michal Simek
  Cc: Sughosh Ganu, Michal Simek, U-Boot, Heinrich Schuchardt,
	Patrick Delaunay, Patrice Chotard, Alexander Graf,
	AKASHI Takahiro, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

Hi,

On 2/9/22 00:39, Masami Hiramatsu wrote:
> Hi Michal,
> 
> 2022年2月8日(火) 23:27 Michal Simek <michal.simek@xilinx.com>:
>>
>>
>>
>> On 2/8/22 15:14, Masami Hiramatsu wrote:
>>> 2022年2月8日(火) 22:45 Michal Simek <michal.simek@xilinx.com>:
>>>>
>>>>
>>>>
>>>> On 2/8/22 14:36, Masami Hiramatsu wrote:
>>>>> 2022年2月8日(火) 20:35 Sughosh Ganu <sughosh.ganu@linaro.org>:
>>>>>>
>>>>>> On Tue, 8 Feb 2022 at 16:26, Michal Simek <monstr@monstr.eu> wrote:
>>>>>>>
>>>>>>> po 7. 2. 2022 v 19:21 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
>>>>>>>>
>>>>>>>> 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.
>>>>>>>>
>>>>>>>> A device tree node fwu-mdata has been added, which is used for
>>>>>>>> pointing to the storage device which contains the FWU metadata. The
>>>>>>>> fwu-mdata node is u-boot specific, and can be added the platform's
>>>>>>>> u-boot dtsi file.
>>>>>>>>
>>>>>>>> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
>>>>>>>> ---
>>>>>>>>
>>>>>>>> Changes since V3:
>>>>>>>> * Move the FWU metadata access to driver model
>>>>>>>> * Get the storage device containing the metadata from a device tree
>>>>>>>>      property instead of a platform helper function
>>>>>>>>
>>>>>>>>     arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi      |   7 +
>>>>>>>>     .../firmware/fwu-mdata.txt                    |  18 +
>>>>>>>>     drivers/Kconfig                               |   2 +
>>>>>>>>     drivers/Makefile                              |   1 +
>>>>>>>>     drivers/fwu-mdata/Kconfig                     |   7 +
>>>>>>>>     drivers/fwu-mdata/Makefile                    |   6 +
>>>>>>>>     drivers/fwu-mdata/fwu-mdata-uclass.c          | 434 ++++++++++++++++++
>>>>>>>>     include/dm/uclass-id.h                        |   1 +
>>>>>>>>     include/fwu.h                                 |  51 ++
>>>>>>>>     include/fwu_mdata.h                           |  67 +++
>>>>>>>>     10 files changed, 594 insertions(+)
>>>>>>>>     create mode 100644 doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>>>     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/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
>>>>>>>> index 06ef3a4095..3bec6107f7 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";
>>>>>>>> +               fwu-mdata-store = <&sdmmc1>;
>>>>>>>> +       };
>>>>>>>> +};
>>>>>>>> diff --git a/doc/device-tree-bindings/firmware/fwu-mdata.txt b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>>> new file mode 100644
>>>>>>>> index 0000000000..c766b595ef
>>>>>>>> --- /dev/null
>>>>>>>> +++ b/doc/device-tree-bindings/firmware/fwu-mdata.txt
>>>>>>>> @@ -0,0 +1,18 @@
>>>>>>>> +FWU Metadata Access Devicetree Binding
>>>>>>>> +
>>>>>>>> +The FWU Multi Bank Update feature uses a metadata structure, stored on
>>>>>>>> +a separate partition for keeping information on the set of updatable
>>>>>>>> +images. The device tree node provides information on the storage
>>>>>>>> +device that contains the FWU metadata.
>>>>>>>> +
>>>>>>>> +Required properties :
>>>>>>>> +
>>>>>>>> +- compatible : "u-boot,fwu-mdata";
>>>>>>>> +- fwu-mdata-store : should point to the storage device which contains
>>>>>>>> +                   the FWU metadata partition.
>>>>>>>
>>>>>>> In 0/11 you are describing GPT partitions but I don't think this
>>>>>>> binding is generic enough to describe
>>>>>>> other cases. It is saying device but not where exactly it is.
>>>>>>> I didn't read the whole series yet but arm spec recommends GPT but dt
>>>>>>> binding should be generic enough to describe
>>>>>>> also other cases.
>>>>>>> We are saving this structure to qspi for example but current binding
>>>>>>> can't be used for it.
>>>>>>
>>>>>> I would wait to see Masami's implementation of this feature. If I am
>>>>>> not wrong, his platform too is enabling this feature with a spi as the
>>>>>> storage device. Maybe we can instead put a list of <device partition>
>>>>>> tuples which can then list the device and partition number of the
>>>>>> metadata partitions.
>>>>>
>>>>> Yes, I would like to define new compatible for sf backend, e.g.
>>>>> "u-boot,fwu-mdata-sf".
>>>>
>>>> backend is fine. What does this compatible string have to do with it?
>>>> I didn't see any fwu-mdata-gpt in this series.
>>>
>>> Sughosh made it "fwu-mdata" but I think it should be "fwu-mdata-gpt"
>>> if the required parameters are different.
>>>
>>>>
>>>>> It will have the fwu-mdata-store to point the SPI flash device, and
>>>>> will have a list of offset information for the metadata.
>>>>
>>>> Can you describe it?
>>>>
>>>> Something like for raw accesses?
>>>> fwu-mdta-store = <&qspi 0 XXXX>;
>>>
>>> I'm still not sure what is the best way. What I thought was,
>>>
>>> fwu-mdata-store = <&spi-flash>;
>>> fwu-mdata-offsets = <500000, 520000>;
>>
>> as I said. Before this is applied I think we should work on generic proposal how
>> to describe it. Because the same way can be used for u-boot variables and maybe
>> others.
> 
> Agreed. This also reminds me the dfu_alt_info. Currently the dfu_alt_info
> is passed via u-boot variables, but this should be a (important) part of
> firmware information. I think it should be defined in the devicetree too.
> (actually, stm32 builds dfu_alt_info from the device information already)

yes that capsule update via dfu_alt_info and upgrading all that structure should 
be also the part of it. I am not saying in this series. On the top of this one 
should be fine but it should be clear how this is supposed to work.


>> Definitely I would prefer to ask Rob for helping with this and get this to yaml
>> to be able to use the whole infrastructure to check it.
> 
> Yeah, and at first we should define what information should be in the
> devicetree.

yes.

Thanks,
Michal


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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-09  4:56   ` Masami Hiramatsu
@ 2022-02-09  9:03     ` Sughosh Ganu
  2022-02-09 11:47       ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-09  9:03 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Wed, 9 Feb 2022 at 10:26, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> While porting mdata-sf driver, I'm confusing on the devicetree
> usage.
>
> 2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> > +int fwu_get_mdata_device(struct udevice **mdata_dev)
> > +{
> > +       u32 phandle;
> > +       int ret, size;
> > +       struct udevice *dev, *child;
> > +       ofnode fwu_mdata_node;
> > +       const fdt32_t *phandle_p = NULL;
> > +
> > +       fwu_mdata_node = ofnode_path("/fwu-mdata");
> > +       if (!ofnode_valid(fwu_mdata_node)) {
> > +               log_err("fwu-node not found\n");
> > +               return -ENOENT;
> > +       }
>
> So this seems to get the udevice from path, but I think fwu-mdata node
> has "u-boot,fwu-mdata" compatible property, in that case probe function
> already gets the node. Why would you search it again by path?

Okay. Is there some other api that I can use which is faster than the
approach currently taken? If so, do let me know.

>
> > +
> > +       phandle_p = ofnode_get_property(fwu_mdata_node, "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),
> > +                                         &dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       ret = -ENODEV;
> > +       for (device_find_first_child(dev, &child); child;
> > +            device_find_next_child(&child)) {
> > +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> > +                       *mdata_dev = child;
>
> I thought that the blk device node directly passed by the
> "fwu-mdata-store" property. Would we need to search it from
> children nodes?

What the device tree is pointing to is the device like the mmc, which
is described through a device tree node. The block device is the child
of this device, which is not described in the device tree. The driver
finally needs the block device.

>
> BTW, if we can use the devicetree, can we define the number of banks
> and the number of images can be described too?

It is much easier to handle if these values are defined through
Kconfig symbols. That way, this gets directly included in the config
file, and can be used directly in the fwu_mdata.h metadata structure.

> Of course as I said in the other thread, I would like to put the
> dfu_alt_info like information in the devicetree too.
> (But it maybe different from this discussion)

Just curious, why do you need to define a variable like dfu_alt_info
in a device tree. If this has already been described earlier, you can
point me to that discussion. Trying to understand what benefit does
having the variables defined in a device tree brings. Thanks.

-sughosh

>
> Thank you,
>
>
> > +                       ret = 0;
> > +               }
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > +{
> > +       int ret;
> > +       struct udevice *mdata_dev = NULL;
> > +
> > +       ret = fwu_get_mdata_device(&mdata_dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       dev_set_priv(dev, mdata_dev);
> > +
> > +       return 0;
> > +}
> > +
> > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > +       .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" },
>
> > +       { }
> > +};
> > +
> > +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,
> > +};
> > diff --git a/include/fwu.h b/include/fwu.h
> > index 5a99c579fc..2c7db2dff9 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> > +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.17.1
> >
>
>
> --
> Masami Hiramatsu

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-09  9:03     ` Sughosh Ganu
@ 2022-02-09 11:47       ` Masami Hiramatsu
  2022-02-09 18:40         ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-09 11:47 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

2022年2月9日(水) 18:03 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> hi Masami,
>
> On Wed, 9 Feb 2022 at 10:26, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > While porting mdata-sf driver, I'm confusing on the devicetree
> > usage.
> >
> > 2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > > +int fwu_get_mdata_device(struct udevice **mdata_dev)
> > > +{
> > > +       u32 phandle;
> > > +       int ret, size;
> > > +       struct udevice *dev, *child;
> > > +       ofnode fwu_mdata_node;
> > > +       const fdt32_t *phandle_p = NULL;
> > > +
> > > +       fwu_mdata_node = ofnode_path("/fwu-mdata");
> > > +       if (!ofnode_valid(fwu_mdata_node)) {
> > > +               log_err("fwu-node not found\n");
> > > +               return -ENOENT;
> > > +       }
> >
> > So this seems to get the udevice from path, but I think fwu-mdata node
> > has "u-boot,fwu-mdata" compatible property, in that case probe function
> > already gets the node. Why would you search it again by path?
>
> Okay. Is there some other api that I can use which is faster than the
> approach currently taken? If so, do let me know.

I thought the ofnode which has "u-boot,fwu-mdata" compatible property
is passed to fwu_mdata_gpt_blk_probe(), and that is , doesn't it?

If so, as you show in the example,
       fwu-mdata {
               compatible = "u-boot,fwu-mdata";
               fwu-mdata-store = <&sdmmc1>;
       };

you already got the "/fwu-mdata" node. You don't need any API to find
that node because you already has that. That is what I meant.

> > > +
> > > +       phandle_p = ofnode_get_property(fwu_mdata_node, "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),
> > > +                                         &dev);
> > > +       if (ret)
> > > +               return ret;
> > > +
> > > +       ret = -ENODEV;
> > > +       for (device_find_first_child(dev, &child); child;
> > > +            device_find_next_child(&child)) {
> > > +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> > > +                       *mdata_dev = child;
> >
> > I thought that the blk device node directly passed by the
> > "fwu-mdata-store" property. Would we need to search it from
> > children nodes?
>
> What the device tree is pointing to is the device like the mmc, which
> is described through a device tree node. The block device is the child
> of this device, which is not described in the device tree. The driver
> finally needs the block device.

Ah, OK. Can't we specify the block device node to  "fwu-mdata-store"
directly?

> > BTW, if we can use the devicetree, can we define the number of banks
> > and the number of images can be described too?
>
> It is much easier to handle if these values are defined through
> Kconfig symbols. That way, this gets directly included in the config
> file, and can be used directly in the fwu_mdata.h metadata structure.

Yes, it is easier to implement. And that means the firmware bank
configuration is embedded in the firmware binary (code) instead
of the configuration data (devicetree).
For the same reason I think dfu_alt_info (or the basement info like
device and offsets) should be in the devicetree. Current implementation
is very fragile (because dfu_alt_info can be changed by the user) or
fixed in the code (like stm32, it generates the dfu_alt_info by the
platform driver.)

>
> > Of course as I said in the other thread, I would like to put the
> > dfu_alt_info like information in the devicetree too.
> > (But it maybe different from this discussion)
>
> Just curious, why do you need to define a variable like dfu_alt_info
> in a device tree. If this has already been described earlier, you can
> point me to that discussion. Trying to understand what benefit does
> having the variables defined in a device tree brings. Thanks.

If we can consolidate the configuration information related to the
firmware layout on the devicetree, it is very easy to understand
and manage the firmware update only by checking the devicetree.
Current design is very fragile from the consistency viewpoint,
because there are 3 different information we are using for FWU,
Kconfig, devicetree and u-boot env-variables. If one of them
sets inconsistent value, FWU may not work as we expected.

That is my impression felt from porting AB update on the DeveloperBox platform.

Thank you,

>
> -sughosh
>
> >
> > Thank you,
> >
> >
> > > +                       ret = 0;
> > > +               }
> > > +       }
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > > +{
> > > +       int ret;
> > > +       struct udevice *mdata_dev = NULL;
> > > +
> > > +       ret = fwu_get_mdata_device(&mdata_dev);
> > > +       if (ret)
> > > +               return ret;
> > > +
> > > +       dev_set_priv(dev, mdata_dev);
> > > +
> > > +       return 0;
> > > +}
> > > +
> > > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > > +       .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" },
> >
> > > +       { }
> > > +};
> > > +
> > > +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,
> > > +};
> > > diff --git a/include/fwu.h b/include/fwu.h
> > > index 5a99c579fc..2c7db2dff9 100644
> > > --- a/include/fwu.h
> > > +++ b/include/fwu.h
> > > @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> > > +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.17.1
> > >
> >
> >
> > --
> > Masami Hiramatsu



--
Masami Hiramatsu

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-09 11:47       ` Masami Hiramatsu
@ 2022-02-09 18:40         ` Sughosh Ganu
  2022-02-10  1:43           ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-09 18:40 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Wed, 9 Feb 2022 at 17:18, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> 2022年2月9日(水) 18:03 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > hi Masami,
> >
> > On Wed, 9 Feb 2022 at 10:26, Masami Hiramatsu
> > <masami.hiramatsu@linaro.org> wrote:
> > >
> > > Hi Sughosh,
> > >
> > > While porting mdata-sf driver, I'm confusing on the devicetree
> > > usage.
> > >
> > > 2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > >
> > > > +int fwu_get_mdata_device(struct udevice **mdata_dev)
> > > > +{
> > > > +       u32 phandle;
> > > > +       int ret, size;
> > > > +       struct udevice *dev, *child;
> > > > +       ofnode fwu_mdata_node;
> > > > +       const fdt32_t *phandle_p = NULL;
> > > > +
> > > > +       fwu_mdata_node = ofnode_path("/fwu-mdata");
> > > > +       if (!ofnode_valid(fwu_mdata_node)) {
> > > > +               log_err("fwu-node not found\n");
> > > > +               return -ENOENT;
> > > > +       }
> > >
> > > So this seems to get the udevice from path, but I think fwu-mdata node
> > > has "u-boot,fwu-mdata" compatible property, in that case probe function
> > > already gets the node. Why would you search it again by path?
> >
> > Okay. Is there some other api that I can use which is faster than the
> > approach currently taken? If so, do let me know.
>
> I thought the ofnode which has "u-boot,fwu-mdata" compatible property
> is passed to fwu_mdata_gpt_blk_probe(), and that is , doesn't it?
>
> If so, as you show in the example,
>        fwu-mdata {
>                compatible = "u-boot,fwu-mdata";
>                fwu-mdata-store = <&sdmmc1>;
>        };
>
> you already got the "/fwu-mdata" node. You don't need any API to find
> that node because you already has that. That is what I meant.

The probe function gets passed the corresponding udevice structure.
This structure contains node_ member, which should correspond to the
device node. I will try to use this member instead of searching for
the node.

>
> > > > +
> > > > +       phandle_p = ofnode_get_property(fwu_mdata_node, "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),
> > > > +                                         &dev);
> > > > +       if (ret)
> > > > +               return ret;
> > > > +
> > > > +       ret = -ENODEV;
> > > > +       for (device_find_first_child(dev, &child); child;
> > > > +            device_find_next_child(&child)) {
> > > > +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> > > > +                       *mdata_dev = child;
> > >
> > > I thought that the blk device node directly passed by the
> > > "fwu-mdata-store" property. Would we need to search it from
> > > children nodes?
> >
> > What the device tree is pointing to is the device like the mmc, which
> > is described through a device tree node. The block device is the child
> > of this device, which is not described in the device tree. The driver
> > finally needs the block device.
>
> Ah, OK. Can't we specify the block device node to  "fwu-mdata-store"
> directly?

I don't think so, since the fwu-mdata-store is pointing to one of the
nodes in the device tree -- the block device does not show up as node
on the device tree.

>
> > > BTW, if we can use the devicetree, can we define the number of banks
> > > and the number of images can be described too?
> >
> > It is much easier to handle if these values are defined through
> > Kconfig symbols. That way, this gets directly included in the config
> > file, and can be used directly in the fwu_mdata.h metadata structure.
>
> Yes, it is easier to implement. And that means the firmware bank
> configuration is embedded in the firmware binary (code) instead
> of the configuration data (devicetree).
> For the same reason I think dfu_alt_info (or the basement info like
> device and offsets) should be in the devicetree. Current implementation
> is very fragile (because dfu_alt_info can be changed by the user) or
> fixed in the code (like stm32, it generates the dfu_alt_info by the
> platform driver.)
>
> >
> > > Of course as I said in the other thread, I would like to put the
> > > dfu_alt_info like information in the devicetree too.
> > > (But it maybe different from this discussion)
> >
> > Just curious, why do you need to define a variable like dfu_alt_info
> > in a device tree. If this has already been described earlier, you can
> > point me to that discussion. Trying to understand what benefit does
> > having the variables defined in a device tree brings. Thanks.
>
> If we can consolidate the configuration information related to the
> firmware layout on the devicetree, it is very easy to understand
> and manage the firmware update only by checking the devicetree.
> Current design is very fragile from the consistency viewpoint,
> because there are 3 different information we are using for FWU,
> Kconfig, devicetree and u-boot env-variables. If one of them
> sets inconsistent value, FWU may not work as we expected.

I get your point. But I think generating the dfu_alt_info at runtime,
like how it is done for the ST platforms is in general a better
method, as against using a static variable defined in the device tree.
With runtime generation of the variable, the same code can be used on
multiple platforms and can be generated at runtime -- I feel that is
better than defining the variable in every platform's device tree.
Btw, there is also provision to define the variable(or part of it)
statically through Kconfig variables. As against your concern about
the feature using multiple methods for stating information, it is
indeed valid. But I guess we can have documentation explaining how
each of that information needs to be defined. Thanks.

-sughosh

>
> That is my impression felt from porting AB update on the DeveloperBox platform.
>
> Thank you,
>
> >
> > -sughosh
> >
> > >
> > > Thank you,
> > >
> > >
> > > > +                       ret = 0;
> > > > +               }
> > > > +       }
> > > > +
> > > > +       return ret;
> > > > +}
> > > > +
> > > > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > > > +{
> > > > +       int ret;
> > > > +       struct udevice *mdata_dev = NULL;
> > > > +
> > > > +       ret = fwu_get_mdata_device(&mdata_dev);
> > > > +       if (ret)
> > > > +               return ret;
> > > > +
> > > > +       dev_set_priv(dev, mdata_dev);
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > > > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > > > +       .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" },
> > >
> > > > +       { }
> > > > +};
> > > > +
> > > > +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,
> > > > +};
> > > > diff --git a/include/fwu.h b/include/fwu.h
> > > > index 5a99c579fc..2c7db2dff9 100644
> > > > --- a/include/fwu.h
> > > > +++ b/include/fwu.h
> > > > @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> > > > +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.17.1
> > > >
> > >
> > >
> > > --
> > > Masami Hiramatsu
>
>
>
> --
> Masami Hiramatsu

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

* Re: [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules
  2022-02-09  3:05   ` AKASHI Takahiro
@ 2022-02-10  1:27     ` AKASHI Takahiro
  2022-02-11 13:27       ` Sughosh Ganu
  2022-02-11 13:25     ` Sughosh Ganu
  1 sibling, 1 reply; 64+ messages in thread
From: AKASHI Takahiro @ 2022-02-10  1:27 UTC (permalink / raw)
  To: Sughosh Ganu, u-boot, Heinrich Schuchardt, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Alexander Graf, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Wed, Feb 09, 2022 at 12:05:06PM +0900, AKASHI Takahiro wrote:
> Hi Sughosh,
> 
> On Mon, Feb 07, 2022 at 11:50:00PM +0530, Sughosh Ganu wrote:
> > The Dependable Boot specification describes the structure of the
> 
> What is this specification? Please specify the link to the doc.
> 
> > 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.
> > 
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> > 
> > Changes since V3:
> > * Add related documentation for empty capsules in the mkeficapsule man
> >   page.
> > * Add separate usage for empty capsules, with corresponding valid
> >   options.
> > * Use ternary operators where possible.
> > * Put a exclusivity check for the empty capsule options.
> > 
> >  doc/mkeficapsule.1   |  23 +++++++-
> >  tools/eficapsule.h   |   8 +++
> >  tools/mkeficapsule.c | 131 ++++++++++++++++++++++++++++++++++++-------
> >  3 files changed, 139 insertions(+), 23 deletions(-)
> > 
> > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> > index 8babb27ee8..75fc15906a 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
> 
> With this formatting, "capsule-file" will get italic.

oops, I meant to say "roman."

> => .RI [ options "] [" image-blob "] " capsule-file
> 
> Right?
> 
> Furthermore, I think we can describe the command syntax of the two
> different cases (normal or empty capsule) more specifically.
> 
> >  
> >  .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.
> > @@ -43,7 +48,7 @@ specify a guid for the FMP driver.
> >  .SH "OPTIONS"
> >  One of
> >  .BR --fit ", " --raw " or " --guid
> > -option must be specified.
> > +option must be specified for non empty capsules.
> >  
> >  .TP
> >  .BR -f ", " --fit
> > @@ -69,6 +74,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
> 
> I don't still understand why we need GUID for accept empty capsule.
> We should have only one choice, whether all the new firmware be
> permanently applied or completely reverted.
> 
> That's A/B update, isn't it?
> 
> > +.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 8c1560bb06..6001952bdc 100644
> > --- a/tools/eficapsule.h
> > +++ b/tools/eficapsule.h
> > @@ -50,6 +50,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 161affdd15..e5dbec3a92 100644
> > --- a/tools/mkeficapsule.c
> > +++ b/tools/mkeficapsule.c
> > @@ -29,6 +29,7 @@
> >  #include "eficapsule.h"
> >  
> >  static const char *tool_name = "mkeficapsule";
> > +unsigned char accept_fw_capsule, revert_fw_capsule, empty_capsule;
> 
> Bool? but those variables are redundant.
> 
> As Ilias suggested, introducing a new enum type here can
> simplify the code in the following code.
> enum {
>         CAPSULE_NORMAL_BLOB = 0,
>         CAPSULE_ACCEPT,
>         CAPSULE_REVERT,
> } capsule_type;
> 
> 
> >  
> >  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
> >  efi_guid_t efi_guid_image_type_uboot_fit =
> > @@ -38,9 +39,9 @@ efi_guid_t efi_guid_image_type_uboot_raw =
> >  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> >  
> >  #ifdef CONFIG_TOOLS_LIBCRYPTO
> 
> Please rebase your patch to my v10 or later.
> I have already removed the dependency on openssl library.
> 
> > -static const char *opts_short = "frg:i:I:v:p:c:m:dh";
> > +static const char *opts_short = "frg:i:I:v:p:c:m:dhAR";
> >  #else
> > -static const char *opts_short = "frg:i:I:v:h";
> > +static const char *opts_short = "frg:i:I:v:hAR";
> >  #endif
> >  
> >  static struct option options[] = {
> > @@ -55,28 +56,50 @@ static struct option options[] = {
> >  	{"monotonic-count", required_argument, NULL, 'm'},
> >  	{"dump-sig", no_argument, NULL, 'd'},
> >  #endif
> > +	{"fw-accept", no_argument, NULL, 'A'},
> > +	{"fw-revert", no_argument, NULL, 'R'},
> >  	{"help", no_argument, NULL, 'h'},
> >  	{NULL, 0, NULL, 0},
> >  };
> >  
> >  static void print_usage(void)
> >  {
> > -	fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n"
> > -		"Options:\n"
> > -
> > -		"\t-f, --fit                   FIT image type\n"
> > -		"\t-r, --raw                   raw image type\n"
> > -		"\t-g, --guid <guid string>    guid for image blob type\n"
> > -		"\t-i, --index <index>         update image index\n"
> > -		"\t-I, --instance <instance>   update hardware instance\n"
> > +	if (empty_capsule) {
> > +		if (accept_fw_capsule) {
> > +			fprintf(stderr, "Usage: %s [options] <output file>\n",
> > +				tool_name);
> > +			fprintf(stderr, "Options:\n"
> > +				"\t-A, --fw-accept          firmware accept capsule\n"
> > +				"\t-g, --guid <guid string>    guid for image blob type\n"
> 
> While I doubt the necessity of "--guid,"
> why not accept "-f" or "-r" as a guid of image blob type?
> (It seems that your actual code does.)
> 
> > +				"\t-h, --help                  print a help message\n"
> > +				);
> > +		} else {
> > +			fprintf(stderr, "Usage: %s [options] <output file>\n",
> > +				tool_name);
> > +			fprintf(stderr, "Options:\n"
> > +				"\t-R, --fw-revert          firmware revert capsule\n"
> > +				"\t-h, --help                  print a help message\n"
> > +				);
> > +		}
> > +	} else {
> > +		fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> > +			tool_name);
> > +		fprintf(stderr, "Options:\n"
> > +			"\t-f, --fit                   FIT image type\n"
> > +			"\t-r, --raw                   raw image type\n"
> > +			"\t-g, --guid <guid string>    guid for image blob type\n"
> > +			"\t-i, --index <index>         update image index\n"
> > +			"\t-I, --instance <instance>   update hardware instance\n"
> >  #ifdef CONFIG_TOOLS_LIBCRYPTO
> > -		"\t-p, --private-key <privkey file>  private key file\n"
> > -		"\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-p, --private-key <privkey file>  private key file\n"
> > +			"\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"
> >  #endif
> > -		"\t-h, --help                  print a help message\n",
> > -		tool_name);
> > +			"\t-A, --fw-accept          firmware accept capsule\n"
> > +			"\t-R, --fw-revert          firmware revert capsule\n"
> > +			"\t-h, --help                  print a help message\n");
> > +	}
> >  }
> >  
> >  /**
> > @@ -598,6 +621,50 @@ 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;
> > +	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 payload, 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) {
> > +		memcpy(&payload, guid, sizeof(efi_guid_t));
> > +		if (write_capsule_file(f, &payload, sizeof(payload),
> > +				       "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
> > @@ -625,6 +692,8 @@ int main(int argc, char **argv)
> >  	mcount = 0;
> >  	privkey_file = NULL;
> >  	cert_file = NULL;
> > +	accept_fw_capsule = 0;
> > +	revert_fw_capsule = 0;
> >  	dump_sig = 0;
> >  	for (;;) {
> >  		c = getopt_long(argc, argv, opts_short, options, &idx);
> > @@ -691,22 +760,44 @@ int main(int argc, char **argv)
> >  			dump_sig = 1;
> >  			break;
> >  #endif /* CONFIG_TOOLS_LIBCRYPTO */
> > +		case 'A':
> > +			accept_fw_capsule = 1;
> > +			break;
> > +		case 'R':
> > +			revert_fw_capsule = 1;
> > +			break;
> >  		case 'h':
> >  			print_usage();
> >  			exit(EXIT_SUCCESS);
> >  		}
> >  	}
> >  
> > +	if (accept_fw_capsule && revert_fw_capsule) {
> > +		fprintf(stderr,
> > +			"Select either of Accept or Revert capsule generation\n");
> > +		exit(EXIT_FAILURE);
> > +	}
> > +
> > +	empty_capsule = (accept_fw_capsule || revert_fw_capsule);
> > +
> >  	/* check necessary parameters */
> > -	if ((argc != optind + 2) || !guid ||
> > -	    ((privkey_file && !cert_file) ||
> > +	if ((!empty_capsule && argc != optind + 2) ||
> > +	    (empty_capsule && argc != optind + 1) ||
> > +	    (!revert_fw_capsule && !guid) || ((privkey_file && !cert_file) ||
> >  	     (!privkey_file && cert_file))) {
> 
> Well, the error condition looks complicated due to mixing two cases
> and can be hard to maintain in the future. How about
> 	if (!empty_capsule &&
>                 ((argc != optind + 2) || !guid ||
>                  ((privkey_file && !cert_file) ||
>                   (!privkey_file && cert_file))) ||
>             empty_capsule &&
>                 ((argc != optind + 1) ||
>                  (accept_fw_capsule && revert_fw_capsule) ||
>                  (accept_fw_capsule && !guid))  # arguable as mentioned above
>                  (revert_fw_capsule && guid))
>         ...

I've got one concern here; Can we sign an empty capsule file?
I think we should.
If so, the help message (by print_usage()) doesn't reflect it.

-Takahiro Akashi

> 
> >  		print_usage();
> >  		exit(EXIT_FAILURE);
> >  	}
> >  
> > -	if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
> > -			 mcount, privkey_file, cert_file) < 0) {
> > +	if (empty_capsule) {
> > +		if (create_empty_capsule(argv[argc - 1], guid,
> > +					 accept_fw_capsule ? 1 : 0) < 0) {
> 
> The third argument can be simplified to "accept_fw_capsule".
> 
> -Takahiro Akashi
> 
> > +			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.17.1
> > 

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-09 18:40         ` Sughosh Ganu
@ 2022-02-10  1:43           ` Masami Hiramatsu
  2022-02-10  3:14             ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-10  1:43 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

2022年2月10日(木) 3:40 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> hi Masami,
>
> On Wed, 9 Feb 2022 at 17:18, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > 2022年2月9日(水) 18:03 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > >
> > > hi Masami,
> > >
> > > On Wed, 9 Feb 2022 at 10:26, Masami Hiramatsu
> > > <masami.hiramatsu@linaro.org> wrote:
> > > >
> > > > Hi Sughosh,
> > > >
> > > > While porting mdata-sf driver, I'm confusing on the devicetree
> > > > usage.
> > > >
> > > > 2022年2月8日(火) 3:21 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > > >
> > > > > +int fwu_get_mdata_device(struct udevice **mdata_dev)
> > > > > +{
> > > > > +       u32 phandle;
> > > > > +       int ret, size;
> > > > > +       struct udevice *dev, *child;
> > > > > +       ofnode fwu_mdata_node;
> > > > > +       const fdt32_t *phandle_p = NULL;
> > > > > +
> > > > > +       fwu_mdata_node = ofnode_path("/fwu-mdata");
> > > > > +       if (!ofnode_valid(fwu_mdata_node)) {
> > > > > +               log_err("fwu-node not found\n");
> > > > > +               return -ENOENT;
> > > > > +       }
> > > >
> > > > So this seems to get the udevice from path, but I think fwu-mdata node
> > > > has "u-boot,fwu-mdata" compatible property, in that case probe function
> > > > already gets the node. Why would you search it again by path?
> > >
> > > Okay. Is there some other api that I can use which is faster than the
> > > approach currently taken? If so, do let me know.
> >
> > I thought the ofnode which has "u-boot,fwu-mdata" compatible property
> > is passed to fwu_mdata_gpt_blk_probe(), and that is , doesn't it?
> >
> > If so, as you show in the example,
> >        fwu-mdata {
> >                compatible = "u-boot,fwu-mdata";
> >                fwu-mdata-store = <&sdmmc1>;
> >        };
> >
> > you already got the "/fwu-mdata" node. You don't need any API to find
> > that node because you already has that. That is what I meant.
>
> The probe function gets passed the corresponding udevice structure.
> This structure contains node_ member, which should correspond to the
> device node. I will try to use this member instead of searching for
> the node.

Yeah, you can use "dev_ofnode()".

> > > > > +
> > > > > +       phandle_p = ofnode_get_property(fwu_mdata_node, "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),
> > > > > +                                         &dev);
> > > > > +       if (ret)
> > > > > +               return ret;
> > > > > +
> > > > > +       ret = -ENODEV;
> > > > > +       for (device_find_first_child(dev, &child); child;
> > > > > +            device_find_next_child(&child)) {
> > > > > +               if (device_get_uclass_id(child) == UCLASS_BLK) {
> > > > > +                       *mdata_dev = child;
> > > >
> > > > I thought that the blk device node directly passed by the
> > > > "fwu-mdata-store" property. Would we need to search it from
> > > > children nodes?
> > >
> > > What the device tree is pointing to is the device like the mmc, which
> > > is described through a device tree node. The block device is the child
> > > of this device, which is not described in the device tree. The driver
> > > finally needs the block device.
> >
> > Ah, OK. Can't we specify the block device node to  "fwu-mdata-store"
> > directly?
>
> I don't think so, since the fwu-mdata-store is pointing to one of the
> nodes in the device tree -- the block device does not show up as node
> on the device tree.

Ah, I got it. Indeed. In my case spi-nor device will be on the devicetree,
but mmc media is not. Sorry about that.

In that case, does fwu-mdata-store refer the controller node?
If there are several blk devices under that (I'm not sure it can be)
mdata must be in the first device (maybe decided by scanning order?).
I think this should be documented for who ports AB-update on
another platform.

> > > > BTW, if we can use the devicetree, can we define the number of banks
> > > > and the number of images can be described too?
> > >
> > > It is much easier to handle if these values are defined through
> > > Kconfig symbols. That way, this gets directly included in the config
> > > file, and can be used directly in the fwu_mdata.h metadata structure.
> >
> > Yes, it is easier to implement. And that means the firmware bank
> > configuration is embedded in the firmware binary (code) instead
> > of the configuration data (devicetree).
> > For the same reason I think dfu_alt_info (or the basement info like
> > device and offsets) should be in the devicetree. Current implementation
> > is very fragile (because dfu_alt_info can be changed by the user) or
> > fixed in the code (like stm32, it generates the dfu_alt_info by the
> > platform driver.)
> >
> > >
> > > > Of course as I said in the other thread, I would like to put the
> > > > dfu_alt_info like information in the devicetree too.
> > > > (But it maybe different from this discussion)
> > >
> > > Just curious, why do you need to define a variable like dfu_alt_info
> > > in a device tree. If this has already been described earlier, you can
> > > point me to that discussion. Trying to understand what benefit does
> > > having the variables defined in a device tree brings. Thanks.
> >
> > If we can consolidate the configuration information related to the
> > firmware layout on the devicetree, it is very easy to understand
> > and manage the firmware update only by checking the devicetree.
> > Current design is very fragile from the consistency viewpoint,
> > because there are 3 different information we are using for FWU,
> > Kconfig, devicetree and u-boot env-variables. If one of them
> > sets inconsistent value, FWU may not work as we expected.
>
> I get your point. But I think generating the dfu_alt_info at runtime,
> like how it is done for the ST platforms is in general a better
> method, as against using a static variable defined in the device tree.

Yeah, the GPT based one is able to store this information on the GPT,
and it must be a primary definition.

> With runtime generation of the variable, the same code can be used on
> multiple platforms and can be generated at runtime -- I feel that is
> better than defining the variable in every platform's device tree.

I don't agree this point at least for non-GPT devices, since the
firmware storage layout depends on the platform hardware configuration
statically in such cases.
Of course if the device uses GPT to store the firmware, we have to
follow the GPT layout and FWU Metadata to find the corresponding
firmware partition.

> Btw, there is also provision to define the variable(or part of it)
> statically through Kconfig variables. As against your concern about
> the feature using multiple methods for stating information, it is
> indeed valid. But I guess we can have documentation explaining how
> each of that information needs to be defined. Thanks.

Yeah, even using GPT, we need to set correct UUID to the FWU metadata,
and the metadata depends on Kconfig if we keep putting the #of
images-per-bank and the #of banks in the Kconfig, and storage
(controller) is defined in the devicetree.

And I still feel this "chain of definitions" seems a bit fragile. This
fragile comes from the FWU metadata is not enough self-described (it
has no the #of images-per-bank and the #of banks, without this
information we can not decode FWU metadata itself.)
Anyway, if we can define the #of images-per-bank and the #of banks in
the devicetree, we don't need to change the binary but just changing
the devicetree for the different products which has different firmware
layout. I think that is more flexible.

Thank you,

>
> -sughosh
>
> >
> > That is my impression felt from porting AB update on the DeveloperBox platform.
> >
> > Thank you,
> >
> > >
> > > -sughosh
> > >
> > > >
> > > > Thank you,
> > > >
> > > >
> > > > > +                       ret = 0;
> > > > > +               }
> > > > > +       }
> > > > > +
> > > > > +       return ret;
> > > > > +}
> > > > > +
> > > > > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > > > > +{
> > > > > +       int ret;
> > > > > +       struct udevice *mdata_dev = NULL;
> > > > > +
> > > > > +       ret = fwu_get_mdata_device(&mdata_dev);
> > > > > +       if (ret)
> > > > > +               return ret;
> > > > > +
> > > > > +       dev_set_priv(dev, mdata_dev);
> > > > > +
> > > > > +       return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > > > > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > > > > +       .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" },
> > > >
> > > > > +       { }
> > > > > +};
> > > > > +
> > > > > +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,
> > > > > +};
> > > > > diff --git a/include/fwu.h b/include/fwu.h
> > > > > index 5a99c579fc..2c7db2dff9 100644
> > > > > --- a/include/fwu.h
> > > > > +++ b/include/fwu.h
> > > > > @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> > > > > +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.17.1
> > > > >
> > > >
> > > >
> > > > --
> > > > Masami Hiramatsu
> >
> >
> >
> > --
> > Masami Hiramatsu



-- 
Masami Hiramatsu

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-07 18:19 ` [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
@ 2022-02-10  2:48   ` AKASHI Takahiro
  2022-02-10  7:18     ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: AKASHI Takahiro @ 2022-02-10  2:48 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> The FWU Multi Banks Update feature allows updating different types of
> updatable firmware images on the platform. These image types are
> identified using the ImageTypeId GUID value. Add support in the
> GetImageInfo function of the FMP protocol to get the GUID values for
> the individual images and populate these in the image descriptor for
> the corresponding images.

After re-thinking of your approach here, I would have to say NAK.

You use ImageTypeId to identify a particular firmware object.
(By "object," I mean one of firmware instances represented by "dfu_alto_info".
Please don't confuse it with the binary blob embedded in a capsule file.)
But ImageTypeId is not for that purpose, at least, as my intention
in initially implementing capsule framework and FMP drivers.

1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
   either FIT FMP driver or Raw FMP driver.
2) Each firmware object handled by a given FMP driver can further be
   identified by ImageIndex. 

My implementation of efi_fmp_find() does (1) and Raw FMP driver does
(2) in efi_firmware_raw_set_image() which takes "image_index" as
a parameter.

Using ImageTypeId as an identifier is simply wrong in my opinion and
doesn't meet the UEFI specification.

-Takahiro Akashi


> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> 
> Changes since V3:
> * Define a weak function fill_image_type_guid_array for populating the
>   image descriptor array with u-boot's raw and fit image GUIDs
> 
>  include/efi_loader.h          |  2 +
>  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
>  2 files changed, 66 insertions(+), 7 deletions(-)
> 
> diff --git a/include/efi_loader.h b/include/efi_loader.h
> index f4860e87fc..ae60de0be5 100644
> --- a/include/efi_loader.h
> +++ b/include/efi_loader.h
> @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
>  efi_status_t efi_load_capsule_drivers(void);
>  
>  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> +					efi_guid_t **part_guid_arr);
>  #endif /* _EFI_LOADER_H */
> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> index a1b88dbfc2..5642be9f9a 100644
> --- a/lib/efi_loader/efi_firmware.c
> +++ b/lib/efi_loader/efi_firmware.c
> @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
>  	return EFI_EXIT(EFI_UNSUPPORTED);
>  }
>  
> +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> +					       efi_guid_t **part_guid_arr)
> +{
> +	int i;
> +	int dfu_num = 0;
> +	efi_guid_t *guid_arr;
> +	struct dfu_entity *dfu;
> +	efi_status_t ret = EFI_SUCCESS;
> +
> +	dfu_init_env_entities(NULL, NULL);
> +
> +	dfu_num = 0;
> +	list_for_each_entry(dfu, &dfu_list, list) {
> +		dfu_num++;
> +	}
> +
> +	if (!dfu_num) {
> +		log_warning("Probably dfu_alt_info not defined\n");
> +		ret = EFI_NOT_READY;
> +		goto out;
> +	}
> +
> +	*part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> +	if (!*part_guid_arr) {
> +		ret = EFI_OUT_OF_RESOURCES;
> +		goto out;
> +	}
> +
> +	guid_arr = *part_guid_arr;
> +	for (i = 0; i < dfu_num; i++) {
> +		guidcpy(guid_arr, guid);
> +		++guid_arr;
> +	}
> +
> +out:
> +	dfu_free_entities();
> +
> +	return ret;
> +}
> +
>  /**
>   * efi_get_dfu_info - return information about the current firmware image
>   * @this:			Protocol instance
> @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
>   * @descriptor_version:		Pointer to version number
>   * @descriptor_count:		Pointer to number of descriptors
>   * @descriptor_size:		Pointer to descriptor size
> - * package_version:		Package version
> - * package_version_name:	Package version's name
> - * image_type:			Image type GUID
> + * @package_version:		Package version
> + * @package_version_name:	Package version's name
> + * @guid_array:			Image type GUID array
>   *
>   * Return information bout the current firmware image in @image_info.
>   * @image_info will consist of a number of descriptors.
> @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
>  	efi_uintn_t *descriptor_size,
>  	u32 *package_version,
>  	u16 **package_version_name,
> -	const efi_guid_t *image_type)
> +	const efi_guid_t *guid_array)
>  {
>  	struct dfu_entity *dfu;
>  	size_t names_len, total_size;
> @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
>  	next = name;
>  	list_for_each_entry(dfu, &dfu_list, list) {
>  		image_info[i].image_index = dfu->alt + 1;
> -		image_info[i].image_type_id = *image_type;
> +		image_info[i].image_type_id = guid_array[i];
>  		image_info[i].image_id = dfu->alt;
>  
>  		/* copy the DFU entity name */
> @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
>  	u16 **package_version_name)
>  {
>  	efi_status_t ret;
> +	efi_guid_t *part_guid_arr = NULL;
>  
>  	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
>  		  image_info_size, image_info,
> @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
>  	     !descriptor_size || !package_version || !package_version_name))
>  		return EFI_EXIT(EFI_INVALID_PARAMETER);
>  
> +	ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> +					 &part_guid_arr);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
>  	ret = efi_get_dfu_info(image_info_size, image_info,
>  			       descriptor_version, descriptor_count,
>  			       descriptor_size,
>  			       package_version, package_version_name,
> -			       &efi_firmware_image_type_uboot_fit);
> +			       part_guid_arr);
>  
> +out:
> +	free(part_guid_arr);
>  	return EFI_EXIT(ret);
>  }
>  
> @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
>  	u16 **package_version_name)
>  {
>  	efi_status_t ret = EFI_SUCCESS;
> +	efi_guid_t *part_guid_arr = NULL;
>  
>  	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
>  		  image_info_size, image_info,
> @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
>  	     !descriptor_size || !package_version || !package_version_name))
>  		return EFI_EXIT(EFI_INVALID_PARAMETER);
>  
> +	ret = fill_image_type_guid_array(
> +		&efi_firmware_image_type_uboot_raw,
> +		&part_guid_arr);
> +	if (ret != EFI_SUCCESS)
> +		goto out;
> +
>  	ret = efi_get_dfu_info(image_info_size, image_info,
>  			       descriptor_version, descriptor_count,
>  			       descriptor_size,
>  			       package_version, package_version_name,
> -			       &efi_firmware_image_type_uboot_raw);
> +			       part_guid_arr);
>  
> +out:
> +	free(part_guid_arr);
>  	return EFI_EXIT(ret);
>  }
>  
> -- 
> 2.17.1
> 

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-10  1:43           ` Masami Hiramatsu
@ 2022-02-10  3:14             ` Masami Hiramatsu
  2022-02-10 12:25               ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-10  3:14 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

2022年2月10日(木) 10:43 Masami Hiramatsu <masami.hiramatsu@linaro.org>:
>
> > > > > Of course as I said in the other thread, I would like to put the
> > > > > dfu_alt_info like information in the devicetree too.
> > > > > (But it maybe different from this discussion)
> > > >
> > > > Just curious, why do you need to define a variable like dfu_alt_info
> > > > in a device tree. If this has already been described earlier, you can
> > > > point me to that discussion. Trying to understand what benefit does
> > > > having the variables defined in a device tree brings. Thanks.
> > >
> > > If we can consolidate the configuration information related to the
> > > firmware layout on the devicetree, it is very easy to understand
> > > and manage the firmware update only by checking the devicetree.
> > > Current design is very fragile from the consistency viewpoint,
> > > because there are 3 different information we are using for FWU,
> > > Kconfig, devicetree and u-boot env-variables. If one of them
> > > sets inconsistent value, FWU may not work as we expected.
> >
> > I get your point. But I think generating the dfu_alt_info at runtime,
> > like how it is done for the ST platforms is in general a better
> > method, as against using a static variable defined in the device tree.
>
> Yeah, the GPT based one is able to store this information on the GPT,
> and it must be a primary definition.
>
> > With runtime generation of the variable, the same code can be used on
> > multiple platforms and can be generated at runtime -- I feel that is
> > better than defining the variable in every platform's device tree.
>
> I don't agree this point at least for non-GPT devices, since the
> firmware storage layout depends on the platform hardware configuration
> statically in such cases.

I changed my mind, it can be solved if we have "uuid" property for
each partition in the devicetree. I will explain later.

> Of course if the device uses GPT to store the firmware, we have to
> follow the GPT layout and FWU Metadata to find the corresponding
> firmware partition.
>
> > Btw, there is also provision to define the variable(or part of it)
> > statically through Kconfig variables. As against your concern about
> > the feature using multiple methods for stating information, it is
> > indeed valid. But I guess we can have documentation explaining how
> > each of that information needs to be defined. Thanks.
>
> Yeah, even using GPT, we need to set correct UUID to the FWU metadata,
> and the metadata depends on Kconfig if we keep putting the #of
> images-per-bank and the #of banks in the Kconfig, and storage

Sorry, I confused. there are "#of images and #of banks per image".

> (controller) is defined in the devicetree.
>
> And I still feel this "chain of definitions" seems a bit fragile. This
> fragile comes from the FWU metadata is not enough self-described (it
> has no the #of images-per-bank and the #of banks, without this
> information we can not decode FWU metadata itself.)
> Anyway, if we can define the #of images-per-bank and the #of banks in
> the devicetree, we don't need to change the binary but just changing
> the devicetree for the different products which has different firmware
> layout. I think that is more flexible.

What I would like to suggest is

/* For GPT BLK backend */
fwu_mdata {
    compatible = "u-boot,fwu-mdata-gpt";
    fwu-mdata-store = <&mmc1>;
    /* No need to specify the mdata partition, because it finds the
mdata by partition type uuid. */
    banks = <2>;
    images-per-bank = <1>;
};

/* For SF backend */
fwu_mdata {
    compatible = "u-boot,fwu-mdata-sf";
    fwu-mdata-store = <&spi-flash0>;
    mdata-offsets = <500000, 520000>; /* Or specified by partition label? */
    banks = <6>;
    images-per-bank = <1>;
};

Note that this is only for the metadata, the real firmware layout issue
still exists. If we can add "uuid" property for the fixed-partitions node
as a additional property, e.g.

spi-flash@0 {
   partitions {
       compatible = "fixed-partitions";
       ...
       uuid = "aaaaaaaa-bbbb-cccc-dddd-eeeeffffgggg";
       ...
       partition@600000 {
           label = "Firmware-Bank0";
           reg = <600000, 400000>;
           uuid = "12345678-aaaa-bbbb-cccc-0123456789ab";
       };
       ...
   };
};

Then we can decode the real fwu-mdata and find corresponding
partitions, and able to build dfu_alt_info in runtime.

What would you think?

Thank you,

>
> Thank you,
>
> >
> > -sughosh
> >
> > >
> > > That is my impression felt from porting AB update on the DeveloperBox platform.
> > >
> > > Thank you,
> > >
> > > >
> > > > -sughosh
> > > >
> > > > >
> > > > > Thank you,
> > > > >
> > > > >
> > > > > > +                       ret = 0;
> > > > > > +               }
> > > > > > +       }
> > > > > > +
> > > > > > +       return ret;
> > > > > > +}
> > > > > > +
> > > > > > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > > > > > +{
> > > > > > +       int ret;
> > > > > > +       struct udevice *mdata_dev = NULL;
> > > > > > +
> > > > > > +       ret = fwu_get_mdata_device(&mdata_dev);
> > > > > > +       if (ret)
> > > > > > +               return ret;
> > > > > > +
> > > > > > +       dev_set_priv(dev, mdata_dev);
> > > > > > +
> > > > > > +       return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > > > > > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > > > > > +       .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" },
> > > > >
> > > > > > +       { }
> > > > > > +};
> > > > > > +
> > > > > > +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,
> > > > > > +};
> > > > > > diff --git a/include/fwu.h b/include/fwu.h
> > > > > > index 5a99c579fc..2c7db2dff9 100644
> > > > > > --- a/include/fwu.h
> > > > > > +++ b/include/fwu.h
> > > > > > @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> > > > > > +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.17.1
> > > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Masami Hiramatsu
> > >
> > >
> > >
> > > --
> > > Masami Hiramatsu
>
>
>
> --
> Masami Hiramatsu



--
Masami Hiramatsu

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-10  2:48   ` AKASHI Takahiro
@ 2022-02-10  7:18     ` Sughosh Ganu
  2022-02-10  7:58       ` AKASHI Takahiro
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-10  7:18 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Heinrich Schuchardt,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

hi Takahiro,

On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Hi Sughosh,
>
> On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > The FWU Multi Banks Update feature allows updating different types of
> > updatable firmware images on the platform. These image types are
> > identified using the ImageTypeId GUID value. Add support in the
> > GetImageInfo function of the FMP protocol to get the GUID values for
> > the individual images and populate these in the image descriptor for
> > the corresponding images.
>
> After re-thinking of your approach here, I would have to say NAK.
>
> You use ImageTypeId to identify a particular firmware object.
> (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> Please don't confuse it with the binary blob embedded in a capsule file.)
> But ImageTypeId is not for that purpose, at least, as my intention
> in initially implementing capsule framework and FMP drivers.
>
> 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
>    either FIT FMP driver or Raw FMP driver.

I believe the identification of an FMP protocol should be done by the
FMP GUID, which is what is done in efi_fmp_find. The ImageTypeId is
nowhere involved in this identification.

> 2) Each firmware object handled by a given FMP driver can further be
>    identified by ImageIndex.
>
> My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> (2) in efi_firmware_raw_set_image() which takes "image_index" as
> a parameter.
>
> Using ImageTypeId as an identifier is simply wrong in my opinion and
> doesn't meet the UEFI specification.

So, as per what you are stating, all payloads under a given
EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
values, the check in efi_fmp_find to compare the UpdateImageTypeId
with the ImageTypeId retrieved from the image descriptor would simply
fail.

I think this interpretation of the UEFI spec is incorrect, since the
spec states that the ImageTypeId and the UpdateImageTypeId are fields
used to identify the firmware component targeted for the update. If
all values in the image descriptor array and the UpdateImageTypeId are
the same, why have this field in the first place for individual
images.

-sughosh

>
> -Takahiro Akashi
>
>
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >
> > Changes since V3:
> > * Define a weak function fill_image_type_guid_array for populating the
> >   image descriptor array with u-boot's raw and fit image GUIDs
> >
> >  include/efi_loader.h          |  2 +
> >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> >  2 files changed, 66 insertions(+), 7 deletions(-)
> >
> > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > index f4860e87fc..ae60de0be5 100644
> > --- a/include/efi_loader.h
> > +++ b/include/efi_loader.h
> > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> >  efi_status_t efi_load_capsule_drivers(void);
> >
> >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > +                                     efi_guid_t **part_guid_arr);
> >  #endif /* _EFI_LOADER_H */
> > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > index a1b88dbfc2..5642be9f9a 100644
> > --- a/lib/efi_loader/efi_firmware.c
> > +++ b/lib/efi_loader/efi_firmware.c
> > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> >       return EFI_EXIT(EFI_UNSUPPORTED);
> >  }
> >
> > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > +                                            efi_guid_t **part_guid_arr)
> > +{
> > +     int i;
> > +     int dfu_num = 0;
> > +     efi_guid_t *guid_arr;
> > +     struct dfu_entity *dfu;
> > +     efi_status_t ret = EFI_SUCCESS;
> > +
> > +     dfu_init_env_entities(NULL, NULL);
> > +
> > +     dfu_num = 0;
> > +     list_for_each_entry(dfu, &dfu_list, list) {
> > +             dfu_num++;
> > +     }
> > +
> > +     if (!dfu_num) {
> > +             log_warning("Probably dfu_alt_info not defined\n");
> > +             ret = EFI_NOT_READY;
> > +             goto out;
> > +     }
> > +
> > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > +     if (!*part_guid_arr) {
> > +             ret = EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +
> > +     guid_arr = *part_guid_arr;
> > +     for (i = 0; i < dfu_num; i++) {
> > +             guidcpy(guid_arr, guid);
> > +             ++guid_arr;
> > +     }
> > +
> > +out:
> > +     dfu_free_entities();
> > +
> > +     return ret;
> > +}
> > +
> >  /**
> >   * efi_get_dfu_info - return information about the current firmware image
> >   * @this:                    Protocol instance
> > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> >   * @descriptor_version:              Pointer to version number
> >   * @descriptor_count:                Pointer to number of descriptors
> >   * @descriptor_size:         Pointer to descriptor size
> > - * package_version:          Package version
> > - * package_version_name:     Package version's name
> > - * image_type:                       Image type GUID
> > + * @package_version:         Package version
> > + * @package_version_name:    Package version's name
> > + * @guid_array:                      Image type GUID array
> >   *
> >   * Return information bout the current firmware image in @image_info.
> >   * @image_info will consist of a number of descriptors.
> > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> >       efi_uintn_t *descriptor_size,
> >       u32 *package_version,
> >       u16 **package_version_name,
> > -     const efi_guid_t *image_type)
> > +     const efi_guid_t *guid_array)
> >  {
> >       struct dfu_entity *dfu;
> >       size_t names_len, total_size;
> > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> >       next = name;
> >       list_for_each_entry(dfu, &dfu_list, list) {
> >               image_info[i].image_index = dfu->alt + 1;
> > -             image_info[i].image_type_id = *image_type;
> > +             image_info[i].image_type_id = guid_array[i];
> >               image_info[i].image_id = dfu->alt;
> >
> >               /* copy the DFU entity name */
> > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> >       u16 **package_version_name)
> >  {
> >       efi_status_t ret;
> > +     efi_guid_t *part_guid_arr = NULL;
> >
> >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> >                 image_info_size, image_info,
> > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> >            !descriptor_size || !package_version || !package_version_name))
> >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> >
> > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > +                                      &part_guid_arr);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> >       ret = efi_get_dfu_info(image_info_size, image_info,
> >                              descriptor_version, descriptor_count,
> >                              descriptor_size,
> >                              package_version, package_version_name,
> > -                            &efi_firmware_image_type_uboot_fit);
> > +                            part_guid_arr);
> >
> > +out:
> > +     free(part_guid_arr);
> >       return EFI_EXIT(ret);
> >  }
> >
> > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> >       u16 **package_version_name)
> >  {
> >       efi_status_t ret = EFI_SUCCESS;
> > +     efi_guid_t *part_guid_arr = NULL;
> >
> >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> >                 image_info_size, image_info,
> > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> >            !descriptor_size || !package_version || !package_version_name))
> >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> >
> > +     ret = fill_image_type_guid_array(
> > +             &efi_firmware_image_type_uboot_raw,
> > +             &part_guid_arr);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
> > +
> >       ret = efi_get_dfu_info(image_info_size, image_info,
> >                              descriptor_version, descriptor_count,
> >                              descriptor_size,
> >                              package_version, package_version_name,
> > -                            &efi_firmware_image_type_uboot_raw);
> > +                            part_guid_arr);
> >
> > +out:
> > +     free(part_guid_arr);
> >       return EFI_EXIT(ret);
> >  }
> >
> > --
> > 2.17.1
> >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-10  7:18     ` Sughosh Ganu
@ 2022-02-10  7:58       ` AKASHI Takahiro
  2022-02-10 10:10         ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: AKASHI Takahiro @ 2022-02-10  7:58 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> hi Takahiro,
> 
> On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > The FWU Multi Banks Update feature allows updating different types of
> > > updatable firmware images on the platform. These image types are
> > > identified using the ImageTypeId GUID value. Add support in the
> > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > the individual images and populate these in the image descriptor for
> > > the corresponding images.
> >
> > After re-thinking of your approach here, I would have to say NAK.
> >
> > You use ImageTypeId to identify a particular firmware object.
> > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > Please don't confuse it with the binary blob embedded in a capsule file.)
> > But ImageTypeId is not for that purpose, at least, as my intention
> > in initially implementing capsule framework and FMP drivers.
> >
> > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> >    either FIT FMP driver or Raw FMP driver.
> 
> I believe the identification of an FMP protocol should be done by the
> FMP GUID,

What does FMP GUID stand for?

> which is what is done in efi_fmp_find. The ImageTypeId is
> nowhere involved in this identification.

Please take a look at efi_capsule_update_firmware() carefully.
efi_find_fmp() is called with the image's update_image_type_id
which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
(see create_fwbin()).

> > 2) Each firmware object handled by a given FMP driver can further be
> >    identified by ImageIndex.
> >
> > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > a parameter.
> >
> > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > doesn't meet the UEFI specification.
> 
> So, as per what you are stating, all payloads under a given
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> with the ImageTypeId retrieved from the image descriptor would simply
> fail.

I don't follow your point.
Please elaborate a bit more.

> I think this interpretation of the UEFI spec is incorrect, since the
> spec states that the ImageTypeId and the UpdateImageTypeId are fields
> used to identify the firmware component targeted for the update. If
> all values in the image descriptor array and the UpdateImageTypeId are
> the same, why have this field in the first place for individual
> images.

As I said, ImageIndex is for that purpose.

-Takahiro Akashi

> 
> -sughosh
> 
> >
> > -Takahiro Akashi
> >
> >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > ---
> > >
> > > Changes since V3:
> > > * Define a weak function fill_image_type_guid_array for populating the
> > >   image descriptor array with u-boot's raw and fit image GUIDs
> > >
> > >  include/efi_loader.h          |  2 +
> > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > index f4860e87fc..ae60de0be5 100644
> > > --- a/include/efi_loader.h
> > > +++ b/include/efi_loader.h
> > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > >  efi_status_t efi_load_capsule_drivers(void);
> > >
> > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > +                                     efi_guid_t **part_guid_arr);
> > >  #endif /* _EFI_LOADER_H */
> > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > index a1b88dbfc2..5642be9f9a 100644
> > > --- a/lib/efi_loader/efi_firmware.c
> > > +++ b/lib/efi_loader/efi_firmware.c
> > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > >  }
> > >
> > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > +                                            efi_guid_t **part_guid_arr)
> > > +{
> > > +     int i;
> > > +     int dfu_num = 0;
> > > +     efi_guid_t *guid_arr;
> > > +     struct dfu_entity *dfu;
> > > +     efi_status_t ret = EFI_SUCCESS;
> > > +
> > > +     dfu_init_env_entities(NULL, NULL);
> > > +
> > > +     dfu_num = 0;
> > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > +             dfu_num++;
> > > +     }
> > > +
> > > +     if (!dfu_num) {
> > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > +             ret = EFI_NOT_READY;
> > > +             goto out;
> > > +     }
> > > +
> > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > +     if (!*part_guid_arr) {
> > > +             ret = EFI_OUT_OF_RESOURCES;
> > > +             goto out;
> > > +     }
> > > +
> > > +     guid_arr = *part_guid_arr;
> > > +     for (i = 0; i < dfu_num; i++) {
> > > +             guidcpy(guid_arr, guid);
> > > +             ++guid_arr;
> > > +     }
> > > +
> > > +out:
> > > +     dfu_free_entities();
> > > +
> > > +     return ret;
> > > +}
> > > +
> > >  /**
> > >   * efi_get_dfu_info - return information about the current firmware image
> > >   * @this:                    Protocol instance
> > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > >   * @descriptor_version:              Pointer to version number
> > >   * @descriptor_count:                Pointer to number of descriptors
> > >   * @descriptor_size:         Pointer to descriptor size
> > > - * package_version:          Package version
> > > - * package_version_name:     Package version's name
> > > - * image_type:                       Image type GUID
> > > + * @package_version:         Package version
> > > + * @package_version_name:    Package version's name
> > > + * @guid_array:                      Image type GUID array
> > >   *
> > >   * Return information bout the current firmware image in @image_info.
> > >   * @image_info will consist of a number of descriptors.
> > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > >       efi_uintn_t *descriptor_size,
> > >       u32 *package_version,
> > >       u16 **package_version_name,
> > > -     const efi_guid_t *image_type)
> > > +     const efi_guid_t *guid_array)
> > >  {
> > >       struct dfu_entity *dfu;
> > >       size_t names_len, total_size;
> > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > >       next = name;
> > >       list_for_each_entry(dfu, &dfu_list, list) {
> > >               image_info[i].image_index = dfu->alt + 1;
> > > -             image_info[i].image_type_id = *image_type;
> > > +             image_info[i].image_type_id = guid_array[i];
> > >               image_info[i].image_id = dfu->alt;
> > >
> > >               /* copy the DFU entity name */
> > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > >       u16 **package_version_name)
> > >  {
> > >       efi_status_t ret;
> > > +     efi_guid_t *part_guid_arr = NULL;
> > >
> > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > >                 image_info_size, image_info,
> > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > >            !descriptor_size || !package_version || !package_version_name))
> > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > >
> > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > +                                      &part_guid_arr);
> > > +     if (ret != EFI_SUCCESS)
> > > +             goto out;
> > > +
> > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > >                              descriptor_version, descriptor_count,
> > >                              descriptor_size,
> > >                              package_version, package_version_name,
> > > -                            &efi_firmware_image_type_uboot_fit);
> > > +                            part_guid_arr);
> > >
> > > +out:
> > > +     free(part_guid_arr);
> > >       return EFI_EXIT(ret);
> > >  }
> > >
> > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > >       u16 **package_version_name)
> > >  {
> > >       efi_status_t ret = EFI_SUCCESS;
> > > +     efi_guid_t *part_guid_arr = NULL;
> > >
> > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > >                 image_info_size, image_info,
> > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > >            !descriptor_size || !package_version || !package_version_name))
> > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > >
> > > +     ret = fill_image_type_guid_array(
> > > +             &efi_firmware_image_type_uboot_raw,
> > > +             &part_guid_arr);
> > > +     if (ret != EFI_SUCCESS)
> > > +             goto out;
> > > +
> > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > >                              descriptor_version, descriptor_count,
> > >                              descriptor_size,
> > >                              package_version, package_version_name,
> > > -                            &efi_firmware_image_type_uboot_raw);
> > > +                            part_guid_arr);
> > >
> > > +out:
> > > +     free(part_guid_arr);
> > >       return EFI_EXIT(ret);
> > >  }
> > >
> > > --
> > > 2.17.1
> > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-10  7:58       ` AKASHI Takahiro
@ 2022-02-10 10:10         ` Sughosh Ganu
  2022-02-14  3:24           ` AKASHI Takahiro
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-10 10:10 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Heinrich Schuchardt,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > hi Takahiro,
> >
> > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > Hi Sughosh,
> > >
> > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > The FWU Multi Banks Update feature allows updating different types of
> > > > updatable firmware images on the platform. These image types are
> > > > identified using the ImageTypeId GUID value. Add support in the
> > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > the individual images and populate these in the image descriptor for
> > > > the corresponding images.
> > >
> > > After re-thinking of your approach here, I would have to say NAK.
> > >
> > > You use ImageTypeId to identify a particular firmware object.
> > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > But ImageTypeId is not for that purpose, at least, as my intention
> > > in initially implementing capsule framework and FMP drivers.
> > >
> > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > >    either FIT FMP driver or Raw FMP driver.
> >
> > I believe the identification of an FMP protocol should be done by the
> > FMP GUID,
>
> What does FMP GUID stand for?

EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
What I mean is that even when installing the FMP protocol, the call to
efi_install_multiple_protocol_interfaces takes the above FMP GUID as
an argument -- nowhere is the ImageTypeId considered when installing
the protocol.

>
> > which is what is done in efi_fmp_find. The ImageTypeId is
> > nowhere involved in this identification.
>
> Please take a look at efi_capsule_update_firmware() carefully.
> efi_find_fmp() is called with the image's update_image_type_id
> which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> (see create_fwbin()).

I think you are thinking from the point of view of the '--guid' value
that is being passed to the capsule generation tool. But the thing is
that it is the current design(or limitation) of the tool that it takes
only a single guid parameter. So the mkeficapsule tool currently can
generate only a single payload capsule. Please check the
GenerateCapsule script in EDK2. In case of a multi payload based
capsule, individual parameters like the UpdateImageTypeId are passed
through the json file, where each of the UpdateImageTypeId has a
different value per payload.

>
> > > 2) Each firmware object handled by a given FMP driver can further be
> > >    identified by ImageIndex.
> > >
> > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > a parameter.
> > >
> > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > doesn't meet the UEFI specification.
> >
> > So, as per what you are stating, all payloads under a given
> > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > with the ImageTypeId retrieved from the image descriptor would simply
> > fail.
>
> I don't follow your point.
> Please elaborate a bit more.

The current implementation of GetImageInfo, passes either of
EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
descriptor array. So, in case the capsule is generated with a '--guid'
value which is different from these two values, the check in
efi_fmp_find on line 204 will fail. This means that unless the --guid
value passed to the capsule generation is either of u-boot FIT or
u-boot raw, the current FMP protocol for raw devices cannot be used.
Why do we need that restriction. It should be possible to use the raw
FMP protocol for any other type of image types as well.


>
> > I think this interpretation of the UEFI spec is incorrect, since the
> > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > used to identify the firmware component targeted for the update. If
> > all values in the image descriptor array and the UpdateImageTypeId are
> > the same, why have this field in the first place for individual
> > images.
>
> As I said, ImageIndex is for that purpose.

Yes, that is one possible way in the scenario where the ImageIndex is
determined at the capsule generation time. But, for the A/B update
scenario, we do not know the ImageIndex at build time -- this is
determined only at runtime, and is based on the bank to which the
image is to be updated. Which is why I am finding out the alt_num at
runtime in case the FWU Multi Bank feature is enabled. Like I said
above, I do not see a reason why the current FMP protocols should be
restricted to only the u-boot FIT and u-boot raw image types. It is
being extended, without affecting the default non FWU behaviour.

-sughosh

>
> -Takahiro Akashi
>
> >
> > -sughosh
> >
> > >
> > > -Takahiro Akashi
> > >
> > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > ---
> > > >
> > > > Changes since V3:
> > > > * Define a weak function fill_image_type_guid_array for populating the
> > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > >
> > > >  include/efi_loader.h          |  2 +
> > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > >
> > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > index f4860e87fc..ae60de0be5 100644
> > > > --- a/include/efi_loader.h
> > > > +++ b/include/efi_loader.h
> > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > >  efi_status_t efi_load_capsule_drivers(void);
> > > >
> > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > +                                     efi_guid_t **part_guid_arr);
> > > >  #endif /* _EFI_LOADER_H */
> > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > index a1b88dbfc2..5642be9f9a 100644
> > > > --- a/lib/efi_loader/efi_firmware.c
> > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > >  }
> > > >
> > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > +                                            efi_guid_t **part_guid_arr)
> > > > +{
> > > > +     int i;
> > > > +     int dfu_num = 0;
> > > > +     efi_guid_t *guid_arr;
> > > > +     struct dfu_entity *dfu;
> > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > +
> > > > +     dfu_init_env_entities(NULL, NULL);
> > > > +
> > > > +     dfu_num = 0;
> > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > +             dfu_num++;
> > > > +     }
> > > > +
> > > > +     if (!dfu_num) {
> > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > +             ret = EFI_NOT_READY;
> > > > +             goto out;
> > > > +     }
> > > > +
> > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > +     if (!*part_guid_arr) {
> > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > +             goto out;
> > > > +     }
> > > > +
> > > > +     guid_arr = *part_guid_arr;
> > > > +     for (i = 0; i < dfu_num; i++) {
> > > > +             guidcpy(guid_arr, guid);
> > > > +             ++guid_arr;
> > > > +     }
> > > > +
> > > > +out:
> > > > +     dfu_free_entities();
> > > > +
> > > > +     return ret;
> > > > +}
> > > > +
> > > >  /**
> > > >   * efi_get_dfu_info - return information about the current firmware image
> > > >   * @this:                    Protocol instance
> > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > >   * @descriptor_version:              Pointer to version number
> > > >   * @descriptor_count:                Pointer to number of descriptors
> > > >   * @descriptor_size:         Pointer to descriptor size
> > > > - * package_version:          Package version
> > > > - * package_version_name:     Package version's name
> > > > - * image_type:                       Image type GUID
> > > > + * @package_version:         Package version
> > > > + * @package_version_name:    Package version's name
> > > > + * @guid_array:                      Image type GUID array
> > > >   *
> > > >   * Return information bout the current firmware image in @image_info.
> > > >   * @image_info will consist of a number of descriptors.
> > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > >       efi_uintn_t *descriptor_size,
> > > >       u32 *package_version,
> > > >       u16 **package_version_name,
> > > > -     const efi_guid_t *image_type)
> > > > +     const efi_guid_t *guid_array)
> > > >  {
> > > >       struct dfu_entity *dfu;
> > > >       size_t names_len, total_size;
> > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > >       next = name;
> > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > >               image_info[i].image_index = dfu->alt + 1;
> > > > -             image_info[i].image_type_id = *image_type;
> > > > +             image_info[i].image_type_id = guid_array[i];
> > > >               image_info[i].image_id = dfu->alt;
> > > >
> > > >               /* copy the DFU entity name */
> > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > >       u16 **package_version_name)
> > > >  {
> > > >       efi_status_t ret;
> > > > +     efi_guid_t *part_guid_arr = NULL;
> > > >
> > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > >                 image_info_size, image_info,
> > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > >            !descriptor_size || !package_version || !package_version_name))
> > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > >
> > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > +                                      &part_guid_arr);
> > > > +     if (ret != EFI_SUCCESS)
> > > > +             goto out;
> > > > +
> > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > >                              descriptor_version, descriptor_count,
> > > >                              descriptor_size,
> > > >                              package_version, package_version_name,
> > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > +                            part_guid_arr);
> > > >
> > > > +out:
> > > > +     free(part_guid_arr);
> > > >       return EFI_EXIT(ret);
> > > >  }
> > > >
> > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > >       u16 **package_version_name)
> > > >  {
> > > >       efi_status_t ret = EFI_SUCCESS;
> > > > +     efi_guid_t *part_guid_arr = NULL;
> > > >
> > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > >                 image_info_size, image_info,
> > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > >            !descriptor_size || !package_version || !package_version_name))
> > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > >
> > > > +     ret = fill_image_type_guid_array(
> > > > +             &efi_firmware_image_type_uboot_raw,
> > > > +             &part_guid_arr);
> > > > +     if (ret != EFI_SUCCESS)
> > > > +             goto out;
> > > > +
> > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > >                              descriptor_version, descriptor_count,
> > > >                              descriptor_size,
> > > >                              package_version, package_version_name,
> > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > +                            part_guid_arr);
> > > >
> > > > +out:
> > > > +     free(part_guid_arr);
> > > >       return EFI_EXIT(ret);
> > > >  }
> > > >
> > > > --
> > > > 2.17.1
> > > >

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-10  3:14             ` Masami Hiramatsu
@ 2022-02-10 12:25               ` Sughosh Ganu
  2022-02-11  1:58                 ` Masami Hiramatsu
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-10 12:25 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Thu, 10 Feb 2022 at 08:45, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> 2022年2月10日(木) 10:43 Masami Hiramatsu <masami.hiramatsu@linaro.org>:
> >
> > > > > > Of course as I said in the other thread, I would like to put the
> > > > > > dfu_alt_info like information in the devicetree too.
> > > > > > (But it maybe different from this discussion)
> > > > >
> > > > > Just curious, why do you need to define a variable like dfu_alt_info
> > > > > in a device tree. If this has already been described earlier, you can
> > > > > point me to that discussion. Trying to understand what benefit does
> > > > > having the variables defined in a device tree brings. Thanks.
> > > >
> > > > If we can consolidate the configuration information related to the
> > > > firmware layout on the devicetree, it is very easy to understand
> > > > and manage the firmware update only by checking the devicetree.
> > > > Current design is very fragile from the consistency viewpoint,
> > > > because there are 3 different information we are using for FWU,
> > > > Kconfig, devicetree and u-boot env-variables. If one of them
> > > > sets inconsistent value, FWU may not work as we expected.
> > >
> > > I get your point. But I think generating the dfu_alt_info at runtime,
> > > like how it is done for the ST platforms is in general a better
> > > method, as against using a static variable defined in the device tree.
> >
> > Yeah, the GPT based one is able to store this information on the GPT,
> > and it must be a primary definition.
> >
> > > With runtime generation of the variable, the same code can be used on
> > > multiple platforms and can be generated at runtime -- I feel that is
> > > better than defining the variable in every platform's device tree.
> >
> > I don't agree this point at least for non-GPT devices, since the
> > firmware storage layout depends on the platform hardware configuration
> > statically in such cases.
>
> I changed my mind, it can be solved if we have "uuid" property for
> each partition in the devicetree. I will explain later.
>
> > Of course if the device uses GPT to store the firmware, we have to
> > follow the GPT layout and FWU Metadata to find the corresponding
> > firmware partition.
> >
> > > Btw, there is also provision to define the variable(or part of it)
> > > statically through Kconfig variables. As against your concern about
> > > the feature using multiple methods for stating information, it is
> > > indeed valid. But I guess we can have documentation explaining how
> > > each of that information needs to be defined. Thanks.
> >
> > Yeah, even using GPT, we need to set correct UUID to the FWU metadata,
> > and the metadata depends on Kconfig if we keep putting the #of
> > images-per-bank and the #of banks in the Kconfig, and storage
>
> Sorry, I confused. there are "#of images and #of banks per image".
>
> > (controller) is defined in the devicetree.
> >
> > And I still feel this "chain of definitions" seems a bit fragile. This
> > fragile comes from the FWU metadata is not enough self-described (it
> > has no the #of images-per-bank and the #of banks, without this
> > information we can not decode FWU metadata itself.)
> > Anyway, if we can define the #of images-per-bank and the #of banks in
> > the devicetree, we don't need to change the binary but just changing
> > the devicetree for the different products which has different firmware
> > layout. I think that is more flexible.

Do you really feel that using config values for #banks and
#images_per_bank is such a bad idea. With the approach that you
suggest, we will have to use variable sized arrays, and populate the
values in the probe function of every driver. Also, since you are
going to use the same fwu_mdata.h header in your other project, will
you be able to use variable sized arrays there as well. I feel that we
are complicating things without much benefits.

>
> What I would like to suggest is
>
> /* For GPT BLK backend */
> fwu_mdata {
>     compatible = "u-boot,fwu-mdata-gpt";
>     fwu-mdata-store = <&mmc1>;
>     /* No need to specify the mdata partition, because it finds the
> mdata by partition type uuid. */
>     banks = <2>;
>     images-per-bank = <1>;
> };
>
> /* For SF backend */
> fwu_mdata {
>     compatible = "u-boot,fwu-mdata-sf";
>     fwu-mdata-store = <&spi-flash0>;
>     mdata-offsets = <500000, 520000>; /* Or specified by partition label? */
>     banks = <6>;
>     images-per-bank = <1>;
> };

Looks good overall. Should the mdata-offsets property be instead
mdata-parts, where we define the start offset and size of the metadata
partitions. Or are we going to figure out the size of the metadata
partition through some other mechanism.

Also, do are using a different compatible string for every type of
storage device type. Can we not do with a common string instead? I
understand your reasoning here, of trying to identify the driver at
runtime. Just that I wonder if we are going to build multiple drivers
for a platform. Although I do not have a strong opinion on this.

>
> Note that this is only for the metadata, the real firmware layout issue
> still exists. If we can add "uuid" property for the fixed-partitions node
> as a additional property, e.g.
>
> spi-flash@0 {
>    partitions {
>        compatible = "fixed-partitions";
>        ...
>        uuid = "aaaaaaaa-bbbb-cccc-dddd-eeeeffffgggg";
>        ...
>        partition@600000 {
>            label = "Firmware-Bank0";
>            reg = <600000, 400000>;
>            uuid = "12345678-aaaa-bbbb-cccc-0123456789ab";
>        };
>        ...
>    };
> };
>
> Then we can decode the real fwu-mdata and find corresponding
> partitions, and able to build dfu_alt_info in runtime.

This is a sound idea. With this method, we can still use the GUIDs in
the metadata structure, and map those with the partitions using the
above nodes. Only question is, are these partition
nodes(partition@600000) standard, and are defined for all platforms,
for all type of devices(like NOR, Nand). If so, this scheme will work.

-sughosh

>
> What would you think?
>
> Thank you,
>
> >
> > Thank you,
> >
> > >
> > > -sughosh
> > >
> > > >
> > > > That is my impression felt from porting AB update on the DeveloperBox platform.
> > > >
> > > > Thank you,
> > > >
> > > > >
> > > > > -sughosh
> > > > >
> > > > > >
> > > > > > Thank you,
> > > > > >
> > > > > >
> > > > > > > +                       ret = 0;
> > > > > > > +               }
> > > > > > > +       }
> > > > > > > +
> > > > > > > +       return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int fwu_mdata_gpt_blk_probe(struct udevice *dev)
> > > > > > > +{
> > > > > > > +       int ret;
> > > > > > > +       struct udevice *mdata_dev = NULL;
> > > > > > > +
> > > > > > > +       ret = fwu_get_mdata_device(&mdata_dev);
> > > > > > > +       if (ret)
> > > > > > > +               return ret;
> > > > > > > +
> > > > > > > +       dev_set_priv(dev, mdata_dev);
> > > > > > > +
> > > > > > > +       return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static const struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > > > > > > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > > > > > > +       .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" },
> > > > > >
> > > > > > > +       { }
> > > > > > > +};
> > > > > > > +
> > > > > > > +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,
> > > > > > > +};
> > > > > > > diff --git a/include/fwu.h b/include/fwu.h
> > > > > > > index 5a99c579fc..2c7db2dff9 100644
> > > > > > > --- a/include/fwu.h
> > > > > > > +++ b/include/fwu.h
> > > > > > > @@ -43,6 +43,8 @@ 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_get_mdata_device(struct udevice **mdata_dev);
> > > > > > > +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.17.1
> > > > > > >
> > > > > >
> > > > > >
> > > > > > --
> > > > > > Masami Hiramatsu
> > > >
> > > >
> > > >
> > > > --
> > > > Masami Hiramatsu
> >
> >
> >
> > --
> > Masami Hiramatsu
>
>
>
> --
> Masami Hiramatsu

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

* Re: [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices
  2022-02-10 12:25               ` Sughosh Ganu
@ 2022-02-11  1:58                 ` Masami Hiramatsu
  0 siblings, 0 replies; 64+ messages in thread
From: Masami Hiramatsu @ 2022-02-11  1:58 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

2022年2月10日(木) 21:25 Sughosh Ganu <sughosh.ganu@linaro.org>:

>
> hi Masami,
>
> On Thu, 10 Feb 2022 at 08:45, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > 2022年2月10日(木) 10:43 Masami Hiramatsu <masami.hiramatsu@linaro.org>:
> > >
> > > > > > > Of course as I said in the other thread, I would like to put the
> > > > > > > dfu_alt_info like information in the devicetree too.
> > > > > > > (But it maybe different from this discussion)
> > > > > >
> > > > > > Just curious, why do you need to define a variable like dfu_alt_info
> > > > > > in a device tree. If this has already been described earlier, you can
> > > > > > point me to that discussion. Trying to understand what benefit does
> > > > > > having the variables defined in a device tree brings. Thanks.
> > > > >
> > > > > If we can consolidate the configuration information related to the
> > > > > firmware layout on the devicetree, it is very easy to understand
> > > > > and manage the firmware update only by checking the devicetree.
> > > > > Current design is very fragile from the consistency viewpoint,
> > > > > because there are 3 different information we are using for FWU,
> > > > > Kconfig, devicetree and u-boot env-variables. If one of them
> > > > > sets inconsistent value, FWU may not work as we expected.
> > > >
> > > > I get your point. But I think generating the dfu_alt_info at runtime,
> > > > like how it is done for the ST platforms is in general a better
> > > > method, as against using a static variable defined in the device tree.
> > >
> > > Yeah, the GPT based one is able to store this information on the GPT,
> > > and it must be a primary definition.
> > >
> > > > With runtime generation of the variable, the same code can be used on
> > > > multiple platforms and can be generated at runtime -- I feel that is
> > > > better than defining the variable in every platform's device tree.
> > >
> > > I don't agree this point at least for non-GPT devices, since the
> > > firmware storage layout depends on the platform hardware configuration
> > > statically in such cases.
> >
> > I changed my mind, it can be solved if we have "uuid" property for
> > each partition in the devicetree. I will explain later.
> >
> > > Of course if the device uses GPT to store the firmware, we have to
> > > follow the GPT layout and FWU Metadata to find the corresponding
> > > firmware partition.
> > >
> > > > Btw, there is also provision to define the variable(or part of it)
> > > > statically through Kconfig variables. As against your concern about
> > > > the feature using multiple methods for stating information, it is
> > > > indeed valid. But I guess we can have documentation explaining how
> > > > each of that information needs to be defined. Thanks.
> > >
> > > Yeah, even using GPT, we need to set correct UUID to the FWU metadata,
> > > and the metadata depends on Kconfig if we keep putting the #of
> > > images-per-bank and the #of banks in the Kconfig, and storage
> >
> > Sorry, I confused. there are "#of images and #of banks per image".
> >
> > > (controller) is defined in the devicetree.
> > >
> > > And I still feel this "chain of definitions" seems a bit fragile. This
> > > fragile comes from the FWU metadata is not enough self-described (it
> > > has no the #of images-per-bank and the #of banks, without this
> > > information we can not decode FWU metadata itself.)
> > > Anyway, if we can define the #of images-per-bank and the #of banks in
> > > the devicetree, we don't need to change the binary but just changing
> > > the devicetree for the different products which has different firmware
> > > layout. I think that is more flexible.
>
> Do you really feel that using config values for #banks and
> #images_per_bank is such a bad idea. With the approach that you
> suggest, we will have to use variable sized arrays, and populate the
> values in the probe function of every driver. Also, since you are
> going to use the same fwu_mdata.h header in your other project, will
> you be able to use variable sized arrays there as well. I feel that we
> are complicating things without much benefits.

Hm, indeed. It may make us to handle the metadata as a single data
structure on memory. We may need allocate several objects (and arrays)
and decode/encode the data from/to storage device. OK, then let those
parameters keep in the kconfig.

> >
> > What I would like to suggest is
> >
> > /* For GPT BLK backend */
> > fwu_mdata {
> >     compatible = "u-boot,fwu-mdata-gpt";
> >     fwu-mdata-store = <&mmc1>;
> >     /* No need to specify the mdata partition, because it finds the
> > mdata by partition type uuid. */
> >     banks = <2>;
> >     images-per-bank = <1>;
> > };
> >
> > /* For SF backend */
> > fwu_mdata {
> >     compatible = "u-boot,fwu-mdata-sf";
> >     fwu-mdata-store = <&spi-flash0>;
> >     mdata-offsets = <500000, 520000>; /* Or specified by partition label? */
> >     banks = <6>;
> >     images-per-bank = <1>;
> > };
>
> Looks good overall. Should the mdata-offsets property be instead
> mdata-parts, where we define the start offset and size of the metadata
> partitions. Or are we going to figure out the size of the metadata
> partition through some other mechanism.

mdata-parts may only need the label names, since we can find the
partition by name. The partition size can be defined by partitions
node. But do we really need the size? I'm reserving an enough
bigger area for mdata. (And if it is NAND, we need to reserve
"a page" for mdata)

> Also, do are using a different compatible string for every type of
> storage device type. Can we not do with a common string instead? I
> understand your reasoning here, of trying to identify the driver at
> runtime. Just that I wonder if we are going to build multiple drivers
> for a platform. Although I do not have a strong opinion on this.

I can't imagine the case that a platform has different mdata store
at the same time... Anyway, as you said, we need the different
compatible strings for different drivers.

> > Note that this is only for the metadata, the real firmware layout issue
> > still exists. If we can add "uuid" property for the fixed-partitions node
> > as a additional property, e.g.
> >
> > spi-flash@0 {
> >    partitions {
> >        compatible = "fixed-partitions";
> >        ...
> >        uuid = "aaaaaaaa-bbbb-cccc-dddd-eeeeffffgggg";
> >        ...
> >        partition@600000 {
> >            label = "Firmware-Bank0";
> >            reg = <600000, 400000>;
> >            uuid = "12345678-aaaa-bbbb-cccc-0123456789ab";
> >        };
> >        ...
> >    };
> > };
> >
> > Then we can decode the real fwu-mdata and find corresponding
> > partitions, and able to build dfu_alt_info in runtime.
>
> This is a sound idea. With this method, we can still use the GUIDs in
> the metadata structure, and map those with the partitions using the
> above nodes. Only question is, are these partition
> nodes(partition@600000) standard, and are defined for all platforms,
> for all type of devices(like NOR, Nand). If so, this scheme will work.

Yes, as far as I know, now mtd subsystem requires to define the partitions
by the devicetree, and that is acceptable both U-Boot and Linux.
You can find the "fixed-partitions" definition in the Linux dt-bindings.

https://www.kernel.org/doc/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml

I think we can add uuid because there is "additionalProperties: true".

We need the image-type-id uuid, but we can get it from fwu mdata.

Thus, the boot sequence will be
1. parse devicetree.
2. probe fwu-mdata driver and load mdata.
3. platform driver builds dfu_alt_info according to the mdata.
    a. read mdata and identify the partitions ofnode by location uuid.
    b. find partition ofnodes by image-uuid.
    c. build dfu-alt-info by the ofnodes information.
    d. build guid-array by mdata's image-type uuid.

Thank you,

--
Masami Hiramatsu

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

* Re: [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification
  2022-02-08 10:53   ` Michal Simek
@ 2022-02-11 10:46     ` Sughosh Ganu
  0 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-11 10:46 UTC (permalink / raw)
  To: Michal Simek
  Cc: U-Boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, AKASHI Takahiro, Simon Glass,
	Bin Meng, Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Tue, 8 Feb 2022 at 16:23, Michal Simek <monstr@monstr.eu> wrote:
>
> po 7. 2. 2022 v 19:22 odesílatel Sughosh Ganu <sughosh.ganu@linaro.org> napsal:
> >
> > 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 V3:
> > * Change the TrialStateCtr efi variable attribute to remove the
> >   runtime attribute
> >
> >  common/board_r.c      |   6 ++
> >  include/fwu.h         |   3 +
> >  lib/fwu_updates/fwu.c | 178 ++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 187 insertions(+)
> >  create mode 100644 lib/fwu_updates/fwu.c
> >
> > diff --git a/common/board_r.c b/common/board_r.c
> > index 31a59c585a..81678870b9 100644
> > --- a/common/board_r.c
> > +++ b/common/board_r.c
> > @@ -78,6 +78,9 @@
> >  #ifdef CONFIG_EFI_SETUP_EARLY
> >  #include <efi_loader.h>
> >  #endif
> > +#ifdef CONFIG_FWU_MULTI_BANK_UPDATE
> > +#include <fwu.h>
> > +#endif
> >
> >  DECLARE_GLOBAL_DATA_PTR;
> >
> > @@ -805,6 +808,9 @@ static init_fnc_t init_sequence_r[] = {
> >  #endif
> >  #ifdef CONFIG_EFI_SETUP_EARLY
> >         (init_fnc_t)efi_init_obj_list,
> > +#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 90b8cd41e5..5a329d9ef7 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)
> >
> > +int fwu_boottime_checks(void);
> > +u8 fwu_update_checks_pass(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
> > new file mode 100644
> > index 0000000000..86933123e7
> > --- /dev/null
> > +++ b/lib/fwu_updates/fwu.c
> > @@ -0,0 +1,178 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2021, 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 = 0;
> > +static u8 boottime_check = 0;
>
> you don't need to initialize them to 0. They are in bss which is setup
> to 0 already.
>
> > +
> > +static int fwu_trial_state_check(void)
> > +{
> > +       int ret, i;
> > +       efi_status_t status;
> > +       efi_uintn_t var_size;
> > +       u16 trial_state_ctr;
> > +       u32 nimages, active_bank, var_attributes, active_idx;
> > +       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)
>
> Isn't it easier to have if (ret) here?
>
> > +               return ret;
> > +
> > +       ret = 0;
>
> Then you can remove this and the whole ret handling below is weird.
>
>
> > +       nimages = CONFIG_FWU_NUM_IMAGES_PER_BANK;
> > +       active_bank = mdata->active_index;
> > +       img_entry = &mdata->img_entry[0];
> > +       for (i = 0; i < nimages; i++) {
> > +               img_bank_info = &img_entry[i].img_bank_info[active_bank];
> > +               if (!img_bank_info->accepted) {
> > +                       trial_state = 1;
> > +                       break;
> > +               }
> > +       }
> > +
> > +       if (trial_state) {
> > +               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(L"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;
>
> Any reason not to use standard return macros? The same I see below too.

This is because the ret is just used to indicate whether the function
has returned successfully, or not. The value is not getting passed
anywhere from the caller function -- it is only used to either return
back or continue with further processing. And the error reason is also
being printed in all cases.

I have incorporated all your other comments. Thanks.

-sughosh

>
> > +                       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 < 0) {
>
> I would use if (ret) here.
>
> > +                               log_err("Unable to revert active_index\n");
> > +                               goto out;
> > +                       }
> > +
> > +                       trial_state_ctr = 0;
> > +                       status = efi_set_variable_int(L"TrialStateCtr",
> > +                                                     &efi_global_variable_guid,
> > +                                                     var_attributes,
> > +                                                     0,
> > +                                                     &trial_state_ctr, false);
> > +                       if (status != EFI_SUCCESS) {
> > +                               log_err("Unable to clear TrialStateCtr variable\n");
> > +                               ret = -1;
> > +                               goto out;
> > +                       }
> > +               } else {
> > +                       status = efi_set_variable_int(L"TrialStateCtr",
> > +                                                     &efi_global_variable_guid,
> > +                                                     var_attributes,
> > +                                                     var_size,
> > +                                                     &trial_state_ctr, false);
> > +                       if (status != EFI_SUCCESS) {
> > +                               log_err("Unable to increment TrialStateCtr variable\n");
> > +                               ret = -1;
> > +                               goto out;
> > +                       } else {
> > +                               ret = 0;
>
> Why do you need this? ret should be 0 when you get here.
>
> > +                       }
> > +               }
> > +       } else {
> > +               trial_state_ctr = 0;
> > +               ret = 0;
>
> the same here. You have ret=0 above that's why I think this is just an
> additional line here.
>
> > +               status = efi_set_variable_int(L"TrialStateCtr",
> > +                                             &efi_global_variable_guid,
> > +                                             0,
> > +                                             0, &trial_state_ctr,
> > +                                             NULL);
> > +       }
> > +
> > +out:
> > +       free(mdata);
> > +       return ret;
> > +}
> > +
> > +u8 fwu_update_checks_pass(void)
> > +{
> > +       return !trial_state && boottime_check;
> > +}
> > +
> > +int fwu_boottime_checks(void)
> > +{
> > +       int ret;
> > +       struct udevice *dev;
> > +       u32 boot_idx, active_idx;
> > +
> > +       if (uclass_get_device(UCLASS_FWU_MDATA, 0, &dev) || !dev) {
> > +               log_err("FWU Metadata device not found\n");
> > +               boottime_check = 0;
>
> All these boottime_check initialization to 0 seems to me useless.
>
> > +               return 0;
> > +       }
> > +
> > +       ret = fwu_mdata_check();
> > +       if (ret < 0) {
>
> up to you but I would also use if (ret) here.
>
> > +               boottime_check = 0;
>
> It is zero already when you get here that's why all these = 0 lines
> should be IMHO removed.
>
> > +               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");
> > +               boottime_check = 0;
>
> ditto.
>
> > +               return 0;
> > +       }
> > +
> > +       ret = fwu_get_active_index(&active_idx);
> > +       if (ret < 0) {
>
> ditto.
>
> > +               log_err("Unable to read active_index\n");
> > +               boottime_check = 0;
>
> ditto.
>
> > +               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 < 0)
>
> ditto.
>
> > +                       boottime_check = 0;
>
> ditto
>
> > +               else
> > +                       boottime_check = 1;
> > +
> > +               return 0;
> > +       }
> > +
> > +       ret = fwu_trial_state_check();
> > +       if (ret < 0)
>
> ditto
>
> > +               boottime_check = 0;
>
> ditto.
>
> > +       else
> > +               boottime_check = 1;
> > +
> > +       return 0;
> > +}
> > --
> > 2.17.1
> >
>
> Thanks,
> Michal
>
> --
> Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
> w: www.monstr.eu p: +42-0-721842854
> Maintainer of Linux kernel - Xilinx Microblaze
> Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
> U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs

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

* Re: [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules
  2022-02-09  3:05   ` AKASHI Takahiro
  2022-02-10  1:27     ` AKASHI Takahiro
@ 2022-02-11 13:25     ` Sughosh Ganu
  1 sibling, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-11 13:25 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Heinrich Schuchardt,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

hi Takahiro,

On Wed, 9 Feb 2022 at 08:35, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
>
> Hi Sughosh,
>
> On Mon, Feb 07, 2022 at 11:50:00PM +0530, Sughosh Ganu wrote:
> > The Dependable Boot specification describes the structure of the
>
> What is this specification? Please specify the link to the doc.
>
> > 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.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >
> > Changes since V3:
> > * Add related documentation for empty capsules in the mkeficapsule man
> >   page.
> > * Add separate usage for empty capsules, with corresponding valid
> >   options.
> > * Use ternary operators where possible.
> > * Put a exclusivity check for the empty capsule options.
> >
> >  doc/mkeficapsule.1   |  23 +++++++-
> >  tools/eficapsule.h   |   8 +++
> >  tools/mkeficapsule.c | 131 ++++++++++++++++++++++++++++++++++++-------
> >  3 files changed, 139 insertions(+), 23 deletions(-)
> >
> > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> > index 8babb27ee8..75fc15906a 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
>
> With this formatting, "capsule-file" will get italic.
>
> => .RI [ options "] [" image-blob "] " capsule-file
>
> Right?
>
> Furthermore, I think we can describe the command syntax of the two
> different cases (normal or empty capsule) more specifically.

The syntax of the two empty capsules is described in detail in the
documentation patch. Is that not sufficient. Moreover, the usage shows
the arguments for the -A and -R options separately.

>
> >
> >  .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.
> > @@ -43,7 +48,7 @@ specify a guid for the FMP driver.
> >  .SH "OPTIONS"
> >  One of
> >  .BR --fit ", " --raw " or " --guid
> > -option must be specified.
> > +option must be specified for non empty capsules.
> >
> >  .TP
> >  .BR -f ", " --fit
> > @@ -69,6 +74,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
>
> I don't still understand why we need GUID for accept empty capsule.
> We should have only one choice, whether all the new firmware be
> permanently applied or completely reverted.

The accept capsule is accepting a given firmware image in the active
bank(active_index). The specification requires that all firmware
images be accepted separately and explicitly. With firmware revert,
the idea is that if the OS reverts even one of the images, we need to
switch to booting from a different bank. Hence no GUID specified with
the revert capsule.

>
> That's A/B update, isn't it?
>
> > +.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 8c1560bb06..6001952bdc 100644
> > --- a/tools/eficapsule.h
> > +++ b/tools/eficapsule.h
> > @@ -50,6 +50,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 161affdd15..e5dbec3a92 100644
> > --- a/tools/mkeficapsule.c
> > +++ b/tools/mkeficapsule.c
> > @@ -29,6 +29,7 @@
> >  #include "eficapsule.h"
> >
> >  static const char *tool_name = "mkeficapsule";
> > +unsigned char accept_fw_capsule, revert_fw_capsule, empty_capsule;
>
> Bool? but those variables are redundant.
>
> As Ilias suggested, introducing a new enum type here can
> simplify the code in the following code.
> enum {
>         CAPSULE_NORMAL_BLOB = 0,
>         CAPSULE_ACCEPT,
>         CAPSULE_REVERT,
> } capsule_type;

Okay. Actually, I forgot about Ilias's this particular review comment.
Will incorporate.

>
>
> >
> >  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
> >  efi_guid_t efi_guid_image_type_uboot_fit =
> > @@ -38,9 +39,9 @@ efi_guid_t efi_guid_image_type_uboot_raw =
> >  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> >
> >  #ifdef CONFIG_TOOLS_LIBCRYPTO
>
> Please rebase your patch to my v10 or later.
> I have already removed the dependency on openssl library.

Yes, I will have to now rebase on your V11.

>
> > -static const char *opts_short = "frg:i:I:v:p:c:m:dh";
> > +static const char *opts_short = "frg:i:I:v:p:c:m:dhAR";
> >  #else
> > -static const char *opts_short = "frg:i:I:v:h";
> > +static const char *opts_short = "frg:i:I:v:hAR";
> >  #endif
> >
> >  static struct option options[] = {
> > @@ -55,28 +56,50 @@ static struct option options[] = {
> >       {"monotonic-count", required_argument, NULL, 'm'},
> >       {"dump-sig", no_argument, NULL, 'd'},
> >  #endif
> > +     {"fw-accept", no_argument, NULL, 'A'},
> > +     {"fw-revert", no_argument, NULL, 'R'},
> >       {"help", no_argument, NULL, 'h'},
> >       {NULL, 0, NULL, 0},
> >  };
> >
> >  static void print_usage(void)
> >  {
> > -     fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n"
> > -             "Options:\n"
> > -
> > -             "\t-f, --fit                   FIT image type\n"
> > -             "\t-r, --raw                   raw image type\n"
> > -             "\t-g, --guid <guid string>    guid for image blob type\n"
> > -             "\t-i, --index <index>         update image index\n"
> > -             "\t-I, --instance <instance>   update hardware instance\n"
> > +     if (empty_capsule) {
> > +             if (accept_fw_capsule) {
> > +                     fprintf(stderr, "Usage: %s [options] <output file>\n",
> > +                             tool_name);
> > +                     fprintf(stderr, "Options:\n"
> > +                             "\t-A, --fw-accept          firmware accept capsule\n"
> > +                             "\t-g, --guid <guid string>    guid for image blob type\n"
>
> While I doubt the necessity of "--guid,"
> why not accept "-f" or "-r" as a guid of image blob type?
> (It seems that your actual code does.)

I don't get this point. The --guid is needed for the firmware accept
capsule, since the GUID value will be that of the firmware image that
is being accepted. Like I mentioned above, firmware acceptance works
on a per image basis.

>
> > +                             "\t-h, --help                  print a help message\n"
> > +                             );
> > +             } else {
> > +                     fprintf(stderr, "Usage: %s [options] <output file>\n",
> > +                             tool_name);
> > +                     fprintf(stderr, "Options:\n"
> > +                             "\t-R, --fw-revert          firmware revert capsule\n"
> > +                             "\t-h, --help                  print a help message\n"
> > +                             );
> > +             }
> > +     } else {
> > +             fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> > +                     tool_name);
> > +             fprintf(stderr, "Options:\n"
> > +                     "\t-f, --fit                   FIT image type\n"
> > +                     "\t-r, --raw                   raw image type\n"
> > +                     "\t-g, --guid <guid string>    guid for image blob type\n"
> > +                     "\t-i, --index <index>         update image index\n"
> > +                     "\t-I, --instance <instance>   update hardware instance\n"
> >  #ifdef CONFIG_TOOLS_LIBCRYPTO
> > -             "\t-p, --private-key <privkey file>  private key file\n"
> > -             "\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-p, --private-key <privkey file>  private key file\n"
> > +                     "\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"
> >  #endif
> > -             "\t-h, --help                  print a help message\n",
> > -             tool_name);
> > +                     "\t-A, --fw-accept          firmware accept capsule\n"
> > +                     "\t-R, --fw-revert          firmware revert capsule\n"
> > +                     "\t-h, --help                  print a help message\n");
> > +     }
> >  }
> >
> >  /**
> > @@ -598,6 +621,50 @@ 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;
> > +     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 payload, 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) {
> > +             memcpy(&payload, guid, sizeof(efi_guid_t));
> > +             if (write_capsule_file(f, &payload, sizeof(payload),
> > +                                    "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
> > @@ -625,6 +692,8 @@ int main(int argc, char **argv)
> >       mcount = 0;
> >       privkey_file = NULL;
> >       cert_file = NULL;
> > +     accept_fw_capsule = 0;
> > +     revert_fw_capsule = 0;
> >       dump_sig = 0;
> >       for (;;) {
> >               c = getopt_long(argc, argv, opts_short, options, &idx);
> > @@ -691,22 +760,44 @@ int main(int argc, char **argv)
> >                       dump_sig = 1;
> >                       break;
> >  #endif /* CONFIG_TOOLS_LIBCRYPTO */
> > +             case 'A':
> > +                     accept_fw_capsule = 1;
> > +                     break;
> > +             case 'R':
> > +                     revert_fw_capsule = 1;
> > +                     break;
> >               case 'h':
> >                       print_usage();
> >                       exit(EXIT_SUCCESS);
> >               }
> >       }
> >
> > +     if (accept_fw_capsule && revert_fw_capsule) {
> > +             fprintf(stderr,
> > +                     "Select either of Accept or Revert capsule generation\n");
> > +             exit(EXIT_FAILURE);
> > +     }
> > +
> > +     empty_capsule = (accept_fw_capsule || revert_fw_capsule);
> > +
> >       /* check necessary parameters */
> > -     if ((argc != optind + 2) || !guid ||
> > -         ((privkey_file && !cert_file) ||
> > +     if ((!empty_capsule && argc != optind + 2) ||
> > +         (empty_capsule && argc != optind + 1) ||
> > +         (!revert_fw_capsule && !guid) || ((privkey_file && !cert_file) ||
> >            (!privkey_file && cert_file))) {
>
> Well, the error condition looks complicated due to mixing two cases
> and can be hard to maintain in the future. How about
>         if (!empty_capsule &&
>                 ((argc != optind + 2) || !guid ||
>                  ((privkey_file && !cert_file) ||
>                   (!privkey_file && cert_file))) ||
>             empty_capsule &&
>                 ((argc != optind + 1) ||
>                  (accept_fw_capsule && revert_fw_capsule) ||
>                  (accept_fw_capsule && !guid))  # arguable as mentioned above
>                  (revert_fw_capsule && guid))

Okay. Will change.

>         ...
>
> >               print_usage();
> >               exit(EXIT_FAILURE);
> >       }
> >
> > -     if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
> > -                      mcount, privkey_file, cert_file) < 0) {
> > +     if (empty_capsule) {
> > +             if (create_empty_capsule(argv[argc - 1], guid,
> > +                                      accept_fw_capsule ? 1 : 0) < 0) {
>
> The third argument can be simplified to "accept_fw_capsule".

Will change.

-sughosh

>
> -Takahiro Akashi
>
> > +                     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.17.1
> >

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

* Re: [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules
  2022-02-10  1:27     ` AKASHI Takahiro
@ 2022-02-11 13:27       ` Sughosh Ganu
  0 siblings, 0 replies; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-11 13:27 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Heinrich Schuchardt,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

On Thu, 10 Feb 2022 at 06:57, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> On Wed, Feb 09, 2022 at 12:05:06PM +0900, AKASHI Takahiro wrote:
> > Hi Sughosh,
> >
> > On Mon, Feb 07, 2022 at 11:50:00PM +0530, Sughosh Ganu wrote:
> > > The Dependable Boot specification describes the structure of the
> >
> > What is this specification? Please specify the link to the doc.
> >
> > > 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.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > ---
> > >
> > > Changes since V3:
> > > * Add related documentation for empty capsules in the mkeficapsule man
> > >   page.
> > > * Add separate usage for empty capsules, with corresponding valid
> > >   options.
> > > * Use ternary operators where possible.
> > > * Put a exclusivity check for the empty capsule options.
> > >
> > >  doc/mkeficapsule.1   |  23 +++++++-
> > >  tools/eficapsule.h   |   8 +++
> > >  tools/mkeficapsule.c | 131 ++++++++++++++++++++++++++++++++++++-------
> > >  3 files changed, 139 insertions(+), 23 deletions(-)
> > >
> > > diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> > > index 8babb27ee8..75fc15906a 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
> >
> > With this formatting, "capsule-file" will get italic.
>
> oops, I meant to say "roman."
>
> > => .RI [ options "] [" image-blob "] " capsule-file
> >
> > Right?
> >
> > Furthermore, I think we can describe the command syntax of the two
> > different cases (normal or empty capsule) more specifically.
> >
> > >
> > >  .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.
> > > @@ -43,7 +48,7 @@ specify a guid for the FMP driver.
> > >  .SH "OPTIONS"
> > >  One of
> > >  .BR --fit ", " --raw " or " --guid
> > > -option must be specified.
> > > +option must be specified for non empty capsules.
> > >
> > >  .TP
> > >  .BR -f ", " --fit
> > > @@ -69,6 +74,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
> >
> > I don't still understand why we need GUID for accept empty capsule.
> > We should have only one choice, whether all the new firmware be
> > permanently applied or completely reverted.
> >
> > That's A/B update, isn't it?
> >
> > > +.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 8c1560bb06..6001952bdc 100644
> > > --- a/tools/eficapsule.h
> > > +++ b/tools/eficapsule.h
> > > @@ -50,6 +50,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 161affdd15..e5dbec3a92 100644
> > > --- a/tools/mkeficapsule.c
> > > +++ b/tools/mkeficapsule.c
> > > @@ -29,6 +29,7 @@
> > >  #include "eficapsule.h"
> > >
> > >  static const char *tool_name = "mkeficapsule";
> > > +unsigned char accept_fw_capsule, revert_fw_capsule, empty_capsule;
> >
> > Bool? but those variables are redundant.
> >
> > As Ilias suggested, introducing a new enum type here can
> > simplify the code in the following code.
> > enum {
> >         CAPSULE_NORMAL_BLOB = 0,
> >         CAPSULE_ACCEPT,
> >         CAPSULE_REVERT,
> > } capsule_type;
> >
> >
> > >
> > >  efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
> > >  efi_guid_t efi_guid_image_type_uboot_fit =
> > > @@ -38,9 +39,9 @@ efi_guid_t efi_guid_image_type_uboot_raw =
> > >  efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> > >
> > >  #ifdef CONFIG_TOOLS_LIBCRYPTO
> >
> > Please rebase your patch to my v10 or later.
> > I have already removed the dependency on openssl library.
> >
> > > -static const char *opts_short = "frg:i:I:v:p:c:m:dh";
> > > +static const char *opts_short = "frg:i:I:v:p:c:m:dhAR";
> > >  #else
> > > -static const char *opts_short = "frg:i:I:v:h";
> > > +static const char *opts_short = "frg:i:I:v:hAR";
> > >  #endif
> > >
> > >  static struct option options[] = {
> > > @@ -55,28 +56,50 @@ static struct option options[] = {
> > >     {"monotonic-count", required_argument, NULL, 'm'},
> > >     {"dump-sig", no_argument, NULL, 'd'},
> > >  #endif
> > > +   {"fw-accept", no_argument, NULL, 'A'},
> > > +   {"fw-revert", no_argument, NULL, 'R'},
> > >     {"help", no_argument, NULL, 'h'},
> > >     {NULL, 0, NULL, 0},
> > >  };
> > >
> > >  static void print_usage(void)
> > >  {
> > > -   fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n"
> > > -           "Options:\n"
> > > -
> > > -           "\t-f, --fit                   FIT image type\n"
> > > -           "\t-r, --raw                   raw image type\n"
> > > -           "\t-g, --guid <guid string>    guid for image blob type\n"
> > > -           "\t-i, --index <index>         update image index\n"
> > > -           "\t-I, --instance <instance>   update hardware instance\n"
> > > +   if (empty_capsule) {
> > > +           if (accept_fw_capsule) {
> > > +                   fprintf(stderr, "Usage: %s [options] <output file>\n",
> > > +                           tool_name);
> > > +                   fprintf(stderr, "Options:\n"
> > > +                           "\t-A, --fw-accept          firmware accept capsule\n"
> > > +                           "\t-g, --guid <guid string>    guid for image blob type\n"
> >
> > While I doubt the necessity of "--guid,"
> > why not accept "-f" or "-r" as a guid of image blob type?
> > (It seems that your actual code does.)
> >
> > > +                           "\t-h, --help                  print a help message\n"
> > > +                           );
> > > +           } else {
> > > +                   fprintf(stderr, "Usage: %s [options] <output file>\n",
> > > +                           tool_name);
> > > +                   fprintf(stderr, "Options:\n"
> > > +                           "\t-R, --fw-revert          firmware revert capsule\n"
> > > +                           "\t-h, --help                  print a help message\n"
> > > +                           );
> > > +           }
> > > +   } else {
> > > +           fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> > > +                   tool_name);
> > > +           fprintf(stderr, "Options:\n"
> > > +                   "\t-f, --fit                   FIT image type\n"
> > > +                   "\t-r, --raw                   raw image type\n"
> > > +                   "\t-g, --guid <guid string>    guid for image blob type\n"
> > > +                   "\t-i, --index <index>         update image index\n"
> > > +                   "\t-I, --instance <instance>   update hardware instance\n"
> > >  #ifdef CONFIG_TOOLS_LIBCRYPTO
> > > -           "\t-p, --private-key <privkey file>  private key file\n"
> > > -           "\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-p, --private-key <privkey file>  private key file\n"
> > > +                   "\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"
> > >  #endif
> > > -           "\t-h, --help                  print a help message\n",
> > > -           tool_name);
> > > +                   "\t-A, --fw-accept          firmware accept capsule\n"
> > > +                   "\t-R, --fw-revert          firmware revert capsule\n"
> > > +                   "\t-h, --help                  print a help message\n");
> > > +   }
> > >  }
> > >
> > >  /**
> > > @@ -598,6 +621,50 @@ 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;
> > > +   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 payload, 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) {
> > > +           memcpy(&payload, guid, sizeof(efi_guid_t));
> > > +           if (write_capsule_file(f, &payload, sizeof(payload),
> > > +                                  "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
> > > @@ -625,6 +692,8 @@ int main(int argc, char **argv)
> > >     mcount = 0;
> > >     privkey_file = NULL;
> > >     cert_file = NULL;
> > > +   accept_fw_capsule = 0;
> > > +   revert_fw_capsule = 0;
> > >     dump_sig = 0;
> > >     for (;;) {
> > >             c = getopt_long(argc, argv, opts_short, options, &idx);
> > > @@ -691,22 +760,44 @@ int main(int argc, char **argv)
> > >                     dump_sig = 1;
> > >                     break;
> > >  #endif /* CONFIG_TOOLS_LIBCRYPTO */
> > > +           case 'A':
> > > +                   accept_fw_capsule = 1;
> > > +                   break;
> > > +           case 'R':
> > > +                   revert_fw_capsule = 1;
> > > +                   break;
> > >             case 'h':
> > >                     print_usage();
> > >                     exit(EXIT_SUCCESS);
> > >             }
> > >     }
> > >
> > > +   if (accept_fw_capsule && revert_fw_capsule) {
> > > +           fprintf(stderr,
> > > +                   "Select either of Accept or Revert capsule generation\n");
> > > +           exit(EXIT_FAILURE);
> > > +   }
> > > +
> > > +   empty_capsule = (accept_fw_capsule || revert_fw_capsule);
> > > +
> > >     /* check necessary parameters */
> > > -   if ((argc != optind + 2) || !guid ||
> > > -       ((privkey_file && !cert_file) ||
> > > +   if ((!empty_capsule && argc != optind + 2) ||
> > > +       (empty_capsule && argc != optind + 1) ||
> > > +       (!revert_fw_capsule && !guid) || ((privkey_file && !cert_file) ||
> > >          (!privkey_file && cert_file))) {
> >
> > Well, the error condition looks complicated due to mixing two cases
> > and can be hard to maintain in the future. How about
> >       if (!empty_capsule &&
> >                 ((argc != optind + 2) || !guid ||
> >                  ((privkey_file && !cert_file) ||
> >                   (!privkey_file && cert_file))) ||
> >             empty_capsule &&
> >                 ((argc != optind + 1) ||
> >                  (accept_fw_capsule && revert_fw_capsule) ||
> >                  (accept_fw_capsule && !guid))  # arguable as mentioned above
> >                  (revert_fw_capsule && guid))
> >         ...
>
> I've got one concern here; Can we sign an empty capsule file?
> I think we should.
> If so, the help message (by print_usage()) doesn't reflect it.

We do have plans to sign the empty capsule, although it is not being
added currently. I will keep this on my Todo list. Hope that is fine.
Thanks.

-sughosh

>
> -Takahiro Akashi
>
> >
> > >             print_usage();
> > >             exit(EXIT_FAILURE);
> > >     }
> > >
> > > -   if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
> > > -                    mcount, privkey_file, cert_file) < 0) {
> > > +   if (empty_capsule) {
> > > +           if (create_empty_capsule(argv[argc - 1], guid,
> > > +                                    accept_fw_capsule ? 1 : 0) < 0) {
> >
> > The third argument can be simplified to "accept_fw_capsule".
> >
> > -Takahiro Akashi
> >
> > > +                   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.17.1
> > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-10 10:10         ` Sughosh Ganu
@ 2022-02-14  3:24           ` AKASHI Takahiro
  2022-02-14  5:42             ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: AKASHI Takahiro @ 2022-02-14  3:24 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Sughosh,

On Thu, Feb 10, 2022 at 03:40:00PM +0530, Sughosh Ganu wrote:
> On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > > hi Takahiro,
> > >
> > > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > > <takahiro.akashi@linaro.org> wrote:
> > > >
> > > > Hi Sughosh,
> > > >
> > > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > > The FWU Multi Banks Update feature allows updating different types of
> > > > > updatable firmware images on the platform. These image types are
> > > > > identified using the ImageTypeId GUID value. Add support in the
> > > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > > the individual images and populate these in the image descriptor for
> > > > > the corresponding images.
> > > >
> > > > After re-thinking of your approach here, I would have to say NAK.
> > > >
> > > > You use ImageTypeId to identify a particular firmware object.
> > > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > > But ImageTypeId is not for that purpose, at least, as my intention
> > > > in initially implementing capsule framework and FMP drivers.
> > > >
> > > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > > >    either FIT FMP driver or Raw FMP driver.
> > >
> > > I believe the identification of an FMP protocol should be done by the
> > > FMP GUID,
> >
> > What does FMP GUID stand for?
> 
> EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
> What I mean is that even when installing the FMP protocol, the call to
> efi_install_multiple_protocol_interfaces takes the above FMP GUID as
> an argument -- nowhere is the ImageTypeId considered when installing
> the protocol.

Okay.

> >
> > > which is what is done in efi_fmp_find. The ImageTypeId is
> > > nowhere involved in this identification.
> >
> > Please take a look at efi_capsule_update_firmware() carefully.
> > efi_find_fmp() is called with the image's update_image_type_id
> > which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> > (see create_fwbin()).
> 
> I think you are thinking from the point of view of the '--guid' value
> that is being passed to the capsule generation tool. But the thing is
> that it is the current design(or limitation) of the tool that it takes
> only a single guid parameter. So the mkeficapsule tool currently can
> generate only a single payload capsule.

That is exactly what I intended to do here.
We have only one FMP driver (either FIT or RAW) which is based on
U-Boot's DFU framework and we need only one payload since, for
multiple objects of firmware, we can use FIT format as a payload.
That is what FIT is aimed for.
Or you can use multiple RAW capsule files with different indexes
("--index" exists for this purpose).

> Please check the
> GenerateCapsule script in EDK2. In case of a multi payload based
> capsule, individual parameters like the UpdateImageTypeId are passed
> through the json file, where each of the UpdateImageTypeId has a
> different value per payload.
> 
> >
> > > > 2) Each firmware object handled by a given FMP driver can further be
> > > >    identified by ImageIndex.
> > > >
> > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > a parameter.
> > > >
> > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > doesn't meet the UEFI specification.
> > >
> > > So, as per what you are stating, all payloads under a given
> > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > with the ImageTypeId retrieved from the image descriptor would simply
> > > fail.
> >
> > I don't follow your point.
> > Please elaborate a bit more.
> 
> The current implementation of GetImageInfo, passes either of
> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> descriptor array. So, in case the capsule is generated with a '--guid'
> value which is different from these two values, the check in
> efi_fmp_find on line 204 will fail.

That is an expected behavior, isn't it?
If you want to use a different FMP driver (with another GUID),
you naturally need to add your own FMP driver.


> This means that unless the --guid
> value passed to the capsule generation is either of u-boot FIT or
> u-boot raw, the current FMP protocol for raw devices cannot be used.
> Why do we need that restriction. It should be possible to use the raw
> FMP protocol for any other type of image types as well.
> 
> 
> >
> > > I think this interpretation of the UEFI spec is incorrect, since the
> > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > used to identify the firmware component targeted for the update. If
> > > all values in the image descriptor array and the UpdateImageTypeId are
> > > the same, why have this field in the first place for individual
> > > images.
> >
> > As I said, ImageIndex is for that purpose.
> 
> Yes, that is one possible way in the scenario where the ImageIndex is
> determined at the capsule generation time. But, for the A/B update
> scenario, we do not know the ImageIndex at build time

"Build time" of what?
I think that users should know how "dfu_alt_info" is defined
(in other words, where the firmware be located on the target system)
when capsule files are created.

-Takahiro Akashi


> -- this is
> determined only at runtime, and is based on the bank to which the
> image is to be updated. Which is why I am finding out the alt_num at
> runtime in case the FWU Multi Bank feature is enabled. Like I said
> above, I do not see a reason why the current FMP protocols should be
> restricted to only the u-boot FIT and u-boot raw image types. It is
> being extended, without affecting the default non FWU behaviour.
> 
> -sughosh
> 
> >
> > -Takahiro Akashi
> >
> > >
> > > -sughosh
> > >
> > > >
> > > > -Takahiro Akashi
> > > >
> > > >
> > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > ---
> > > > >
> > > > > Changes since V3:
> > > > > * Define a weak function fill_image_type_guid_array for populating the
> > > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > > >
> > > > >  include/efi_loader.h          |  2 +
> > > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > > >
> > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > index f4860e87fc..ae60de0be5 100644
> > > > > --- a/include/efi_loader.h
> > > > > +++ b/include/efi_loader.h
> > > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > > >  efi_status_t efi_load_capsule_drivers(void);
> > > > >
> > > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > > +                                     efi_guid_t **part_guid_arr);
> > > > >  #endif /* _EFI_LOADER_H */
> > > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > > index a1b88dbfc2..5642be9f9a 100644
> > > > > --- a/lib/efi_loader/efi_firmware.c
> > > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > > >  }
> > > > >
> > > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > > +                                            efi_guid_t **part_guid_arr)
> > > > > +{
> > > > > +     int i;
> > > > > +     int dfu_num = 0;
> > > > > +     efi_guid_t *guid_arr;
> > > > > +     struct dfu_entity *dfu;
> > > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > > +
> > > > > +     dfu_init_env_entities(NULL, NULL);
> > > > > +
> > > > > +     dfu_num = 0;
> > > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > > +             dfu_num++;
> > > > > +     }
> > > > > +
> > > > > +     if (!dfu_num) {
> > > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > > +             ret = EFI_NOT_READY;
> > > > > +             goto out;
> > > > > +     }
> > > > > +
> > > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > > +     if (!*part_guid_arr) {
> > > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > > +             goto out;
> > > > > +     }
> > > > > +
> > > > > +     guid_arr = *part_guid_arr;
> > > > > +     for (i = 0; i < dfu_num; i++) {
> > > > > +             guidcpy(guid_arr, guid);
> > > > > +             ++guid_arr;
> > > > > +     }
> > > > > +
> > > > > +out:
> > > > > +     dfu_free_entities();
> > > > > +
> > > > > +     return ret;
> > > > > +}
> > > > > +
> > > > >  /**
> > > > >   * efi_get_dfu_info - return information about the current firmware image
> > > > >   * @this:                    Protocol instance
> > > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > >   * @descriptor_version:              Pointer to version number
> > > > >   * @descriptor_count:                Pointer to number of descriptors
> > > > >   * @descriptor_size:         Pointer to descriptor size
> > > > > - * package_version:          Package version
> > > > > - * package_version_name:     Package version's name
> > > > > - * image_type:                       Image type GUID
> > > > > + * @package_version:         Package version
> > > > > + * @package_version_name:    Package version's name
> > > > > + * @guid_array:                      Image type GUID array
> > > > >   *
> > > > >   * Return information bout the current firmware image in @image_info.
> > > > >   * @image_info will consist of a number of descriptors.
> > > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > > >       efi_uintn_t *descriptor_size,
> > > > >       u32 *package_version,
> > > > >       u16 **package_version_name,
> > > > > -     const efi_guid_t *image_type)
> > > > > +     const efi_guid_t *guid_array)
> > > > >  {
> > > > >       struct dfu_entity *dfu;
> > > > >       size_t names_len, total_size;
> > > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > > >       next = name;
> > > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > > >               image_info[i].image_index = dfu->alt + 1;
> > > > > -             image_info[i].image_type_id = *image_type;
> > > > > +             image_info[i].image_type_id = guid_array[i];
> > > > >               image_info[i].image_id = dfu->alt;
> > > > >
> > > > >               /* copy the DFU entity name */
> > > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > >       u16 **package_version_name)
> > > > >  {
> > > > >       efi_status_t ret;
> > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > >
> > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > >                 image_info_size, image_info,
> > > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > >
> > > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > > +                                      &part_guid_arr);
> > > > > +     if (ret != EFI_SUCCESS)
> > > > > +             goto out;
> > > > > +
> > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > >                              descriptor_version, descriptor_count,
> > > > >                              descriptor_size,
> > > > >                              package_version, package_version_name,
> > > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > > +                            part_guid_arr);
> > > > >
> > > > > +out:
> > > > > +     free(part_guid_arr);
> > > > >       return EFI_EXIT(ret);
> > > > >  }
> > > > >
> > > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > >       u16 **package_version_name)
> > > > >  {
> > > > >       efi_status_t ret = EFI_SUCCESS;
> > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > >
> > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > >                 image_info_size, image_info,
> > > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > >
> > > > > +     ret = fill_image_type_guid_array(
> > > > > +             &efi_firmware_image_type_uboot_raw,
> > > > > +             &part_guid_arr);
> > > > > +     if (ret != EFI_SUCCESS)
> > > > > +             goto out;
> > > > > +
> > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > >                              descriptor_version, descriptor_count,
> > > > >                              descriptor_size,
> > > > >                              package_version, package_version_name,
> > > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > > +                            part_guid_arr);
> > > > >
> > > > > +out:
> > > > > +     free(part_guid_arr);
> > > > >       return EFI_EXIT(ret);
> > > > >  }
> > > > >
> > > > > --
> > > > > 2.17.1
> > > > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-14  3:24           ` AKASHI Takahiro
@ 2022-02-14  5:42             ` Sughosh Ganu
  2022-02-15  1:51               ` AKASHI Takahiro
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-14  5:42 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Heinrich Schuchardt,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

hi Takahiro,

On Mon, 14 Feb 2022 at 08:54, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Sughosh,
>
> On Thu, Feb 10, 2022 at 03:40:00PM +0530, Sughosh Ganu wrote:
> > On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > > > hi Takahiro,
> > > >
> > > > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > > > <takahiro.akashi@linaro.org> wrote:
> > > > >
> > > > > Hi Sughosh,
> > > > >
> > > > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > > > The FWU Multi Banks Update feature allows updating different types of
> > > > > > updatable firmware images on the platform. These image types are
> > > > > > identified using the ImageTypeId GUID value. Add support in the
> > > > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > > > the individual images and populate these in the image descriptor for
> > > > > > the corresponding images.
> > > > >
> > > > > After re-thinking of your approach here, I would have to say NAK.
> > > > >
> > > > > You use ImageTypeId to identify a particular firmware object.
> > > > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > > > But ImageTypeId is not for that purpose, at least, as my intention
> > > > > in initially implementing capsule framework and FMP drivers.
> > > > >
> > > > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > > > >    either FIT FMP driver or Raw FMP driver.
> > > >
> > > > I believe the identification of an FMP protocol should be done by the
> > > > FMP GUID,
> > >
> > > What does FMP GUID stand for?
> >
> > EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
> > What I mean is that even when installing the FMP protocol, the call to
> > efi_install_multiple_protocol_interfaces takes the above FMP GUID as
> > an argument -- nowhere is the ImageTypeId considered when installing
> > the protocol.
>
> Okay.
>
> > >
> > > > which is what is done in efi_fmp_find. The ImageTypeId is
> > > > nowhere involved in this identification.
> > >
> > > Please take a look at efi_capsule_update_firmware() carefully.
> > > efi_find_fmp() is called with the image's update_image_type_id
> > > which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> > > (see create_fwbin()).
> >
> > I think you are thinking from the point of view of the '--guid' value
> > that is being passed to the capsule generation tool. But the thing is
> > that it is the current design(or limitation) of the tool that it takes
> > only a single guid parameter. So the mkeficapsule tool currently can
> > generate only a single payload capsule.
>
> That is exactly what I intended to do here.
> We have only one FMP driver (either FIT or RAW) which is based on
> U-Boot's DFU framework and we need only one payload since, for
> multiple objects of firmware, we can use FIT format as a payload.
> That is what FIT is aimed for.
> Or you can use multiple RAW capsule files with different indexes
> ("--index" exists for this purpose).

Yes, we can use --index when we know the index value corresponding to
the firmware image that we need to update. But like I mentioned in my
earlier reply, for A/B updates, we do not know what the index value is
going to be. That is going to be determined at runtime.

Also, the point I was making is that we can have a capsule which is
consumed by an FMP protocol which has more than one image, and those
images have different ImageTypeId/UpdateImageTypeId.

>
> > Please check the
> > GenerateCapsule script in EDK2. In case of a multi payload based
> > capsule, individual parameters like the UpdateImageTypeId are passed
> > through the json file, where each of the UpdateImageTypeId has a
> > different value per payload.
> >
> > >
> > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > >    identified by ImageIndex.
> > > > >
> > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > a parameter.
> > > > >
> > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > doesn't meet the UEFI specification.
> > > >
> > > > So, as per what you are stating, all payloads under a given
> > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > fail.
> > >
> > > I don't follow your point.
> > > Please elaborate a bit more.
> >
> > The current implementation of GetImageInfo, passes either of
> > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > descriptor array. So, in case the capsule is generated with a '--guid'
> > value which is different from these two values, the check in
> > efi_fmp_find on line 204 will fail.
>
> That is an expected behavior, isn't it?

Yes it is. Do not contest that.

> If you want to use a different FMP driver (with another GUID),
> you naturally need to add your own FMP driver.

This is where I differ. We can use the same FMP protocol instance for
any type of ImageTypeId. I do not see why we need to define a
different FMP protocol instance for a GUID value other than what has
been defined for u-boot raw and u-boot FIT GUIDs.

The platform can give us the image descriptor array, and with that,
the same FMP instance can be used for any type of image(ImageTypeId).

>
>
> > This means that unless the --guid
> > value passed to the capsule generation is either of u-boot FIT or
> > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > Why do we need that restriction. It should be possible to use the raw
> > FMP protocol for any other type of image types as well.
> >
> >
> > >
> > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > used to identify the firmware component targeted for the update. If
> > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > the same, why have this field in the first place for individual
> > > > images.
> > >
> > > As I said, ImageIndex is for that purpose.
> >
> > Yes, that is one possible way in the scenario where the ImageIndex is
> > determined at the capsule generation time. But, for the A/B update
> > scenario, we do not know the ImageIndex at build time
>
> "Build time" of what?

Of the capsule.

> I think that users should know how "dfu_alt_info" is defined
> (in other words, where the firmware be located on the target system)
> when capsule files are created.

That is true for a non A/B scenario. And that is how it works in the
non A/B updates case. But for A/B updates, since the determination of
the "location" where the firmware image has to be written will be done
only at runtime, we cannot use the --index to differentiate.

Like I mentioned earlier, this is not breaking the existing behaviour
-- for the non A/B updates, the update procedure remains exactly the
same, of using the index value to determine the location of the
update. I have only extended the behaviour to use the same FMP
instance for the A/B update(FWU) feature using ImageTypeId's.

-sughosh

>
> -Takahiro Akashi
>
>
> > -- this is
> > determined only at runtime, and is based on the bank to which the
> > image is to be updated. Which is why I am finding out the alt_num at
> > runtime in case the FWU Multi Bank feature is enabled. Like I said
> > above, I do not see a reason why the current FMP protocols should be
> > restricted to only the u-boot FIT and u-boot raw image types. It is
> > being extended, without affecting the default non FWU behaviour.
> >
> > -sughosh
> >
> > >
> > > -Takahiro Akashi
> > >
> > > >
> > > > -sughosh
> > > >
> > > > >
> > > > > -Takahiro Akashi
> > > > >
> > > > >
> > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > ---
> > > > > >
> > > > > > Changes since V3:
> > > > > > * Define a weak function fill_image_type_guid_array for populating the
> > > > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > > > >
> > > > > >  include/efi_loader.h          |  2 +
> > > > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > > > >
> > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > > index f4860e87fc..ae60de0be5 100644
> > > > > > --- a/include/efi_loader.h
> > > > > > +++ b/include/efi_loader.h
> > > > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > > > >  efi_status_t efi_load_capsule_drivers(void);
> > > > > >
> > > > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > > > +                                     efi_guid_t **part_guid_arr);
> > > > > >  #endif /* _EFI_LOADER_H */
> > > > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > > > index a1b88dbfc2..5642be9f9a 100644
> > > > > > --- a/lib/efi_loader/efi_firmware.c
> > > > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > > > >  }
> > > > > >
> > > > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > > > +                                            efi_guid_t **part_guid_arr)
> > > > > > +{
> > > > > > +     int i;
> > > > > > +     int dfu_num = 0;
> > > > > > +     efi_guid_t *guid_arr;
> > > > > > +     struct dfu_entity *dfu;
> > > > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > > > +
> > > > > > +     dfu_init_env_entities(NULL, NULL);
> > > > > > +
> > > > > > +     dfu_num = 0;
> > > > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > +             dfu_num++;
> > > > > > +     }
> > > > > > +
> > > > > > +     if (!dfu_num) {
> > > > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > > > +             ret = EFI_NOT_READY;
> > > > > > +             goto out;
> > > > > > +     }
> > > > > > +
> > > > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > > > +     if (!*part_guid_arr) {
> > > > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > > > +             goto out;
> > > > > > +     }
> > > > > > +
> > > > > > +     guid_arr = *part_guid_arr;
> > > > > > +     for (i = 0; i < dfu_num; i++) {
> > > > > > +             guidcpy(guid_arr, guid);
> > > > > > +             ++guid_arr;
> > > > > > +     }
> > > > > > +
> > > > > > +out:
> > > > > > +     dfu_free_entities();
> > > > > > +
> > > > > > +     return ret;
> > > > > > +}
> > > > > > +
> > > > > >  /**
> > > > > >   * efi_get_dfu_info - return information about the current firmware image
> > > > > >   * @this:                    Protocol instance
> > > > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > >   * @descriptor_version:              Pointer to version number
> > > > > >   * @descriptor_count:                Pointer to number of descriptors
> > > > > >   * @descriptor_size:         Pointer to descriptor size
> > > > > > - * package_version:          Package version
> > > > > > - * package_version_name:     Package version's name
> > > > > > - * image_type:                       Image type GUID
> > > > > > + * @package_version:         Package version
> > > > > > + * @package_version_name:    Package version's name
> > > > > > + * @guid_array:                      Image type GUID array
> > > > > >   *
> > > > > >   * Return information bout the current firmware image in @image_info.
> > > > > >   * @image_info will consist of a number of descriptors.
> > > > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > >       efi_uintn_t *descriptor_size,
> > > > > >       u32 *package_version,
> > > > > >       u16 **package_version_name,
> > > > > > -     const efi_guid_t *image_type)
> > > > > > +     const efi_guid_t *guid_array)
> > > > > >  {
> > > > > >       struct dfu_entity *dfu;
> > > > > >       size_t names_len, total_size;
> > > > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > >       next = name;
> > > > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > > > >               image_info[i].image_index = dfu->alt + 1;
> > > > > > -             image_info[i].image_type_id = *image_type;
> > > > > > +             image_info[i].image_type_id = guid_array[i];
> > > > > >               image_info[i].image_id = dfu->alt;
> > > > > >
> > > > > >               /* copy the DFU entity name */
> > > > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > >       u16 **package_version_name)
> > > > > >  {
> > > > > >       efi_status_t ret;
> > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > >
> > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > >                 image_info_size, image_info,
> > > > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > >
> > > > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > > > +                                      &part_guid_arr);
> > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > +             goto out;
> > > > > > +
> > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > >                              descriptor_version, descriptor_count,
> > > > > >                              descriptor_size,
> > > > > >                              package_version, package_version_name,
> > > > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > > > +                            part_guid_arr);
> > > > > >
> > > > > > +out:
> > > > > > +     free(part_guid_arr);
> > > > > >       return EFI_EXIT(ret);
> > > > > >  }
> > > > > >
> > > > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > >       u16 **package_version_name)
> > > > > >  {
> > > > > >       efi_status_t ret = EFI_SUCCESS;
> > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > >
> > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > >                 image_info_size, image_info,
> > > > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > >
> > > > > > +     ret = fill_image_type_guid_array(
> > > > > > +             &efi_firmware_image_type_uboot_raw,
> > > > > > +             &part_guid_arr);
> > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > +             goto out;
> > > > > > +
> > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > >                              descriptor_version, descriptor_count,
> > > > > >                              descriptor_size,
> > > > > >                              package_version, package_version_name,
> > > > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > > > +                            part_guid_arr);
> > > > > >
> > > > > > +out:
> > > > > > +     free(part_guid_arr);
> > > > > >       return EFI_EXIT(ret);
> > > > > >  }
> > > > > >
> > > > > > --
> > > > > > 2.17.1
> > > > > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-14  5:42             ` Sughosh Ganu
@ 2022-02-15  1:51               ` AKASHI Takahiro
  2022-02-15  6:38                 ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: AKASHI Takahiro @ 2022-02-15  1:51 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Heinrich Schuchardt, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Sughosh,

On Mon, Feb 14, 2022 at 11:12:22AM +0530, Sughosh Ganu wrote:
> hi Takahiro,
> 
> On Mon, 14 Feb 2022 at 08:54, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > Sughosh,
> >
> > On Thu, Feb 10, 2022 at 03:40:00PM +0530, Sughosh Ganu wrote:
> > > On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
> > > <takahiro.akashi@linaro.org> wrote:
> > > >
> > > > On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > > > > hi Takahiro,
> > > > >
> > > > > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > > > > <takahiro.akashi@linaro.org> wrote:
> > > > > >
> > > > > > Hi Sughosh,
> > > > > >
> > > > > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > > > > The FWU Multi Banks Update feature allows updating different types of
> > > > > > > updatable firmware images on the platform. These image types are
> > > > > > > identified using the ImageTypeId GUID value. Add support in the
> > > > > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > > > > the individual images and populate these in the image descriptor for
> > > > > > > the corresponding images.
> > > > > >
> > > > > > After re-thinking of your approach here, I would have to say NAK.
> > > > > >
> > > > > > You use ImageTypeId to identify a particular firmware object.
> > > > > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > > > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > > > > But ImageTypeId is not for that purpose, at least, as my intention
> > > > > > in initially implementing capsule framework and FMP drivers.
> > > > > >
> > > > > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > > > > >    either FIT FMP driver or Raw FMP driver.
> > > > >
> > > > > I believe the identification of an FMP protocol should be done by the
> > > > > FMP GUID,
> > > >
> > > > What does FMP GUID stand for?
> > >
> > > EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
> > > What I mean is that even when installing the FMP protocol, the call to
> > > efi_install_multiple_protocol_interfaces takes the above FMP GUID as
> > > an argument -- nowhere is the ImageTypeId considered when installing
> > > the protocol.
> >
> > Okay.
> >
> > > >
> > > > > which is what is done in efi_fmp_find. The ImageTypeId is
> > > > > nowhere involved in this identification.
> > > >
> > > > Please take a look at efi_capsule_update_firmware() carefully.
> > > > efi_find_fmp() is called with the image's update_image_type_id
> > > > which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> > > > (see create_fwbin()).
> > >
> > > I think you are thinking from the point of view of the '--guid' value
> > > that is being passed to the capsule generation tool. But the thing is
> > > that it is the current design(or limitation) of the tool that it takes
> > > only a single guid parameter. So the mkeficapsule tool currently can
> > > generate only a single payload capsule.
> >
> > That is exactly what I intended to do here.
> > We have only one FMP driver (either FIT or RAW) which is based on
> > U-Boot's DFU framework and we need only one payload since, for
> > multiple objects of firmware, we can use FIT format as a payload.
> > That is what FIT is aimed for.
> > Or you can use multiple RAW capsule files with different indexes
> > ("--index" exists for this purpose).
> 
> Yes, we can use --index when we know the index value corresponding to
> the firmware image that we need to update. But like I mentioned in my
> earlier reply, for A/B updates, we do not know what the index value is
> going to be. That is going to be determined at runtime.

I don't think so. See below for alternative approach.

> Also, the point I was making is that we can have a capsule which is
> consumed by an FMP protocol which has more than one image, and those
> images have different ImageTypeId/UpdateImageTypeId.

Yes, but it is a design choice in my first implementation.
I didn't think that we need to "have a capsule which is consumed
by an FMP protocol which has more than one image" as long as we
use DFU framework (and FIT as standard format of aggregation on U-Boot).

> >
> > > Please check the
> > > GenerateCapsule script in EDK2. In case of a multi payload based
> > > capsule, individual parameters like the UpdateImageTypeId are passed
> > > through the json file, where each of the UpdateImageTypeId has a
> > > different value per payload.
> > >
> > > >
> > > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > > >    identified by ImageIndex.
> > > > > >
> > > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > > a parameter.
> > > > > >
> > > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > > doesn't meet the UEFI specification.
> > > > >
> > > > > So, as per what you are stating, all payloads under a given
> > > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > > fail.
> > > >
> > > > I don't follow your point.
> > > > Please elaborate a bit more.
> > >
> > > The current implementation of GetImageInfo, passes either of
> > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > > descriptor array. So, in case the capsule is generated with a '--guid'
> > > value which is different from these two values, the check in
> > > efi_fmp_find on line 204 will fail.
> >
> > That is an expected behavior, isn't it?
> 
> Yes it is. Do not contest that.
> 
> > If you want to use a different FMP driver (with another GUID),
> > you naturally need to add your own FMP driver.
> 
> This is where I differ. We can use the same FMP protocol instance for
> any type of ImageTypeId. I do not see why we need to define a
> different FMP protocol instance for a GUID value other than what has
> been defined for u-boot raw and u-boot FIT GUIDs.

I do understand part of your concern a bit.
I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
but we needed different GUIDs here simply because we need to determine
the format of payload, FIT format or raw binary.

> The platform can give us the image descriptor array, and with that,
> the same FMP instance can be used for any type of image(ImageTypeId).

"any type of image"? Really?
> 
> >
> >
> > > This means that unless the --guid
> > > value passed to the capsule generation is either of u-boot FIT or
> > > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > > Why do we need that restriction. It should be possible to use the raw
> > > FMP protocol for any other type of image types as well.
> > >
> > >
> > > >
> > > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > > used to identify the firmware component targeted for the update. If
> > > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > > the same, why have this field in the first place for individual
> > > > > images.
> > > >
> > > > As I said, ImageIndex is for that purpose.
> > >
> > > Yes, that is one possible way in the scenario where the ImageIndex is
> > > determined at the capsule generation time. But, for the A/B update
> > > scenario, we do not know the ImageIndex at build time
> >
> > "Build time" of what?
> 
> Of the capsule.
> 
> > I think that users should know how "dfu_alt_info" is defined
> > (in other words, where the firmware be located on the target system)
> > when capsule files are created.
> 
> That is true for a non A/B scenario. And that is how it works in the
> non A/B updates case. But for A/B updates, since the determination of
> the "location" where the firmware image has to be written will be done
> only at runtime, we cannot use the --index to differentiate.

Yes, we can :)

First of all, my essential assumption in either FIT or RAW FMP driver
is that U-Boot has (somehow conceptually) single firmware blob represented
by DFU or dfu_alt_info. As I said, each object or location in
dfu_alt_info can be further identified by index or "UpdateImageIndex".

Let's assume that we have two locations of firmware, fw1 and fw2, and
that we have two bank A and B.
Then we will define dfu_alt_info as follows:
  <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
  |<---      1st set               --->|<---       2nd set               --->|

When you want to update bank A, we can use the first set of dfu_alt_info,
and use the second set of dfu_alt_info for bank B.
At runtime, you should know which bank you're working on, and therefore
you should know the exact physical location from dfu_alt_info.

Please note that you don't have to change the syntax of dfu_alt_info
at all. Simply offset the location with 0 for bank A and with 2 for bank B.

I don't think we need to introduce extra GUIDs.

-Takahiro Akashi

> Like I mentioned earlier, this is not breaking the existing behaviour
> -- for the non A/B updates, the update procedure remains exactly the
> same, of using the index value to determine the location of the
> update. I have only extended the behaviour to use the same FMP
> instance for the A/B update(FWU) feature using ImageTypeId's.
> 
> -sughosh
> 
> >
> > -Takahiro Akashi
> >
> >
> > > -- this is
> > > determined only at runtime, and is based on the bank to which the
> > > image is to be updated. Which is why I am finding out the alt_num at
> > > runtime in case the FWU Multi Bank feature is enabled. Like I said
> > > above, I do not see a reason why the current FMP protocols should be
> > > restricted to only the u-boot FIT and u-boot raw image types. It is
> > > being extended, without affecting the default non FWU behaviour.
> > >
> > > -sughosh
> > >
> > > >
> > > > -Takahiro Akashi
> > > >
> > > > >
> > > > > -sughosh
> > > > >
> > > > > >
> > > > > > -Takahiro Akashi
> > > > > >
> > > > > >
> > > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > > ---
> > > > > > >
> > > > > > > Changes since V3:
> > > > > > > * Define a weak function fill_image_type_guid_array for populating the
> > > > > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > > > > >
> > > > > > >  include/efi_loader.h          |  2 +
> > > > > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > > > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > > > > >
> > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > > > index f4860e87fc..ae60de0be5 100644
> > > > > > > --- a/include/efi_loader.h
> > > > > > > +++ b/include/efi_loader.h
> > > > > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > > > > >  efi_status_t efi_load_capsule_drivers(void);
> > > > > > >
> > > > > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > > > > +                                     efi_guid_t **part_guid_arr);
> > > > > > >  #endif /* _EFI_LOADER_H */
> > > > > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > > > > index a1b88dbfc2..5642be9f9a 100644
> > > > > > > --- a/lib/efi_loader/efi_firmware.c
> > > > > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > > > > >  }
> > > > > > >
> > > > > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > > > > +                                            efi_guid_t **part_guid_arr)
> > > > > > > +{
> > > > > > > +     int i;
> > > > > > > +     int dfu_num = 0;
> > > > > > > +     efi_guid_t *guid_arr;
> > > > > > > +     struct dfu_entity *dfu;
> > > > > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > > > > +
> > > > > > > +     dfu_init_env_entities(NULL, NULL);
> > > > > > > +
> > > > > > > +     dfu_num = 0;
> > > > > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > +             dfu_num++;
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     if (!dfu_num) {
> > > > > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > > > > +             ret = EFI_NOT_READY;
> > > > > > > +             goto out;
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > > > > +     if (!*part_guid_arr) {
> > > > > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > > > > +             goto out;
> > > > > > > +     }
> > > > > > > +
> > > > > > > +     guid_arr = *part_guid_arr;
> > > > > > > +     for (i = 0; i < dfu_num; i++) {
> > > > > > > +             guidcpy(guid_arr, guid);
> > > > > > > +             ++guid_arr;
> > > > > > > +     }
> > > > > > > +
> > > > > > > +out:
> > > > > > > +     dfu_free_entities();
> > > > > > > +
> > > > > > > +     return ret;
> > > > > > > +}
> > > > > > > +
> > > > > > >  /**
> > > > > > >   * efi_get_dfu_info - return information about the current firmware image
> > > > > > >   * @this:                    Protocol instance
> > > > > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > >   * @descriptor_version:              Pointer to version number
> > > > > > >   * @descriptor_count:                Pointer to number of descriptors
> > > > > > >   * @descriptor_size:         Pointer to descriptor size
> > > > > > > - * package_version:          Package version
> > > > > > > - * package_version_name:     Package version's name
> > > > > > > - * image_type:                       Image type GUID
> > > > > > > + * @package_version:         Package version
> > > > > > > + * @package_version_name:    Package version's name
> > > > > > > + * @guid_array:                      Image type GUID array
> > > > > > >   *
> > > > > > >   * Return information bout the current firmware image in @image_info.
> > > > > > >   * @image_info will consist of a number of descriptors.
> > > > > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > >       efi_uintn_t *descriptor_size,
> > > > > > >       u32 *package_version,
> > > > > > >       u16 **package_version_name,
> > > > > > > -     const efi_guid_t *image_type)
> > > > > > > +     const efi_guid_t *guid_array)
> > > > > > >  {
> > > > > > >       struct dfu_entity *dfu;
> > > > > > >       size_t names_len, total_size;
> > > > > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > >       next = name;
> > > > > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > >               image_info[i].image_index = dfu->alt + 1;
> > > > > > > -             image_info[i].image_type_id = *image_type;
> > > > > > > +             image_info[i].image_type_id = guid_array[i];
> > > > > > >               image_info[i].image_id = dfu->alt;
> > > > > > >
> > > > > > >               /* copy the DFU entity name */
> > > > > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > >       u16 **package_version_name)
> > > > > > >  {
> > > > > > >       efi_status_t ret;
> > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > >
> > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > >                 image_info_size, image_info,
> > > > > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > >
> > > > > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > > > > +                                      &part_guid_arr);
> > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > +             goto out;
> > > > > > > +
> > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > >                              descriptor_version, descriptor_count,
> > > > > > >                              descriptor_size,
> > > > > > >                              package_version, package_version_name,
> > > > > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > > > > +                            part_guid_arr);
> > > > > > >
> > > > > > > +out:
> > > > > > > +     free(part_guid_arr);
> > > > > > >       return EFI_EXIT(ret);
> > > > > > >  }
> > > > > > >
> > > > > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > >       u16 **package_version_name)
> > > > > > >  {
> > > > > > >       efi_status_t ret = EFI_SUCCESS;
> > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > >
> > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > >                 image_info_size, image_info,
> > > > > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > >
> > > > > > > +     ret = fill_image_type_guid_array(
> > > > > > > +             &efi_firmware_image_type_uboot_raw,
> > > > > > > +             &part_guid_arr);
> > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > +             goto out;
> > > > > > > +
> > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > >                              descriptor_version, descriptor_count,
> > > > > > >                              descriptor_size,
> > > > > > >                              package_version, package_version_name,
> > > > > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > > > > +                            part_guid_arr);
> > > > > > >
> > > > > > > +out:
> > > > > > > +     free(part_guid_arr);
> > > > > > >       return EFI_EXIT(ret);
> > > > > > >  }
> > > > > > >
> > > > > > > --
> > > > > > > 2.17.1
> > > > > > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-15  1:51               ` AKASHI Takahiro
@ 2022-02-15  6:38                 ` Sughosh Ganu
  2022-02-15 14:40                   ` Ilias Apalodimas
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-15  6:38 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Heinrich Schuchardt,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

On Tue, 15 Feb 2022 at 07:21, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Sughosh,
>
> On Mon, Feb 14, 2022 at 11:12:22AM +0530, Sughosh Ganu wrote:
> > hi Takahiro,
> >
> > On Mon, 14 Feb 2022 at 08:54, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > Sughosh,
> > >
> > > On Thu, Feb 10, 2022 at 03:40:00PM +0530, Sughosh Ganu wrote:
> > > > On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
> > > > <takahiro.akashi@linaro.org> wrote:
> > > > >
> > > > > On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > > > > > hi Takahiro,
> > > > > >
> > > > > > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > > > > > <takahiro.akashi@linaro.org> wrote:
> > > > > > >
> > > > > > > Hi Sughosh,
> > > > > > >
> > > > > > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > > > > > The FWU Multi Banks Update feature allows updating different types of
> > > > > > > > updatable firmware images on the platform. These image types are
> > > > > > > > identified using the ImageTypeId GUID value. Add support in the
> > > > > > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > > > > > the individual images and populate these in the image descriptor for
> > > > > > > > the corresponding images.
> > > > > > >
> > > > > > > After re-thinking of your approach here, I would have to say NAK.
> > > > > > >
> > > > > > > You use ImageTypeId to identify a particular firmware object.
> > > > > > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > > > > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > > > > > But ImageTypeId is not for that purpose, at least, as my intention
> > > > > > > in initially implementing capsule framework and FMP drivers.
> > > > > > >
> > > > > > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > > > > > >    either FIT FMP driver or Raw FMP driver.
> > > > > >
> > > > > > I believe the identification of an FMP protocol should be done by the
> > > > > > FMP GUID,
> > > > >
> > > > > What does FMP GUID stand for?
> > > >
> > > > EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
> > > > What I mean is that even when installing the FMP protocol, the call to
> > > > efi_install_multiple_protocol_interfaces takes the above FMP GUID as
> > > > an argument -- nowhere is the ImageTypeId considered when installing
> > > > the protocol.
> > >
> > > Okay.
> > >
> > > > >
> > > > > > which is what is done in efi_fmp_find. The ImageTypeId is
> > > > > > nowhere involved in this identification.
> > > > >
> > > > > Please take a look at efi_capsule_update_firmware() carefully.
> > > > > efi_find_fmp() is called with the image's update_image_type_id
> > > > > which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> > > > > (see create_fwbin()).
> > > >
> > > > I think you are thinking from the point of view of the '--guid' value
> > > > that is being passed to the capsule generation tool. But the thing is
> > > > that it is the current design(or limitation) of the tool that it takes
> > > > only a single guid parameter. So the mkeficapsule tool currently can
> > > > generate only a single payload capsule.
> > >
> > > That is exactly what I intended to do here.
> > > We have only one FMP driver (either FIT or RAW) which is based on
> > > U-Boot's DFU framework and we need only one payload since, for
> > > multiple objects of firmware, we can use FIT format as a payload.
> > > That is what FIT is aimed for.
> > > Or you can use multiple RAW capsule files with different indexes
> > > ("--index" exists for this purpose).
> >
> > Yes, we can use --index when we know the index value corresponding to
> > the firmware image that we need to update. But like I mentioned in my
> > earlier reply, for A/B updates, we do not know what the index value is
> > going to be. That is going to be determined at runtime.
>
> I don't think so. See below for alternative approach.
>
> > Also, the point I was making is that we can have a capsule which is
> > consumed by an FMP protocol which has more than one image, and those
> > images have different ImageTypeId/UpdateImageTypeId.
>
> Yes, but it is a design choice in my first implementation.
> I didn't think that we need to "have a capsule which is consumed
> by an FMP protocol which has more than one image" as long as we
> use DFU framework (and FIT as standard format of aggregation on U-Boot).

But this design can be extended without any hassle, and more
importantly without any regression, no? What kind of a problem does it
create if the FMP can handle more than one image type.

Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
header for all images to be managed by the FMP protocol which has
multiple images with different UpdateImageTypeId.

>
> > >
> > > > Please check the
> > > > GenerateCapsule script in EDK2. In case of a multi payload based
> > > > capsule, individual parameters like the UpdateImageTypeId are passed
> > > > through the json file, where each of the UpdateImageTypeId has a
> > > > different value per payload.
> > > >
> > > > >
> > > > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > > > >    identified by ImageIndex.
> > > > > > >
> > > > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > > > a parameter.
> > > > > > >
> > > > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > > > doesn't meet the UEFI specification.
> > > > > >
> > > > > > So, as per what you are stating, all payloads under a given
> > > > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > > > fail.
> > > > >
> > > > > I don't follow your point.
> > > > > Please elaborate a bit more.
> > > >
> > > > The current implementation of GetImageInfo, passes either of
> > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > > > descriptor array. So, in case the capsule is generated with a '--guid'
> > > > value which is different from these two values, the check in
> > > > efi_fmp_find on line 204 will fail.
> > >
> > > That is an expected behavior, isn't it?
> >
> > Yes it is. Do not contest that.
> >
> > > If you want to use a different FMP driver (with another GUID),
> > > you naturally need to add your own FMP driver.
> >
> > This is where I differ. We can use the same FMP protocol instance for
> > any type of ImageTypeId. I do not see why we need to define a
> > different FMP protocol instance for a GUID value other than what has
> > been defined for u-boot raw and u-boot FIT GUIDs.
>
> I do understand part of your concern a bit.
> I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> but we needed different GUIDs here simply because we need to determine
> the format of payload, FIT format or raw binary.
>
> > The platform can give us the image descriptor array, and with that,
> > the same FMP instance can be used for any type of image(ImageTypeId).
>
> "any type of image"? Really?

The raw FMP instance can certainly handle any type of binary payloads
right. There is no restriction on what type of payload it is as long
as it is all going as a single entity to a given dfu partition.

> >
> > >
> > >
> > > > This means that unless the --guid
> > > > value passed to the capsule generation is either of u-boot FIT or
> > > > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > > > Why do we need that restriction. It should be possible to use the raw
> > > > FMP protocol for any other type of image types as well.
> > > >
> > > >
> > > > >
> > > > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > > > used to identify the firmware component targeted for the update. If
> > > > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > > > the same, why have this field in the first place for individual
> > > > > > images.
> > > > >
> > > > > As I said, ImageIndex is for that purpose.
> > > >
> > > > Yes, that is one possible way in the scenario where the ImageIndex is
> > > > determined at the capsule generation time. But, for the A/B update
> > > > scenario, we do not know the ImageIndex at build time
> > >
> > > "Build time" of what?
> >
> > Of the capsule.
> >
> > > I think that users should know how "dfu_alt_info" is defined
> > > (in other words, where the firmware be located on the target system)
> > > when capsule files are created.
> >
> > That is true for a non A/B scenario. And that is how it works in the
> > non A/B updates case. But for A/B updates, since the determination of
> > the "location" where the firmware image has to be written will be done
> > only at runtime, we cannot use the --index to differentiate.
>
> Yes, we can :)

You know what I mean -- if we could use the same logic, I would not
have added all that code :)

>
> First of all, my essential assumption in either FIT or RAW FMP driver
> is that U-Boot has (somehow conceptually) single firmware blob represented
> by DFU or dfu_alt_info. As I said, each object or location in
> dfu_alt_info can be further identified by index or "UpdateImageIndex".
>
> Let's assume that we have two locations of firmware, fw1 and fw2, and
> that we have two bank A and B.
> Then we will define dfu_alt_info as follows:
>   <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
>   |<---      1st set               --->|<---       2nd set               --->|
>
> When you want to update bank A, we can use the first set of dfu_alt_info,
> and use the second set of dfu_alt_info for bank B.
> At runtime, you should know which bank you're working on, and therefore
> you should know the exact physical location from dfu_alt_info.
>
> Please note that you don't have to change the syntax of dfu_alt_info
> at all. Simply offset the location with 0 for bank A and with 2 for bank B.

We can use this logic yes. But please note, that with this, we need to
a) Keep a definite order of the images in all the banks, and b) Know
the order of the images.

With the way the FWU metadata is designed, we do not have these
restrictions -- the firmware images can be placed on the device in any
order, irrespective of the bank that they belong to. One might prefer
clubbing images of a given bank together, but that is not the
restriction put by the FWU spec. That is because the images are being
identified using image GUIDs.

I really don't get your opposition to extending the current design. I
would like to hear from Heinrich or Ilias on what their thoughts are
on this.

-sughosh

>
> I don't think we need to introduce extra GUIDs.
>
> -Takahiro Akashi
>
> > Like I mentioned earlier, this is not breaking the existing behaviour
> > -- for the non A/B updates, the update procedure remains exactly the
> > same, of using the index value to determine the location of the
> > update. I have only extended the behaviour to use the same FMP
> > instance for the A/B update(FWU) feature using ImageTypeId's.
> >
> > -sughosh
> >
> > >
> > > -Takahiro Akashi
> > >
> > >
> > > > -- this is
> > > > determined only at runtime, and is based on the bank to which the
> > > > image is to be updated. Which is why I am finding out the alt_num at
> > > > runtime in case the FWU Multi Bank feature is enabled. Like I said
> > > > above, I do not see a reason why the current FMP protocols should be
> > > > restricted to only the u-boot FIT and u-boot raw image types. It is
> > > > being extended, without affecting the default non FWU behaviour.
> > > >
> > > > -sughosh
> > > >
> > > > >
> > > > > -Takahiro Akashi
> > > > >
> > > > > >
> > > > > > -sughosh
> > > > > >
> > > > > > >
> > > > > > > -Takahiro Akashi
> > > > > > >
> > > > > > >
> > > > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > > > ---
> > > > > > > >
> > > > > > > > Changes since V3:
> > > > > > > > * Define a weak function fill_image_type_guid_array for populating the
> > > > > > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > > > > > >
> > > > > > > >  include/efi_loader.h          |  2 +
> > > > > > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > > > > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > > > > index f4860e87fc..ae60de0be5 100644
> > > > > > > > --- a/include/efi_loader.h
> > > > > > > > +++ b/include/efi_loader.h
> > > > > > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > > > > > >  efi_status_t efi_load_capsule_drivers(void);
> > > > > > > >
> > > > > > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > > > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > > > > > +                                     efi_guid_t **part_guid_arr);
> > > > > > > >  #endif /* _EFI_LOADER_H */
> > > > > > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > > > > > index a1b88dbfc2..5642be9f9a 100644
> > > > > > > > --- a/lib/efi_loader/efi_firmware.c
> > > > > > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > > > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > > > > > +                                            efi_guid_t **part_guid_arr)
> > > > > > > > +{
> > > > > > > > +     int i;
> > > > > > > > +     int dfu_num = 0;
> > > > > > > > +     efi_guid_t *guid_arr;
> > > > > > > > +     struct dfu_entity *dfu;
> > > > > > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > > > > > +
> > > > > > > > +     dfu_init_env_entities(NULL, NULL);
> > > > > > > > +
> > > > > > > > +     dfu_num = 0;
> > > > > > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > > +             dfu_num++;
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     if (!dfu_num) {
> > > > > > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > > > > > +             ret = EFI_NOT_READY;
> > > > > > > > +             goto out;
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > > > > > +     if (!*part_guid_arr) {
> > > > > > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > > > > > +             goto out;
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +     guid_arr = *part_guid_arr;
> > > > > > > > +     for (i = 0; i < dfu_num; i++) {
> > > > > > > > +             guidcpy(guid_arr, guid);
> > > > > > > > +             ++guid_arr;
> > > > > > > > +     }
> > > > > > > > +
> > > > > > > > +out:
> > > > > > > > +     dfu_free_entities();
> > > > > > > > +
> > > > > > > > +     return ret;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >  /**
> > > > > > > >   * efi_get_dfu_info - return information about the current firmware image
> > > > > > > >   * @this:                    Protocol instance
> > > > > > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > > >   * @descriptor_version:              Pointer to version number
> > > > > > > >   * @descriptor_count:                Pointer to number of descriptors
> > > > > > > >   * @descriptor_size:         Pointer to descriptor size
> > > > > > > > - * package_version:          Package version
> > > > > > > > - * package_version_name:     Package version's name
> > > > > > > > - * image_type:                       Image type GUID
> > > > > > > > + * @package_version:         Package version
> > > > > > > > + * @package_version_name:    Package version's name
> > > > > > > > + * @guid_array:                      Image type GUID array
> > > > > > > >   *
> > > > > > > >   * Return information bout the current firmware image in @image_info.
> > > > > > > >   * @image_info will consist of a number of descriptors.
> > > > > > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > > >       efi_uintn_t *descriptor_size,
> > > > > > > >       u32 *package_version,
> > > > > > > >       u16 **package_version_name,
> > > > > > > > -     const efi_guid_t *image_type)
> > > > > > > > +     const efi_guid_t *guid_array)
> > > > > > > >  {
> > > > > > > >       struct dfu_entity *dfu;
> > > > > > > >       size_t names_len, total_size;
> > > > > > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > > >       next = name;
> > > > > > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > >               image_info[i].image_index = dfu->alt + 1;
> > > > > > > > -             image_info[i].image_type_id = *image_type;
> > > > > > > > +             image_info[i].image_type_id = guid_array[i];
> > > > > > > >               image_info[i].image_id = dfu->alt;
> > > > > > > >
> > > > > > > >               /* copy the DFU entity name */
> > > > > > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > > >       u16 **package_version_name)
> > > > > > > >  {
> > > > > > > >       efi_status_t ret;
> > > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > > >
> > > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > > >                 image_info_size, image_info,
> > > > > > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > > >
> > > > > > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > > > > > +                                      &part_guid_arr);
> > > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > > +             goto out;
> > > > > > > > +
> > > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > > >                              descriptor_version, descriptor_count,
> > > > > > > >                              descriptor_size,
> > > > > > > >                              package_version, package_version_name,
> > > > > > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > > > > > +                            part_guid_arr);
> > > > > > > >
> > > > > > > > +out:
> > > > > > > > +     free(part_guid_arr);
> > > > > > > >       return EFI_EXIT(ret);
> > > > > > > >  }
> > > > > > > >
> > > > > > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > > >       u16 **package_version_name)
> > > > > > > >  {
> > > > > > > >       efi_status_t ret = EFI_SUCCESS;
> > > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > > >
> > > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > > >                 image_info_size, image_info,
> > > > > > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > > >
> > > > > > > > +     ret = fill_image_type_guid_array(
> > > > > > > > +             &efi_firmware_image_type_uboot_raw,
> > > > > > > > +             &part_guid_arr);
> > > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > > +             goto out;
> > > > > > > > +
> > > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > > >                              descriptor_version, descriptor_count,
> > > > > > > >                              descriptor_size,
> > > > > > > >                              package_version, package_version_name,
> > > > > > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > > > > > +                            part_guid_arr);
> > > > > > > >
> > > > > > > > +out:
> > > > > > > > +     free(part_guid_arr);
> > > > > > > >       return EFI_EXIT(ret);
> > > > > > > >  }
> > > > > > > >
> > > > > > > > --
> > > > > > > > 2.17.1
> > > > > > > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-15  6:38                 ` Sughosh Ganu
@ 2022-02-15 14:40                   ` Ilias Apalodimas
  2022-02-15 17:19                     ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Ilias Apalodimas @ 2022-02-15 14:40 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: AKASHI Takahiro, u-boot, Heinrich Schuchardt, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Alexander Graf, Simon Glass,
	Bin Meng, Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

Hi, 

Took me some time to go through the whole thread, but here it goes. 

On Tue, Feb 15, 2022 at 12:08:30PM +0530, Sughosh Ganu wrote:
> On Tue, 15 Feb 2022 at 07:21, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > Sughosh,
> >
> > On Mon, Feb 14, 2022 at 11:12:22AM +0530, Sughosh Ganu wrote:
> > > hi Takahiro,
> > >
> > > On Mon, 14 Feb 2022 at 08:54, AKASHI Takahiro
> > > <takahiro.akashi@linaro.org> wrote:
> > > >
> > > > Sughosh,
> > > >
> > > > On Thu, Feb 10, 2022 at 03:40:00PM +0530, Sughosh Ganu wrote:
> > > > > On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
> > > > > <takahiro.akashi@linaro.org> wrote:
> > > > > >
> > > > > > On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > > > > > > hi Takahiro,
> > > > > > >
> > > > > > > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > > > > > > <takahiro.akashi@linaro.org> wrote:
> > > > > > > >
> > > > > > > > Hi Sughosh,
> > > > > > > >
> > > > > > > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > > > > > > The FWU Multi Banks Update feature allows updating different types of
> > > > > > > > > updatable firmware images on the platform. These image types are
> > > > > > > > > identified using the ImageTypeId GUID value. Add support in the
> > > > > > > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > > > > > > the individual images and populate these in the image descriptor for
> > > > > > > > > the corresponding images.
> > > > > > > >
> > > > > > > > After re-thinking of your approach here, I would have to say NAK.
> > > > > > > >
> > > > > > > > You use ImageTypeId to identify a particular firmware object.
> > > > > > > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > > > > > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > > > > > > But ImageTypeId is not for that purpose, at least, as my intention
> > > > > > > > in initially implementing capsule framework and FMP drivers.
> > > > > > > >
> > > > > > > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > > > > > > >    either FIT FMP driver or Raw FMP driver.
> > > > > > >
> > > > > > > I believe the identification of an FMP protocol should be done by the
> > > > > > > FMP GUID,
> > > > > >
> > > > > > What does FMP GUID stand for?
> > > > >
> > > > > EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
> > > > > What I mean is that even when installing the FMP protocol, the call to
> > > > > efi_install_multiple_protocol_interfaces takes the above FMP GUID as
> > > > > an argument -- nowhere is the ImageTypeId considered when installing
> > > > > the protocol.
> > > >
> > > > Okay.
> > > >
> > > > > >
> > > > > > > which is what is done in efi_fmp_find. The ImageTypeId is
> > > > > > > nowhere involved in this identification.
> > > > > >
> > > > > > Please take a look at efi_capsule_update_firmware() carefully.
> > > > > > efi_find_fmp() is called with the image's update_image_type_id
> > > > > > which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> > > > > > (see create_fwbin()).
> > > > >
> > > > > I think you are thinking from the point of view of the '--guid' value
> > > > > that is being passed to the capsule generation tool. But the thing is
> > > > > that it is the current design(or limitation) of the tool that it takes
> > > > > only a single guid parameter. So the mkeficapsule tool currently can
> > > > > generate only a single payload capsule.
> > > >
> > > > That is exactly what I intended to do here.
> > > > We have only one FMP driver (either FIT or RAW) which is based on
> > > > U-Boot's DFU framework and we need only one payload since, for
> > > > multiple objects of firmware, we can use FIT format as a payload.
> > > > That is what FIT is aimed for.
> > > > Or you can use multiple RAW capsule files with different indexes
> > > > ("--index" exists for this purpose).
> > >
> > > Yes, we can use --index when we know the index value corresponding to
> > > the firmware image that we need to update. But like I mentioned in my
> > > earlier reply, for A/B updates, we do not know what the index value is
> > > going to be. That is going to be determined at runtime.
> >
> > I don't think so. See below for alternative approach.
> >
> > > Also, the point I was making is that we can have a capsule which is
> > > consumed by an FMP protocol which has more than one image, and those
> > > images have different ImageTypeId/UpdateImageTypeId.
> >
> > Yes, but it is a design choice in my first implementation.
> > I didn't think that we need to "have a capsule which is consumed
> > by an FMP protocol which has more than one image" as long as we
> > use DFU framework (and FIT as standard format of aggregation on U-Boot).
> 
> But this design can be extended without any hassle, and more
> importantly without any regression, no? What kind of a problem does it
> create if the FMP can handle more than one image type.
> 
> Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
> header for all images to be managed by the FMP protocol which has
> multiple images with different UpdateImageTypeId.
> 
> >
> > > >
> > > > > Please check the
> > > > > GenerateCapsule script in EDK2. In case of a multi payload based
> > > > > capsule, individual parameters like the UpdateImageTypeId are passed
> > > > > through the json file, where each of the UpdateImageTypeId has a
> > > > > different value per payload.
> > > > >
> > > > > >
> > > > > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > > > > >    identified by ImageIndex.
> > > > > > > >
> > > > > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > > > > a parameter.
> > > > > > > >
> > > > > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > > > > doesn't meet the UEFI specification.
> > > > > > >
> > > > > > > So, as per what you are stating, all payloads under a given
> > > > > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > > > > fail.
> > > > > >
> > > > > > I don't follow your point.
> > > > > > Please elaborate a bit more.
> > > > >
> > > > > The current implementation of GetImageInfo, passes either of
> > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > > > > descriptor array. So, in case the capsule is generated with a '--guid'
> > > > > value which is different from these two values, the check in
> > > > > efi_fmp_find on line 204 will fail.
> > > >
> > > > That is an expected behavior, isn't it?
> > >
> > > Yes it is. Do not contest that.
> > >
> > > > If you want to use a different FMP driver (with another GUID),
> > > > you naturally need to add your own FMP driver.
> > >
> > > This is where I differ. We can use the same FMP protocol instance for
> > > any type of ImageTypeId. I do not see why we need to define a
> > > different FMP protocol instance for a GUID value other than what has
> > > been defined for u-boot raw and u-boot FIT GUIDs.
> >
> > I do understand part of your concern a bit.
> > I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> > but we needed different GUIDs here simply because we need to determine
> > the format of payload, FIT format or raw binary.
> >
> > > The platform can give us the image descriptor array, and with that,
> > > the same FMP instance can be used for any type of image(ImageTypeId).
> >
> > "any type of image"? Really?
> 
> The raw FMP instance can certainly handle any type of binary payloads
> right. There is no restriction on what type of payload it is as long
> as it is all going as a single entity to a given dfu partition.
> 
> > >
> > > >
> > > >
> > > > > This means that unless the --guid
> > > > > value passed to the capsule generation is either of u-boot FIT or
> > > > > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > > > > Why do we need that restriction. It should be possible to use the raw
> > > > > FMP protocol for any other type of image types as well.
> > > > >
> > > > >
> > > > > >
> > > > > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > > > > used to identify the firmware component targeted for the update. If
> > > > > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > > > > the same, why have this field in the first place for individual
> > > > > > > images.
> > > > > >
> > > > > > As I said, ImageIndex is for that purpose.
> > > > >
> > > > > Yes, that is one possible way in the scenario where the ImageIndex is
> > > > > determined at the capsule generation time. But, for the A/B update
> > > > > scenario, we do not know the ImageIndex at build time
> > > >
> > > > "Build time" of what?
> > >
> > > Of the capsule.
> > >
> > > > I think that users should know how "dfu_alt_info" is defined
> > > > (in other words, where the firmware be located on the target system)
> > > > when capsule files are created.
> > >
> > > That is true for a non A/B scenario. And that is how it works in the
> > > non A/B updates case. But for A/B updates, since the determination of
> > > the "location" where the firmware image has to be written will be done
> > > only at runtime, we cannot use the --index to differentiate.
> >
> > Yes, we can :)
> 
> You know what I mean -- if we could use the same logic, I would not
> have added all that code :)
> 
> >
> > First of all, my essential assumption in either FIT or RAW FMP driver
> > is that U-Boot has (somehow conceptually) single firmware blob represented
> > by DFU or dfu_alt_info. As I said, each object or location in
> > dfu_alt_info can be further identified by index or "UpdateImageIndex".
> >
> > Let's assume that we have two locations of firmware, fw1 and fw2, and
> > that we have two bank A and B.
> > Then we will define dfu_alt_info as follows:
> >   <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> >   |<---      1st set               --->|<---       2nd set               --->|
> >
> > When you want to update bank A, we can use the first set of dfu_alt_info,
> > and use the second set of dfu_alt_info for bank B.
> > At runtime, you should know which bank you're working on, and therefore
> > you should know the exact physical location from dfu_alt_info.
> >
> > Please note that you don't have to change the syntax of dfu_alt_info
> > at all. Simply offset the location with 0 for bank A and with 2 for bank B.

I'll try digging a bit more, but I think the current approach is not
working as it was intended wrt to the EFI spec.  My reading of the spec 
and specifically section 23.3.2 is that a Capsule consists of an 
EFI capsule header and a payload.  The payload now has an 
EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.

An FMP implementation should read the  UpdateImageTypeId's used to identify
the image you are updating and from that derive the UpdateImageIndex
which SetImage will use. That would give you the ability to update the
all the firmware components with a single capsule. 

Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
those should be reflected on the ESRT tables from the OS

Regards
/Ilias

> 
> We can use this logic yes. But please note, that with this, we need to
> a) Keep a definite order of the images in all the banks, and b) Know
> the order of the images.
> 
> With the way the FWU metadata is designed, we do not have these
> restrictions -- the firmware images can be placed on the device in any
> order, irrespective of the bank that they belong to. One might prefer
> clubbing images of a given bank together, but that is not the
> restriction put by the FWU spec. That is because the images are being
> identified using image GUIDs.
> 
> I really don't get your opposition to extending the current design. I
> would like to hear from Heinrich or Ilias on what their thoughts are
> on this.
> 
> -sughosh
> 
> >
> > I don't think we need to introduce extra GUIDs.
> >
> > -Takahiro Akashi
> >
> > > Like I mentioned earlier, this is not breaking the existing behaviour
> > > -- for the non A/B updates, the update procedure remains exactly the
> > > same, of using the index value to determine the location of the
> > > update. I have only extended the behaviour to use the same FMP
> > > instance for the A/B update(FWU) feature using ImageTypeId's.
> > >
> > > -sughosh
> > >
> > > >
> > > > -Takahiro Akashi
> > > >
> > > >
> > > > > -- this is
> > > > > determined only at runtime, and is based on the bank to which the
> > > > > image is to be updated. Which is why I am finding out the alt_num at
> > > > > runtime in case the FWU Multi Bank feature is enabled. Like I said
> > > > > above, I do not see a reason why the current FMP protocols should be
> > > > > restricted to only the u-boot FIT and u-boot raw image types. It is
> > > > > being extended, without affecting the default non FWU behaviour.
> > > > >
> > > > > -sughosh
> > > > >
> > > > > >
> > > > > > -Takahiro Akashi
> > > > > >
> > > > > > >
> > > > > > > -sughosh
> > > > > > >
> > > > > > > >
> > > > > > > > -Takahiro Akashi
> > > > > > > >
> > > > > > > >
> > > > > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > > > > ---
> > > > > > > > >
> > > > > > > > > Changes since V3:
> > > > > > > > > * Define a weak function fill_image_type_guid_array for populating the
> > > > > > > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > > > > > > >
> > > > > > > > >  include/efi_loader.h          |  2 +
> > > > > > > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > > > > > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > > > > > index f4860e87fc..ae60de0be5 100644
> > > > > > > > > --- a/include/efi_loader.h
> > > > > > > > > +++ b/include/efi_loader.h
> > > > > > > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > > > > > > >  efi_status_t efi_load_capsule_drivers(void);
> > > > > > > > >
> > > > > > > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > > > > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > > > > > > +                                     efi_guid_t **part_guid_arr);
> > > > > > > > >  #endif /* _EFI_LOADER_H */
> > > > > > > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > > > > > > index a1b88dbfc2..5642be9f9a 100644
> > > > > > > > > --- a/lib/efi_loader/efi_firmware.c
> > > > > > > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > > > > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > > > > > > +                                            efi_guid_t **part_guid_arr)
> > > > > > > > > +{
> > > > > > > > > +     int i;
> > > > > > > > > +     int dfu_num = 0;
> > > > > > > > > +     efi_guid_t *guid_arr;
> > > > > > > > > +     struct dfu_entity *dfu;
> > > > > > > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > > > > > > +
> > > > > > > > > +     dfu_init_env_entities(NULL, NULL);
> > > > > > > > > +
> > > > > > > > > +     dfu_num = 0;
> > > > > > > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > > > +             dfu_num++;
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     if (!dfu_num) {
> > > > > > > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > > > > > > +             ret = EFI_NOT_READY;
> > > > > > > > > +             goto out;
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > > > > > > +     if (!*part_guid_arr) {
> > > > > > > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > > > > > > +             goto out;
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +     guid_arr = *part_guid_arr;
> > > > > > > > > +     for (i = 0; i < dfu_num; i++) {
> > > > > > > > > +             guidcpy(guid_arr, guid);
> > > > > > > > > +             ++guid_arr;
> > > > > > > > > +     }
> > > > > > > > > +
> > > > > > > > > +out:
> > > > > > > > > +     dfu_free_entities();
> > > > > > > > > +
> > > > > > > > > +     return ret;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >  /**
> > > > > > > > >   * efi_get_dfu_info - return information about the current firmware image
> > > > > > > > >   * @this:                    Protocol instance
> > > > > > > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > > > >   * @descriptor_version:              Pointer to version number
> > > > > > > > >   * @descriptor_count:                Pointer to number of descriptors
> > > > > > > > >   * @descriptor_size:         Pointer to descriptor size
> > > > > > > > > - * package_version:          Package version
> > > > > > > > > - * package_version_name:     Package version's name
> > > > > > > > > - * image_type:                       Image type GUID
> > > > > > > > > + * @package_version:         Package version
> > > > > > > > > + * @package_version_name:    Package version's name
> > > > > > > > > + * @guid_array:                      Image type GUID array
> > > > > > > > >   *
> > > > > > > > >   * Return information bout the current firmware image in @image_info.
> > > > > > > > >   * @image_info will consist of a number of descriptors.
> > > > > > > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > > > >       efi_uintn_t *descriptor_size,
> > > > > > > > >       u32 *package_version,
> > > > > > > > >       u16 **package_version_name,
> > > > > > > > > -     const efi_guid_t *image_type)
> > > > > > > > > +     const efi_guid_t *guid_array)
> > > > > > > > >  {
> > > > > > > > >       struct dfu_entity *dfu;
> > > > > > > > >       size_t names_len, total_size;
> > > > > > > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > > > >       next = name;
> > > > > > > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > > >               image_info[i].image_index = dfu->alt + 1;
> > > > > > > > > -             image_info[i].image_type_id = *image_type;
> > > > > > > > > +             image_info[i].image_type_id = guid_array[i];
> > > > > > > > >               image_info[i].image_id = dfu->alt;
> > > > > > > > >
> > > > > > > > >               /* copy the DFU entity name */
> > > > > > > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > > > >       u16 **package_version_name)
> > > > > > > > >  {
> > > > > > > > >       efi_status_t ret;
> > > > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > > > >
> > > > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > > > >                 image_info_size, image_info,
> > > > > > > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > > > >
> > > > > > > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > > > > > > +                                      &part_guid_arr);
> > > > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > > > +             goto out;
> > > > > > > > > +
> > > > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > > > >                              descriptor_version, descriptor_count,
> > > > > > > > >                              descriptor_size,
> > > > > > > > >                              package_version, package_version_name,
> > > > > > > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > > > > > > +                            part_guid_arr);
> > > > > > > > >
> > > > > > > > > +out:
> > > > > > > > > +     free(part_guid_arr);
> > > > > > > > >       return EFI_EXIT(ret);
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > > > >       u16 **package_version_name)
> > > > > > > > >  {
> > > > > > > > >       efi_status_t ret = EFI_SUCCESS;
> > > > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > > > >
> > > > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > > > >                 image_info_size, image_info,
> > > > > > > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > > > >
> > > > > > > > > +     ret = fill_image_type_guid_array(
> > > > > > > > > +             &efi_firmware_image_type_uboot_raw,
> > > > > > > > > +             &part_guid_arr);
> > > > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > > > +             goto out;
> > > > > > > > > +
> > > > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > > > >                              descriptor_version, descriptor_count,
> > > > > > > > >                              descriptor_size,
> > > > > > > > >                              package_version, package_version_name,
> > > > > > > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > > > > > > +                            part_guid_arr);
> > > > > > > > >
> > > > > > > > > +out:
> > > > > > > > > +     free(part_guid_arr);
> > > > > > > > >       return EFI_EXIT(ret);
> > > > > > > > >  }
> > > > > > > > >
> > > > > > > > > --
> > > > > > > > > 2.17.1
> > > > > > > > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-15 14:40                   ` Ilias Apalodimas
@ 2022-02-15 17:19                     ` Sughosh Ganu
  2022-02-17  8:22                       ` Ilias Apalodimas
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-15 17:19 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: AKASHI Takahiro, u-boot, Heinrich Schuchardt, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Alexander Graf, Simon Glass,
	Bin Meng, Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

hi Ilias,

On Tue, 15 Feb 2022 at 20:10, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi,
>
> Took me some time to go through the whole thread, but here it goes.
>
> On Tue, Feb 15, 2022 at 12:08:30PM +0530, Sughosh Ganu wrote:
> > On Tue, 15 Feb 2022 at 07:21, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > Sughosh,
> > >
> > > On Mon, Feb 14, 2022 at 11:12:22AM +0530, Sughosh Ganu wrote:
> > > > hi Takahiro,
> > > >
> > > > On Mon, 14 Feb 2022 at 08:54, AKASHI Takahiro
> > > > <takahiro.akashi@linaro.org> wrote:
> > > > >
> > > > > Sughosh,
> > > > >
> > > > > On Thu, Feb 10, 2022 at 03:40:00PM +0530, Sughosh Ganu wrote:
> > > > > > On Thu, 10 Feb 2022 at 13:28, AKASHI Takahiro
> > > > > > <takahiro.akashi@linaro.org> wrote:
> > > > > > >
> > > > > > > On Thu, Feb 10, 2022 at 12:48:13PM +0530, Sughosh Ganu wrote:
> > > > > > > > hi Takahiro,
> > > > > > > >
> > > > > > > > On Thu, 10 Feb 2022 at 08:18, AKASHI Takahiro
> > > > > > > > <takahiro.akashi@linaro.org> wrote:
> > > > > > > > >
> > > > > > > > > Hi Sughosh,
> > > > > > > > >
> > > > > > > > > On Mon, Feb 07, 2022 at 11:49:55PM +0530, Sughosh Ganu wrote:
> > > > > > > > > > The FWU Multi Banks Update feature allows updating different types of
> > > > > > > > > > updatable firmware images on the platform. These image types are
> > > > > > > > > > identified using the ImageTypeId GUID value. Add support in the
> > > > > > > > > > GetImageInfo function of the FMP protocol to get the GUID values for
> > > > > > > > > > the individual images and populate these in the image descriptor for
> > > > > > > > > > the corresponding images.
> > > > > > > > >
> > > > > > > > > After re-thinking of your approach here, I would have to say NAK.
> > > > > > > > >
> > > > > > > > > You use ImageTypeId to identify a particular firmware object.
> > > > > > > > > (By "object," I mean one of firmware instances represented by "dfu_alto_info".
> > > > > > > > > Please don't confuse it with the binary blob embedded in a capsule file.)
> > > > > > > > > But ImageTypeId is not for that purpose, at least, as my intention
> > > > > > > > > in initially implementing capsule framework and FMP drivers.
> > > > > > > > >
> > > > > > > > > 1) ImageTypeId is used to uniquely identify a corresponding FMP driver,
> > > > > > > > >    either FIT FMP driver or Raw FMP driver.
> > > > > > > >
> > > > > > > > I believe the identification of an FMP protocol should be done by the
> > > > > > > > FMP GUID,
> > > > > > >
> > > > > > > What does FMP GUID stand for?
> > > > > >
> > > > > > EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID, defined in include/efi_api.h.
> > > > > > What I mean is that even when installing the FMP protocol, the call to
> > > > > > efi_install_multiple_protocol_interfaces takes the above FMP GUID as
> > > > > > an argument -- nowhere is the ImageTypeId considered when installing
> > > > > > the protocol.
> > > > >
> > > > > Okay.
> > > > >
> > > > > > >
> > > > > > > > which is what is done in efi_fmp_find. The ImageTypeId is
> > > > > > > > nowhere involved in this identification.
> > > > > > >
> > > > > > > Please take a look at efi_capsule_update_firmware() carefully.
> > > > > > > efi_find_fmp() is called with the image's update_image_type_id
> > > > > > > which is to be set to EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID by mkeficapsule
> > > > > > > (see create_fwbin()).
> > > > > >
> > > > > > I think you are thinking from the point of view of the '--guid' value
> > > > > > that is being passed to the capsule generation tool. But the thing is
> > > > > > that it is the current design(or limitation) of the tool that it takes
> > > > > > only a single guid parameter. So the mkeficapsule tool currently can
> > > > > > generate only a single payload capsule.
> > > > >
> > > > > That is exactly what I intended to do here.
> > > > > We have only one FMP driver (either FIT or RAW) which is based on
> > > > > U-Boot's DFU framework and we need only one payload since, for
> > > > > multiple objects of firmware, we can use FIT format as a payload.
> > > > > That is what FIT is aimed for.
> > > > > Or you can use multiple RAW capsule files with different indexes
> > > > > ("--index" exists for this purpose).
> > > >
> > > > Yes, we can use --index when we know the index value corresponding to
> > > > the firmware image that we need to update. But like I mentioned in my
> > > > earlier reply, for A/B updates, we do not know what the index value is
> > > > going to be. That is going to be determined at runtime.
> > >
> > > I don't think so. See below for alternative approach.
> > >
> > > > Also, the point I was making is that we can have a capsule which is
> > > > consumed by an FMP protocol which has more than one image, and those
> > > > images have different ImageTypeId/UpdateImageTypeId.
> > >
> > > Yes, but it is a design choice in my first implementation.
> > > I didn't think that we need to "have a capsule which is consumed
> > > by an FMP protocol which has more than one image" as long as we
> > > use DFU framework (and FIT as standard format of aggregation on U-Boot).
> >
> > But this design can be extended without any hassle, and more
> > importantly without any regression, no? What kind of a problem does it
> > create if the FMP can handle more than one image type.
> >
> > Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
> > header for all images to be managed by the FMP protocol which has
> > multiple images with different UpdateImageTypeId.
> >
> > >
> > > > >
> > > > > > Please check the
> > > > > > GenerateCapsule script in EDK2. In case of a multi payload based
> > > > > > capsule, individual parameters like the UpdateImageTypeId are passed
> > > > > > through the json file, where each of the UpdateImageTypeId has a
> > > > > > different value per payload.
> > > > > >
> > > > > > >
> > > > > > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > > > > > >    identified by ImageIndex.
> > > > > > > > >
> > > > > > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > > > > > a parameter.
> > > > > > > > >
> > > > > > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > > > > > doesn't meet the UEFI specification.
> > > > > > > >
> > > > > > > > So, as per what you are stating, all payloads under a given
> > > > > > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > > > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > > > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > > > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > > > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > > > > > fail.
> > > > > > >
> > > > > > > I don't follow your point.
> > > > > > > Please elaborate a bit more.
> > > > > >
> > > > > > The current implementation of GetImageInfo, passes either of
> > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > > > > > descriptor array. So, in case the capsule is generated with a '--guid'
> > > > > > value which is different from these two values, the check in
> > > > > > efi_fmp_find on line 204 will fail.
> > > > >
> > > > > That is an expected behavior, isn't it?
> > > >
> > > > Yes it is. Do not contest that.
> > > >
> > > > > If you want to use a different FMP driver (with another GUID),
> > > > > you naturally need to add your own FMP driver.
> > > >
> > > > This is where I differ. We can use the same FMP protocol instance for
> > > > any type of ImageTypeId. I do not see why we need to define a
> > > > different FMP protocol instance for a GUID value other than what has
> > > > been defined for u-boot raw and u-boot FIT GUIDs.
> > >
> > > I do understand part of your concern a bit.
> > > I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> > > but we needed different GUIDs here simply because we need to determine
> > > the format of payload, FIT format or raw binary.
> > >
> > > > The platform can give us the image descriptor array, and with that,
> > > > the same FMP instance can be used for any type of image(ImageTypeId).
> > >
> > > "any type of image"? Really?
> >
> > The raw FMP instance can certainly handle any type of binary payloads
> > right. There is no restriction on what type of payload it is as long
> > as it is all going as a single entity to a given dfu partition.
> >
> > > >
> > > > >
> > > > >
> > > > > > This means that unless the --guid
> > > > > > value passed to the capsule generation is either of u-boot FIT or
> > > > > > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > > > > > Why do we need that restriction. It should be possible to use the raw
> > > > > > FMP protocol for any other type of image types as well.
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > > > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > > > > > used to identify the firmware component targeted for the update. If
> > > > > > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > > > > > the same, why have this field in the first place for individual
> > > > > > > > images.
> > > > > > >
> > > > > > > As I said, ImageIndex is for that purpose.
> > > > > >
> > > > > > Yes, that is one possible way in the scenario where the ImageIndex is
> > > > > > determined at the capsule generation time. But, for the A/B update
> > > > > > scenario, we do not know the ImageIndex at build time
> > > > >
> > > > > "Build time" of what?
> > > >
> > > > Of the capsule.
> > > >
> > > > > I think that users should know how "dfu_alt_info" is defined
> > > > > (in other words, where the firmware be located on the target system)
> > > > > when capsule files are created.
> > > >
> > > > That is true for a non A/B scenario. And that is how it works in the
> > > > non A/B updates case. But for A/B updates, since the determination of
> > > > the "location" where the firmware image has to be written will be done
> > > > only at runtime, we cannot use the --index to differentiate.
> > >
> > > Yes, we can :)
> >
> > You know what I mean -- if we could use the same logic, I would not
> > have added all that code :)
> >
> > >
> > > First of all, my essential assumption in either FIT or RAW FMP driver
> > > is that U-Boot has (somehow conceptually) single firmware blob represented
> > > by DFU or dfu_alt_info. As I said, each object or location in
> > > dfu_alt_info can be further identified by index or "UpdateImageIndex".
> > >
> > > Let's assume that we have two locations of firmware, fw1 and fw2, and
> > > that we have two bank A and B.
> > > Then we will define dfu_alt_info as follows:
> > >   <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> > >   |<---      1st set               --->|<---       2nd set               --->|
> > >
> > > When you want to update bank A, we can use the first set of dfu_alt_info,
> > > and use the second set of dfu_alt_info for bank B.
> > > At runtime, you should know which bank you're working on, and therefore
> > > you should know the exact physical location from dfu_alt_info.
> > >
> > > Please note that you don't have to change the syntax of dfu_alt_info
> > > at all. Simply offset the location with 0 for bank A and with 2 for bank B.
>
> I'll try digging a bit more, but I think the current approach is not
> working as it was intended wrt to the EFI spec.  My reading of the spec
> and specifically section 23.3.2 is that a Capsule consists of an
> EFI capsule header and a payload.  The payload now has an
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
> firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
>
> An FMP implementation should read the  UpdateImageTypeId's used to identify
> the image you are updating and from that derive the UpdateImageIndex
> which SetImage will use. That would give you the ability to update the
> all the firmware components with a single capsule.
>
> Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
> those should be reflected on the ESRT tables from the OS

That would depend on the values populated in the
EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
image descriptor structure has an ImageTypeId field. The value of
ImageTypeId is what will be reflected in the ESRT table.

In the current implementation, all the images in the ESRT table will
show the same ImageTypeId value, either
EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.

The UpdateImageTypeId value from the capsule is used to compare with
the ImageTypeId values returned by the GetImageInfo function to check
if the given FMP protocol can be used for the update.

-sughosh

>
> Regards
> /Ilias
>
> >
> > We can use this logic yes. But please note, that with this, we need to
> > a) Keep a definite order of the images in all the banks, and b) Know
> > the order of the images.
> >
> > With the way the FWU metadata is designed, we do not have these
> > restrictions -- the firmware images can be placed on the device in any
> > order, irrespective of the bank that they belong to. One might prefer
> > clubbing images of a given bank together, but that is not the
> > restriction put by the FWU spec. That is because the images are being
> > identified using image GUIDs.
> >
> > I really don't get your opposition to extending the current design. I
> > would like to hear from Heinrich or Ilias on what their thoughts are
> > on this.
> >
> > -sughosh
> >
> > >
> > > I don't think we need to introduce extra GUIDs.
> > >
> > > -Takahiro Akashi
> > >
> > > > Like I mentioned earlier, this is not breaking the existing behaviour
> > > > -- for the non A/B updates, the update procedure remains exactly the
> > > > same, of using the index value to determine the location of the
> > > > update. I have only extended the behaviour to use the same FMP
> > > > instance for the A/B update(FWU) feature using ImageTypeId's.
> > > >
> > > > -sughosh
> > > >
> > > > >
> > > > > -Takahiro Akashi
> > > > >
> > > > >
> > > > > > -- this is
> > > > > > determined only at runtime, and is based on the bank to which the
> > > > > > image is to be updated. Which is why I am finding out the alt_num at
> > > > > > runtime in case the FWU Multi Bank feature is enabled. Like I said
> > > > > > above, I do not see a reason why the current FMP protocols should be
> > > > > > restricted to only the u-boot FIT and u-boot raw image types. It is
> > > > > > being extended, without affecting the default non FWU behaviour.
> > > > > >
> > > > > > -sughosh
> > > > > >
> > > > > > >
> > > > > > > -Takahiro Akashi
> > > > > > >
> > > > > > > >
> > > > > > > > -sughosh
> > > > > > > >
> > > > > > > > >
> > > > > > > > > -Takahiro Akashi
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > > > > > > > ---
> > > > > > > > > >
> > > > > > > > > > Changes since V3:
> > > > > > > > > > * Define a weak function fill_image_type_guid_array for populating the
> > > > > > > > > >   image descriptor array with u-boot's raw and fit image GUIDs
> > > > > > > > > >
> > > > > > > > > >  include/efi_loader.h          |  2 +
> > > > > > > > > >  lib/efi_loader/efi_firmware.c | 71 +++++++++++++++++++++++++++++++----
> > > > > > > > > >  2 files changed, 66 insertions(+), 7 deletions(-)
> > > > > > > > > >
> > > > > > > > > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > > > > > > > > index f4860e87fc..ae60de0be5 100644
> > > > > > > > > > --- a/include/efi_loader.h
> > > > > > > > > > +++ b/include/efi_loader.h
> > > > > > > > > > @@ -992,4 +992,6 @@ efi_status_t efi_esrt_populate(void);
> > > > > > > > > >  efi_status_t efi_load_capsule_drivers(void);
> > > > > > > > > >
> > > > > > > > > >  efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz);
> > > > > > > > > > +efi_status_t fill_image_type_guid_array(const efi_guid_t *default_guid,
> > > > > > > > > > +                                     efi_guid_t **part_guid_arr);
> > > > > > > > > >  #endif /* _EFI_LOADER_H */
> > > > > > > > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > > > > > > > index a1b88dbfc2..5642be9f9a 100644
> > > > > > > > > > --- a/lib/efi_loader/efi_firmware.c
> > > > > > > > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > > > > > > > @@ -96,6 +96,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > > > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > > > > > > > >  }
> > > > > > > > > >
> > > > > > > > > > +efi_status_t __weak fill_image_type_guid_array(const efi_guid_t *guid,
> > > > > > > > > > +                                            efi_guid_t **part_guid_arr)
> > > > > > > > > > +{
> > > > > > > > > > +     int i;
> > > > > > > > > > +     int dfu_num = 0;
> > > > > > > > > > +     efi_guid_t *guid_arr;
> > > > > > > > > > +     struct dfu_entity *dfu;
> > > > > > > > > > +     efi_status_t ret = EFI_SUCCESS;
> > > > > > > > > > +
> > > > > > > > > > +     dfu_init_env_entities(NULL, NULL);
> > > > > > > > > > +
> > > > > > > > > > +     dfu_num = 0;
> > > > > > > > > > +     list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > > > > +             dfu_num++;
> > > > > > > > > > +     }
> > > > > > > > > > +
> > > > > > > > > > +     if (!dfu_num) {
> > > > > > > > > > +             log_warning("Probably dfu_alt_info not defined\n");
> > > > > > > > > > +             ret = EFI_NOT_READY;
> > > > > > > > > > +             goto out;
> > > > > > > > > > +     }
> > > > > > > > > > +
> > > > > > > > > > +     *part_guid_arr = malloc(sizeof(efi_guid_t) * dfu_num);
> > > > > > > > > > +     if (!*part_guid_arr) {
> > > > > > > > > > +             ret = EFI_OUT_OF_RESOURCES;
> > > > > > > > > > +             goto out;
> > > > > > > > > > +     }
> > > > > > > > > > +
> > > > > > > > > > +     guid_arr = *part_guid_arr;
> > > > > > > > > > +     for (i = 0; i < dfu_num; i++) {
> > > > > > > > > > +             guidcpy(guid_arr, guid);
> > > > > > > > > > +             ++guid_arr;
> > > > > > > > > > +     }
> > > > > > > > > > +
> > > > > > > > > > +out:
> > > > > > > > > > +     dfu_free_entities();
> > > > > > > > > > +
> > > > > > > > > > +     return ret;
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > >  /**
> > > > > > > > > >   * efi_get_dfu_info - return information about the current firmware image
> > > > > > > > > >   * @this:                    Protocol instance
> > > > > > > > > > @@ -104,9 +144,9 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > > > > > > > >   * @descriptor_version:              Pointer to version number
> > > > > > > > > >   * @descriptor_count:                Pointer to number of descriptors
> > > > > > > > > >   * @descriptor_size:         Pointer to descriptor size
> > > > > > > > > > - * package_version:          Package version
> > > > > > > > > > - * package_version_name:     Package version's name
> > > > > > > > > > - * image_type:                       Image type GUID
> > > > > > > > > > + * @package_version:         Package version
> > > > > > > > > > + * @package_version_name:    Package version's name
> > > > > > > > > > + * @guid_array:                      Image type GUID array
> > > > > > > > > >   *
> > > > > > > > > >   * Return information bout the current firmware image in @image_info.
> > > > > > > > > >   * @image_info will consist of a number of descriptors.
> > > > > > > > > > @@ -122,7 +162,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > > > > >       efi_uintn_t *descriptor_size,
> > > > > > > > > >       u32 *package_version,
> > > > > > > > > >       u16 **package_version_name,
> > > > > > > > > > -     const efi_guid_t *image_type)
> > > > > > > > > > +     const efi_guid_t *guid_array)
> > > > > > > > > >  {
> > > > > > > > > >       struct dfu_entity *dfu;
> > > > > > > > > >       size_t names_len, total_size;
> > > > > > > > > > @@ -172,7 +212,7 @@ static efi_status_t efi_get_dfu_info(
> > > > > > > > > >       next = name;
> > > > > > > > > >       list_for_each_entry(dfu, &dfu_list, list) {
> > > > > > > > > >               image_info[i].image_index = dfu->alt + 1;
> > > > > > > > > > -             image_info[i].image_type_id = *image_type;
> > > > > > > > > > +             image_info[i].image_type_id = guid_array[i];
> > > > > > > > > >               image_info[i].image_id = dfu->alt;
> > > > > > > > > >
> > > > > > > > > >               /* copy the DFU entity name */
> > > > > > > > > > @@ -250,6 +290,7 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > > > > >       u16 **package_version_name)
> > > > > > > > > >  {
> > > > > > > > > >       efi_status_t ret;
> > > > > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > > > > >
> > > > > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > > > > >                 image_info_size, image_info,
> > > > > > > > > > @@ -264,12 +305,19 @@ efi_status_t EFIAPI efi_firmware_fit_get_image_info(
> > > > > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > > > > >
> > > > > > > > > > +     ret = fill_image_type_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > > > > > > > +                                      &part_guid_arr);
> > > > > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > > > > +             goto out;
> > > > > > > > > > +
> > > > > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > > > > >                              descriptor_version, descriptor_count,
> > > > > > > > > >                              descriptor_size,
> > > > > > > > > >                              package_version, package_version_name,
> > > > > > > > > > -                            &efi_firmware_image_type_uboot_fit);
> > > > > > > > > > +                            part_guid_arr);
> > > > > > > > > >
> > > > > > > > > > +out:
> > > > > > > > > > +     free(part_guid_arr);
> > > > > > > > > >       return EFI_EXIT(ret);
> > > > > > > > > >  }
> > > > > > > > > >
> > > > > > > > > > @@ -359,6 +407,7 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > > > > >       u16 **package_version_name)
> > > > > > > > > >  {
> > > > > > > > > >       efi_status_t ret = EFI_SUCCESS;
> > > > > > > > > > +     efi_guid_t *part_guid_arr = NULL;
> > > > > > > > > >
> > > > > > > > > >       EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> > > > > > > > > >                 image_info_size, image_info,
> > > > > > > > > > @@ -373,12 +422,20 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > > > > > > > >            !descriptor_size || !package_version || !package_version_name))
> > > > > > > > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > > > > > > > >
> > > > > > > > > > +     ret = fill_image_type_guid_array(
> > > > > > > > > > +             &efi_firmware_image_type_uboot_raw,
> > > > > > > > > > +             &part_guid_arr);
> > > > > > > > > > +     if (ret != EFI_SUCCESS)
> > > > > > > > > > +             goto out;
> > > > > > > > > > +
> > > > > > > > > >       ret = efi_get_dfu_info(image_info_size, image_info,
> > > > > > > > > >                              descriptor_version, descriptor_count,
> > > > > > > > > >                              descriptor_size,
> > > > > > > > > >                              package_version, package_version_name,
> > > > > > > > > > -                            &efi_firmware_image_type_uboot_raw);
> > > > > > > > > > +                            part_guid_arr);
> > > > > > > > > >
> > > > > > > > > > +out:
> > > > > > > > > > +     free(part_guid_arr);
> > > > > > > > > >       return EFI_EXIT(ret);
> > > > > > > > > >  }
> > > > > > > > > >
> > > > > > > > > > --
> > > > > > > > > > 2.17.1
> > > > > > > > > >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-15 17:19                     ` Sughosh Ganu
@ 2022-02-17  8:22                       ` Ilias Apalodimas
  2022-02-17 10:10                         ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Ilias Apalodimas @ 2022-02-17  8:22 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: AKASHI Takahiro, u-boot, Heinrich Schuchardt, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Alexander Graf, Simon Glass,
	Bin Meng, Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

> > > > >

[...]

> > > > > Yes, we can use --index when we know the index value corresponding to
> > > > > the firmware image that we need to update. But like I mentioned in my
> > > > > earlier reply, for A/B updates, we do not know what the index value is
> > > > > going to be. That is going to be determined at runtime.
> > > >
> > > > I don't think so. See below for alternative approach.
> > > >
> > > > > Also, the point I was making is that we can have a capsule which is
> > > > > consumed by an FMP protocol which has more than one image, and those
> > > > > images have different ImageTypeId/UpdateImageTypeId.
> > > >
> > > > Yes, but it is a design choice in my first implementation.
> > > > I didn't think that we need to "have a capsule which is consumed
> > > > by an FMP protocol which has more than one image" as long as we
> > > > use DFU framework (and FIT as standard format of aggregation on U-Boot).
> > >
> > > But this design can be extended without any hassle, and more
> > > importantly without any regression, no? What kind of a problem does it
> > > create if the FMP can handle more than one image type.
> > >
> > > Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
> > > header for all images to be managed by the FMP protocol which has
> > > multiple images with different UpdateImageTypeId.
> > >
> > > >
> > > > > >
> > > > > > > Please check the
> > > > > > > GenerateCapsule script in EDK2. In case of a multi payload based
> > > > > > > capsule, individual parameters like the UpdateImageTypeId are passed
> > > > > > > through the json file, where each of the UpdateImageTypeId has a
> > > > > > > different value per payload.
> > > > > > >
> > > > > > > >
> > > > > > > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > > > > > > >    identified by ImageIndex.
> > > > > > > > > >
> > > > > > > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > > > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > > > > > > a parameter.
> > > > > > > > > >
> > > > > > > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > > > > > > doesn't meet the UEFI specification.
> > > > > > > > >
> > > > > > > > > So, as per what you are stating, all payloads under a given
> > > > > > > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > > > > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > > > > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > > > > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > > > > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > > > > > > fail.
> > > > > > > >
> > > > > > > > I don't follow your point.
> > > > > > > > Please elaborate a bit more.
> > > > > > >
> > > > > > > The current implementation of GetImageInfo, passes either of
> > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > > > > > > descriptor array. So, in case the capsule is generated with a '--guid'
> > > > > > > value which is different from these two values, the check in
> > > > > > > efi_fmp_find on line 204 will fail.
> > > > > >
> > > > > > That is an expected behavior, isn't it?
> > > > >
> > > > > Yes it is. Do not contest that.
> > > > >
> > > > > > If you want to use a different FMP driver (with another GUID),
> > > > > > you naturally need to add your own FMP driver.
> > > > >
> > > > > This is where I differ. We can use the same FMP protocol instance for
> > > > > any type of ImageTypeId. I do not see why we need to define a
> > > > > different FMP protocol instance for a GUID value other than what has
> > > > > been defined for u-boot raw and u-boot FIT GUIDs.
> > > >
> > > > I do understand part of your concern a bit.
> > > > I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> > > > but we needed different GUIDs here simply because we need to determine
> > > > the format of payload, FIT format or raw binary.
> > > >
> > > > > The platform can give us the image descriptor array, and with that,
> > > > > the same FMP instance can be used for any type of image(ImageTypeId).
> > > >
> > > > "any type of image"? Really?
> > >
> > > The raw FMP instance can certainly handle any type of binary payloads
> > > right. There is no restriction on what type of payload it is as long
> > > as it is all going as a single entity to a given dfu partition.
> > >
> > > > >
> > > > > >
> > > > > >
> > > > > > > This means that unless the --guid
> > > > > > > value passed to the capsule generation is either of u-boot FIT or
> > > > > > > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > > > > > > Why do we need that restriction. It should be possible to use the raw
> > > > > > > FMP protocol for any other type of image types as well.
> > > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > > > > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > > > > > > used to identify the firmware component targeted for the update. If
> > > > > > > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > > > > > > the same, why have this field in the first place for individual
> > > > > > > > > images.
> > > > > > > >
> > > > > > > > As I said, ImageIndex is for that purpose.
> > > > > > >
> > > > > > > Yes, that is one possible way in the scenario where the ImageIndex is
> > > > > > > determined at the capsule generation time. But, for the A/B update
> > > > > > > scenario, we do not know the ImageIndex at build time
> > > > > >
> > > > > > "Build time" of what?
> > > > >
> > > > > Of the capsule.
> > > > >
> > > > > > I think that users should know how "dfu_alt_info" is defined
> > > > > > (in other words, where the firmware be located on the target system)
> > > > > > when capsule files are created.
> > > > >
> > > > > That is true for a non A/B scenario. And that is how it works in the
> > > > > non A/B updates case. But for A/B updates, since the determination of
> > > > > the "location" where the firmware image has to be written will be done
> > > > > only at runtime, we cannot use the --index to differentiate.
> > > >
> > > > Yes, we can :)
> > >
> > > You know what I mean -- if we could use the same logic, I would not
> > > have added all that code :)
> > >
> > > >
> > > > First of all, my essential assumption in either FIT or RAW FMP driver
> > > > is that U-Boot has (somehow conceptually) single firmware blob represented
> > > > by DFU or dfu_alt_info. As I said, each object or location in
> > > > dfu_alt_info can be further identified by index or "UpdateImageIndex".
> > > >
> > > > Let's assume that we have two locations of firmware, fw1 and fw2, and
> > > > that we have two bank A and B.
> > > > Then we will define dfu_alt_info as follows:
> > > >   <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> > > >   |<---      1st set               --->|<---       2nd set               --->|
> > > >
> > > > When you want to update bank A, we can use the first set of dfu_alt_info,
> > > > and use the second set of dfu_alt_info for bank B.
> > > > At runtime, you should know which bank you're working on, and therefore
> > > > you should know the exact physical location from dfu_alt_info.
> > > >
> > > > Please note that you don't have to change the syntax of dfu_alt_info
> > > > at all. Simply offset the location with 0 for bank A and with 2 for bank B.
> >
> > I'll try digging a bit more, but I think the current approach is not
> > working as it was intended wrt to the EFI spec.  My reading of the spec
> > and specifically section 23.3.2 is that a Capsule consists of an
> > EFI capsule header and a payload.  The payload now has an
> > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
> > firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
> >
> > An FMP implementation should read the  UpdateImageTypeId's used to identify
> > the image you are updating and from that derive the UpdateImageIndex
> > which SetImage will use. That would give you the ability to update the
> > all the firmware components with a single capsule.
> >
> > Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
> > those should be reflected on the ESRT tables from the OS
> 
> That would depend on the values populated in the
> EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
> image descriptor structure has an ImageTypeId field. The value of
> ImageTypeId is what will be reflected in the ESRT table.
> 
> In the current implementation, all the images in the ESRT table will
> show the same ImageTypeId value, either
> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.

Yea I was mostly asking wrt to A/B updates.  Would the correct UUID be
shown in the ESRT instead of EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID? 

> 
> The UpdateImageTypeId value from the capsule is used to compare with
> the ImageTypeId values returned by the GetImageInfo function to check
> if the given FMP protocol can be used for the update.
> 
> -sughosh
> 
[...]


Regards
/Ilias

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-17  8:22                       ` Ilias Apalodimas
@ 2022-02-17 10:10                         ` Sughosh Ganu
  2022-02-26  6:54                           ` Heinrich Schuchardt
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-17 10:10 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: AKASHI Takahiro, u-boot, Heinrich Schuchardt, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Alexander Graf, Simon Glass,
	Bin Meng, Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

On Thu, 17 Feb 2022 at 13:52, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> > > > > >
>
> [...]
>
> > > > > > Yes, we can use --index when we know the index value corresponding to
> > > > > > the firmware image that we need to update. But like I mentioned in my
> > > > > > earlier reply, for A/B updates, we do not know what the index value is
> > > > > > going to be. That is going to be determined at runtime.
> > > > >
> > > > > I don't think so. See below for alternative approach.
> > > > >
> > > > > > Also, the point I was making is that we can have a capsule which is
> > > > > > consumed by an FMP protocol which has more than one image, and those
> > > > > > images have different ImageTypeId/UpdateImageTypeId.
> > > > >
> > > > > Yes, but it is a design choice in my first implementation.
> > > > > I didn't think that we need to "have a capsule which is consumed
> > > > > by an FMP protocol which has more than one image" as long as we
> > > > > use DFU framework (and FIT as standard format of aggregation on U-Boot).
> > > >
> > > > But this design can be extended without any hassle, and more
> > > > importantly without any regression, no? What kind of a problem does it
> > > > create if the FMP can handle more than one image type.
> > > >
> > > > Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
> > > > header for all images to be managed by the FMP protocol which has
> > > > multiple images with different UpdateImageTypeId.
> > > >
> > > > >
> > > > > > >
> > > > > > > > Please check the
> > > > > > > > GenerateCapsule script in EDK2. In case of a multi payload based
> > > > > > > > capsule, individual parameters like the UpdateImageTypeId are passed
> > > > > > > > through the json file, where each of the UpdateImageTypeId has a
> > > > > > > > different value per payload.
> > > > > > > >
> > > > > > > > >
> > > > > > > > > > > 2) Each firmware object handled by a given FMP driver can further be
> > > > > > > > > > >    identified by ImageIndex.
> > > > > > > > > > >
> > > > > > > > > > > My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > > > > > > > > > > (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > > > > > > > > > > a parameter.
> > > > > > > > > > >
> > > > > > > > > > > Using ImageTypeId as an identifier is simply wrong in my opinion and
> > > > > > > > > > > doesn't meet the UEFI specification.
> > > > > > > > > >
> > > > > > > > > > So, as per what you are stating, all payloads under a given
> > > > > > > > > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > > > > > > > > > ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > > > > > > > > > the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > > > > > > > > > values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > > > > > > > > > with the ImageTypeId retrieved from the image descriptor would simply
> > > > > > > > > > fail.
> > > > > > > > >
> > > > > > > > > I don't follow your point.
> > > > > > > > > Please elaborate a bit more.
> > > > > > > >
> > > > > > > > The current implementation of GetImageInfo, passes either of
> > > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > > > > > > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > > > > > > > descriptor array. So, in case the capsule is generated with a '--guid'
> > > > > > > > value which is different from these two values, the check in
> > > > > > > > efi_fmp_find on line 204 will fail.
> > > > > > >
> > > > > > > That is an expected behavior, isn't it?
> > > > > >
> > > > > > Yes it is. Do not contest that.
> > > > > >
> > > > > > > If you want to use a different FMP driver (with another GUID),
> > > > > > > you naturally need to add your own FMP driver.
> > > > > >
> > > > > > This is where I differ. We can use the same FMP protocol instance for
> > > > > > any type of ImageTypeId. I do not see why we need to define a
> > > > > > different FMP protocol instance for a GUID value other than what has
> > > > > > been defined for u-boot raw and u-boot FIT GUIDs.
> > > > >
> > > > > I do understand part of your concern a bit.
> > > > > I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> > > > > but we needed different GUIDs here simply because we need to determine
> > > > > the format of payload, FIT format or raw binary.
> > > > >
> > > > > > The platform can give us the image descriptor array, and with that,
> > > > > > the same FMP instance can be used for any type of image(ImageTypeId).
> > > > >
> > > > > "any type of image"? Really?
> > > >
> > > > The raw FMP instance can certainly handle any type of binary payloads
> > > > right. There is no restriction on what type of payload it is as long
> > > > as it is all going as a single entity to a given dfu partition.
> > > >
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > This means that unless the --guid
> > > > > > > > value passed to the capsule generation is either of u-boot FIT or
> > > > > > > > u-boot raw, the current FMP protocol for raw devices cannot be used.
> > > > > > > > Why do we need that restriction. It should be possible to use the raw
> > > > > > > > FMP protocol for any other type of image types as well.
> > > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > > > I think this interpretation of the UEFI spec is incorrect, since the
> > > > > > > > > > spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > > > > > > > > > used to identify the firmware component targeted for the update. If
> > > > > > > > > > all values in the image descriptor array and the UpdateImageTypeId are
> > > > > > > > > > the same, why have this field in the first place for individual
> > > > > > > > > > images.
> > > > > > > > >
> > > > > > > > > As I said, ImageIndex is for that purpose.
> > > > > > > >
> > > > > > > > Yes, that is one possible way in the scenario where the ImageIndex is
> > > > > > > > determined at the capsule generation time. But, for the A/B update
> > > > > > > > scenario, we do not know the ImageIndex at build time
> > > > > > >
> > > > > > > "Build time" of what?
> > > > > >
> > > > > > Of the capsule.
> > > > > >
> > > > > > > I think that users should know how "dfu_alt_info" is defined
> > > > > > > (in other words, where the firmware be located on the target system)
> > > > > > > when capsule files are created.
> > > > > >
> > > > > > That is true for a non A/B scenario. And that is how it works in the
> > > > > > non A/B updates case. But for A/B updates, since the determination of
> > > > > > the "location" where the firmware image has to be written will be done
> > > > > > only at runtime, we cannot use the --index to differentiate.
> > > > >
> > > > > Yes, we can :)
> > > >
> > > > You know what I mean -- if we could use the same logic, I would not
> > > > have added all that code :)
> > > >
> > > > >
> > > > > First of all, my essential assumption in either FIT or RAW FMP driver
> > > > > is that U-Boot has (somehow conceptually) single firmware blob represented
> > > > > by DFU or dfu_alt_info. As I said, each object or location in
> > > > > dfu_alt_info can be further identified by index or "UpdateImageIndex".
> > > > >
> > > > > Let's assume that we have two locations of firmware, fw1 and fw2, and
> > > > > that we have two bank A and B.
> > > > > Then we will define dfu_alt_info as follows:
> > > > >   <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> > > > >   |<---      1st set               --->|<---       2nd set               --->|
> > > > >
> > > > > When you want to update bank A, we can use the first set of dfu_alt_info,
> > > > > and use the second set of dfu_alt_info for bank B.
> > > > > At runtime, you should know which bank you're working on, and therefore
> > > > > you should know the exact physical location from dfu_alt_info.
> > > > >
> > > > > Please note that you don't have to change the syntax of dfu_alt_info
> > > > > at all. Simply offset the location with 0 for bank A and with 2 for bank B.
> > >
> > > I'll try digging a bit more, but I think the current approach is not
> > > working as it was intended wrt to the EFI spec.  My reading of the spec
> > > and specifically section 23.3.2 is that a Capsule consists of an
> > > EFI capsule header and a payload.  The payload now has an
> > > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
> > > firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
> > >
> > > An FMP implementation should read the  UpdateImageTypeId's used to identify
> > > the image you are updating and from that derive the UpdateImageIndex
> > > which SetImage will use. That would give you the ability to update the
> > > all the firmware components with a single capsule.
> > >
> > > Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
> > > those should be reflected on the ESRT tables from the OS
> >
> > That would depend on the values populated in the
> > EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
> > image descriptor structure has an ImageTypeId field. The value of
> > ImageTypeId is what will be reflected in the ESRT table.
> >
> > In the current implementation, all the images in the ESRT table will
> > show the same ImageTypeId value, either
> > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.
>
> Yea I was mostly asking wrt to A/B updates.  Would the correct UUID be
> shown in the ESRT instead of EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID?

Yes, the platform would have to define the fill_image_type_guid_array
function which would populate the ImageTypeId values in the
EFI_FIRMWARE_IMAGE_DESCRIPTOR array, and the image GUID values would
then show up as part of the ESRT table.

As part of this patchset, I have added this function for the STM32MP1 DK2 board.

-sughosh

>
> >
> > The UpdateImageTypeId value from the capsule is used to compare with
> > the ImageTypeId values returned by the GetImageInfo function to check
> > if the given FMP protocol can be used for the update.
> >
> > -sughosh
> >
> [...]
>
>
> Regards
> /Ilias

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-17 10:10                         ` Sughosh Ganu
@ 2022-02-26  6:54                           ` Heinrich Schuchardt
  2022-02-26  9:54                             ` Sughosh Ganu
  0 siblings, 1 reply; 64+ messages in thread
From: Heinrich Schuchardt @ 2022-02-26  6:54 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: AKASHI Takahiro, u-boot, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere,
	Ilias Apalodimas

On 2/17/22 11:10, Sughosh Ganu wrote:
> On Thu, 17 Feb 2022 at 13:52, Ilias Apalodimas
> <ilias.apalodimas@linaro.org> wrote:
>>
>>>>>>>
>>
>> [...]
>>
>>>>>>> Yes, we can use --index when we know the index value corresponding to
>>>>>>> the firmware image that we need to update. But like I mentioned in my
>>>>>>> earlier reply, for A/B updates, we do not know what the index value is
>>>>>>> going to be. That is going to be determined at runtime.
>>>>>>
>>>>>> I don't think so. See below for alternative approach.
>>>>>>
>>>>>>> Also, the point I was making is that we can have a capsule which is
>>>>>>> consumed by an FMP protocol which has more than one image, and those
>>>>>>> images have different ImageTypeId/UpdateImageTypeId.
>>>>>>
>>>>>> Yes, but it is a design choice in my first implementation.
>>>>>> I didn't think that we need to "have a capsule which is consumed
>>>>>> by an FMP protocol which has more than one image" as long as we
>>>>>> use DFU framework (and FIT as standard format of aggregation on U-Boot).
>>>>>
>>>>> But this design can be extended without any hassle, and more
>>>>> importantly without any regression, no? What kind of a problem does it
>>>>> create if the FMP can handle more than one image type.
>>>>>
>>>>> Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
>>>>> header for all images to be managed by the FMP protocol which has
>>>>> multiple images with different UpdateImageTypeId.
>>>>>
>>>>>>
>>>>>>>>
>>>>>>>>> Please check the
>>>>>>>>> GenerateCapsule script in EDK2. In case of a multi payload based
>>>>>>>>> capsule, individual parameters like the UpdateImageTypeId are passed
>>>>>>>>> through the json file, where each of the UpdateImageTypeId has a
>>>>>>>>> different value per payload.
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>>> 2) Each firmware object handled by a given FMP driver can further be
>>>>>>>>>>>>     identified by ImageIndex.
>>>>>>>>>>>>
>>>>>>>>>>>> My implementation of efi_fmp_find() does (1) and Raw FMP driver does
>>>>>>>>>>>> (2) in efi_firmware_raw_set_image() which takes "image_index" as
>>>>>>>>>>>> a parameter.
>>>>>>>>>>>>
>>>>>>>>>>>> Using ImageTypeId as an identifier is simply wrong in my opinion and
>>>>>>>>>>>> doesn't meet the UEFI specification.
>>>>>>>>>>>
>>>>>>>>>>> So, as per what you are stating, all payloads under a given
>>>>>>>>>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
>>>>>>>>>>> ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
>>>>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
>>>>>>>>>>> the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
>>>>>>>>>>> values, > the check in efi_fmp_find to compare the UpdateImageTypeId
>>>>>>>>>>> with the ImageTypeId retrieved from the image descriptor would simply
>>>>>>>>>>> fail.
>>>>>>>>>>
>>>>>>>>>> I don't follow your point.
>>>>>>>>>> Please elaborate a bit more.
>>>>>>>>>
>>>>>>>>> The current implementation of GetImageInfo, passes either of
>>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
>>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
>>>>>>>>> descriptor array. So, in case the capsule is generated with a '--guid'
>>>>>>>>> value which is different from these two values, the check in
>>>>>>>>> efi_fmp_find on line 204 will fail.
>>>>>>>>
>>>>>>>> That is an expected behavior, isn't it?
>>>>>>>
>>>>>>> Yes it is. Do not contest that.
>>>>>>>
>>>>>>>> If you want to use a different FMP driver (with another GUID),
>>>>>>>> you naturally need to add your own FMP driver.
>>>>>>>
>>>>>>> This is where I differ. We can use the same FMP protocol instance for
>>>>>>> any type of ImageTypeId. I do not see why we need to define a
>>>>>>> different FMP protocol instance for a GUID value other than what has
>>>>>>> been defined for u-boot raw and u-boot FIT GUIDs.
>>>>>>
>>>>>> I do understand part of your concern a bit.
>>>>>> I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
>>>>>> but we needed different GUIDs here simply because we need to determine
>>>>>> the format of payload, FIT format or raw binary.
>>>>>>
>>>>>>> The platform can give us the image descriptor array, and with that,
>>>>>>> the same FMP instance can be used for any type of image(ImageTypeId).
>>>>>>
>>>>>> "any type of image"? Really?
>>>>>
>>>>> The raw FMP instance can certainly handle any type of binary payloads
>>>>> right. There is no restriction on what type of payload it is as long
>>>>> as it is all going as a single entity to a given dfu partition.
>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>> This means that unless the --guid
>>>>>>>>> value passed to the capsule generation is either of u-boot FIT or
>>>>>>>>> u-boot raw, the current FMP protocol for raw devices cannot be used.
>>>>>>>>> Why do we need that restriction. It should be possible to use the raw
>>>>>>>>> FMP protocol for any other type of image types as well.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> I think this interpretation of the UEFI spec is incorrect, since the
>>>>>>>>>>> spec states that the ImageTypeId and the UpdateImageTypeId are fields
>>>>>>>>>>> used to identify the firmware component targeted for the update. If
>>>>>>>>>>> all values in the image descriptor array and the UpdateImageTypeId are
>>>>>>>>>>> the same, why have this field in the first place for individual
>>>>>>>>>>> images.
>>>>>>>>>>
>>>>>>>>>> As I said, ImageIndex is for that purpose.
>>>>>>>>>
>>>>>>>>> Yes, that is one possible way in the scenario where the ImageIndex is
>>>>>>>>> determined at the capsule generation time. But, for the A/B update
>>>>>>>>> scenario, we do not know the ImageIndex at build time
>>>>>>>>
>>>>>>>> "Build time" of what?
>>>>>>>
>>>>>>> Of the capsule.
>>>>>>>
>>>>>>>> I think that users should know how "dfu_alt_info" is defined
>>>>>>>> (in other words, where the firmware be located on the target system)
>>>>>>>> when capsule files are created.
>>>>>>>
>>>>>>> That is true for a non A/B scenario. And that is how it works in the
>>>>>>> non A/B updates case. But for A/B updates, since the determination of
>>>>>>> the "location" where the firmware image has to be written will be done
>>>>>>> only at runtime, we cannot use the --index to differentiate.
>>>>>>
>>>>>> Yes, we can :)
>>>>>
>>>>> You know what I mean -- if we could use the same logic, I would not
>>>>> have added all that code :)
>>>>>
>>>>>>
>>>>>> First of all, my essential assumption in either FIT or RAW FMP driver
>>>>>> is that U-Boot has (somehow conceptually) single firmware blob represented
>>>>>> by DFU or dfu_alt_info. As I said, each object or location in
>>>>>> dfu_alt_info can be further identified by index or "UpdateImageIndex".
>>>>>>
>>>>>> Let's assume that we have two locations of firmware, fw1 and fw2, and
>>>>>> that we have two bank A and B.
>>>>>> Then we will define dfu_alt_info as follows:
>>>>>>    <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
>>>>>>    |<---      1st set               --->|<---       2nd set               --->|
>>>>>>
>>>>>> When you want to update bank A, we can use the first set of dfu_alt_info,
>>>>>> and use the second set of dfu_alt_info for bank B.
>>>>>> At runtime, you should know which bank you're working on, and therefore
>>>>>> you should know the exact physical location from dfu_alt_info.
>>>>>>
>>>>>> Please note that you don't have to change the syntax of dfu_alt_info
>>>>>> at all. Simply offset the location with 0 for bank A and with 2 for bank B.
>>>>
>>>> I'll try digging a bit more, but I think the current approach is not
>>>> working as it was intended wrt to the EFI spec.  My reading of the spec
>>>> and specifically section 23.3.2 is that a Capsule consists of an
>>>> EFI capsule header and a payload.  The payload now has an
>>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
>>>> firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
>>>>
>>>> An FMP implementation should read the  UpdateImageTypeId's used to identify
>>>> the image you are updating and from that derive the UpdateImageIndex
>>>> which SetImage will use. That would give you the ability to update the
>>>> all the firmware components with a single capsule.
>>>>
>>>> Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
>>>> those should be reflected on the ESRT tables from the OS
>>>
>>> That would depend on the values populated in the
>>> EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
>>> image descriptor structure has an ImageTypeId field. The value of
>>> ImageTypeId is what will be reflected in the ESRT table.
>>>
>>> In the current implementation, all the images in the ESRT table will
>>> show the same ImageTypeId value, either
>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.

This is wrong. According to the the UEFI 2.9 specification the
UpdateImageTypeId is used to "identify (the) device firmware targeted by
this update". It does not identify the format in which the firmware is
delivered.

So this needs to be fixed in the next revision of this patch series.

For each firmware part that can be updated provide a unique GUID.

Best regards

Heinrich

>>
>> Yea I was mostly asking wrt to A/B updates.  Would the correct UUID be
>> shown in the ESRT instead of EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID?
>
> Yes, the platform would have to define the fill_image_type_guid_array
> function which would populate the ImageTypeId values in the
> EFI_FIRMWARE_IMAGE_DESCRIPTOR array, and the image GUID values would
> then show up as part of the ESRT table.
>
> As part of this patchset, I have added this function for the STM32MP1 DK2 board.
>
> -sughosh
>
>>
>>>
>>> The UpdateImageTypeId value from the capsule is used to compare with
>>> the ImageTypeId values returned by the GetImageInfo function to check
>>> if the given FMP protocol can be used for the update.
>>>
>>> -sughosh
>>>
>> [...]
>>
>>
>> Regards
>> /Ilias


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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-26  6:54                           ` Heinrich Schuchardt
@ 2022-02-26  9:54                             ` Sughosh Ganu
  2022-03-08 13:13                               ` AKASHI Takahiro
  0 siblings, 1 reply; 64+ messages in thread
From: Sughosh Ganu @ 2022-02-26  9:54 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: AKASHI Takahiro, u-boot, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere,
	Ilias Apalodimas

hello Heinrich,

On Sat, 26 Feb 2022 at 12:24, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 2/17/22 11:10, Sughosh Ganu wrote:
> > On Thu, 17 Feb 2022 at 13:52, Ilias Apalodimas
> > <ilias.apalodimas@linaro.org> wrote:
> >>
> >>>>>>>
> >>
> >> [...]
> >>
> >>>>>>> Yes, we can use --index when we know the index value corresponding to
> >>>>>>> the firmware image that we need to update. But like I mentioned in my
> >>>>>>> earlier reply, for A/B updates, we do not know what the index value is
> >>>>>>> going to be. That is going to be determined at runtime.
> >>>>>>
> >>>>>> I don't think so. See below for alternative approach.
> >>>>>>
> >>>>>>> Also, the point I was making is that we can have a capsule which is
> >>>>>>> consumed by an FMP protocol which has more than one image, and those
> >>>>>>> images have different ImageTypeId/UpdateImageTypeId.
> >>>>>>
> >>>>>> Yes, but it is a design choice in my first implementation.
> >>>>>> I didn't think that we need to "have a capsule which is consumed
> >>>>>> by an FMP protocol which has more than one image" as long as we
> >>>>>> use DFU framework (and FIT as standard format of aggregation on U-Boot).
> >>>>>
> >>>>> But this design can be extended without any hassle, and more
> >>>>> importantly without any regression, no? What kind of a problem does it
> >>>>> create if the FMP can handle more than one image type.
> >>>>>
> >>>>> Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
> >>>>> header for all images to be managed by the FMP protocol which has
> >>>>> multiple images with different UpdateImageTypeId.
> >>>>>
> >>>>>>
> >>>>>>>>
> >>>>>>>>> Please check the
> >>>>>>>>> GenerateCapsule script in EDK2. In case of a multi payload based
> >>>>>>>>> capsule, individual parameters like the UpdateImageTypeId are passed
> >>>>>>>>> through the json file, where each of the UpdateImageTypeId has a
> >>>>>>>>> different value per payload.
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>>> 2) Each firmware object handled by a given FMP driver can further be
> >>>>>>>>>>>>     identified by ImageIndex.
> >>>>>>>>>>>>
> >>>>>>>>>>>> My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> >>>>>>>>>>>> (2) in efi_firmware_raw_set_image() which takes "image_index" as
> >>>>>>>>>>>> a parameter.
> >>>>>>>>>>>>
> >>>>>>>>>>>> Using ImageTypeId as an identifier is simply wrong in my opinion and
> >>>>>>>>>>>> doesn't meet the UEFI specification.
> >>>>>>>>>>>
> >>>>>>>>>>> So, as per what you are stating, all payloads under a given
> >>>>>>>>>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> >>>>>>>>>>> ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> >>>>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> >>>>>>>>>>> the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> >>>>>>>>>>> values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> >>>>>>>>>>> with the ImageTypeId retrieved from the image descriptor would simply
> >>>>>>>>>>> fail.
> >>>>>>>>>>
> >>>>>>>>>> I don't follow your point.
> >>>>>>>>>> Please elaborate a bit more.
> >>>>>>>>>
> >>>>>>>>> The current implementation of GetImageInfo, passes either of
> >>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> >>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> >>>>>>>>> descriptor array. So, in case the capsule is generated with a '--guid'
> >>>>>>>>> value which is different from these two values, the check in
> >>>>>>>>> efi_fmp_find on line 204 will fail.
> >>>>>>>>
> >>>>>>>> That is an expected behavior, isn't it?
> >>>>>>>
> >>>>>>> Yes it is. Do not contest that.
> >>>>>>>
> >>>>>>>> If you want to use a different FMP driver (with another GUID),
> >>>>>>>> you naturally need to add your own FMP driver.
> >>>>>>>
> >>>>>>> This is where I differ. We can use the same FMP protocol instance for
> >>>>>>> any type of ImageTypeId. I do not see why we need to define a
> >>>>>>> different FMP protocol instance for a GUID value other than what has
> >>>>>>> been defined for u-boot raw and u-boot FIT GUIDs.
> >>>>>>
> >>>>>> I do understand part of your concern a bit.
> >>>>>> I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> >>>>>> but we needed different GUIDs here simply because we need to determine
> >>>>>> the format of payload, FIT format or raw binary.
> >>>>>>
> >>>>>>> The platform can give us the image descriptor array, and with that,
> >>>>>>> the same FMP instance can be used for any type of image(ImageTypeId).
> >>>>>>
> >>>>>> "any type of image"? Really?
> >>>>>
> >>>>> The raw FMP instance can certainly handle any type of binary payloads
> >>>>> right. There is no restriction on what type of payload it is as long
> >>>>> as it is all going as a single entity to a given dfu partition.
> >>>>>
> >>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>> This means that unless the --guid
> >>>>>>>>> value passed to the capsule generation is either of u-boot FIT or
> >>>>>>>>> u-boot raw, the current FMP protocol for raw devices cannot be used.
> >>>>>>>>> Why do we need that restriction. It should be possible to use the raw
> >>>>>>>>> FMP protocol for any other type of image types as well.
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>>> I think this interpretation of the UEFI spec is incorrect, since the
> >>>>>>>>>>> spec states that the ImageTypeId and the UpdateImageTypeId are fields
> >>>>>>>>>>> used to identify the firmware component targeted for the update. If
> >>>>>>>>>>> all values in the image descriptor array and the UpdateImageTypeId are
> >>>>>>>>>>> the same, why have this field in the first place for individual
> >>>>>>>>>>> images.
> >>>>>>>>>>
> >>>>>>>>>> As I said, ImageIndex is for that purpose.
> >>>>>>>>>
> >>>>>>>>> Yes, that is one possible way in the scenario where the ImageIndex is
> >>>>>>>>> determined at the capsule generation time. But, for the A/B update
> >>>>>>>>> scenario, we do not know the ImageIndex at build time
> >>>>>>>>
> >>>>>>>> "Build time" of what?
> >>>>>>>
> >>>>>>> Of the capsule.
> >>>>>>>
> >>>>>>>> I think that users should know how "dfu_alt_info" is defined
> >>>>>>>> (in other words, where the firmware be located on the target system)
> >>>>>>>> when capsule files are created.
> >>>>>>>
> >>>>>>> That is true for a non A/B scenario. And that is how it works in the
> >>>>>>> non A/B updates case. But for A/B updates, since the determination of
> >>>>>>> the "location" where the firmware image has to be written will be done
> >>>>>>> only at runtime, we cannot use the --index to differentiate.
> >>>>>>
> >>>>>> Yes, we can :)
> >>>>>
> >>>>> You know what I mean -- if we could use the same logic, I would not
> >>>>> have added all that code :)
> >>>>>
> >>>>>>
> >>>>>> First of all, my essential assumption in either FIT or RAW FMP driver
> >>>>>> is that U-Boot has (somehow conceptually) single firmware blob represented
> >>>>>> by DFU or dfu_alt_info. As I said, each object or location in
> >>>>>> dfu_alt_info can be further identified by index or "UpdateImageIndex".
> >>>>>>
> >>>>>> Let's assume that we have two locations of firmware, fw1 and fw2, and
> >>>>>> that we have two bank A and B.
> >>>>>> Then we will define dfu_alt_info as follows:
> >>>>>>    <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> >>>>>>    |<---      1st set               --->|<---       2nd set               --->|
> >>>>>>
> >>>>>> When you want to update bank A, we can use the first set of dfu_alt_info,
> >>>>>> and use the second set of dfu_alt_info for bank B.
> >>>>>> At runtime, you should know which bank you're working on, and therefore
> >>>>>> you should know the exact physical location from dfu_alt_info.
> >>>>>>
> >>>>>> Please note that you don't have to change the syntax of dfu_alt_info
> >>>>>> at all. Simply offset the location with 0 for bank A and with 2 for bank B.
> >>>>
> >>>> I'll try digging a bit more, but I think the current approach is not
> >>>> working as it was intended wrt to the EFI spec.  My reading of the spec
> >>>> and specifically section 23.3.2 is that a Capsule consists of an
> >>>> EFI capsule header and a payload.  The payload now has an
> >>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
> >>>> firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
> >>>>
> >>>> An FMP implementation should read the  UpdateImageTypeId's used to identify
> >>>> the image you are updating and from that derive the UpdateImageIndex
> >>>> which SetImage will use. That would give you the ability to update the
> >>>> all the firmware components with a single capsule.
> >>>>
> >>>> Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
> >>>> those should be reflected on the ESRT tables from the OS
> >>>
> >>> That would depend on the values populated in the
> >>> EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
> >>> image descriptor structure has an ImageTypeId field. The value of
> >>> ImageTypeId is what will be reflected in the ESRT table.
> >>>
> >>> In the current implementation, all the images in the ESRT table will
> >>> show the same ImageTypeId value, either
> >>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> >>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.
>
> This is wrong. According to the the UEFI 2.9 specification the
> UpdateImageTypeId is used to "identify (the) device firmware targeted by
> this update". It does not identify the format in which the firmware is
> delivered.
>
> So this needs to be fixed in the next revision of this patch series.

This patch series is actually adding that platform function which
populates the image descriptor array with the image GUID's -- patch 6
of this series[1] actually does that for the ST DK2 platform. This
discussion was because Takahiro wanted to use the same image
GUID(u-boot raw/FIT) for all the images, and use the image index for
identifying where the image is to be written.

I guess with what you are stating, along with Ilias's opinion on this,
I will send the next version with the same approach, i.e. using a
platform function to populate the image GUIDs in the firmware image
descriptor array. With this, each firmware image will have a different
GUID which can be used to identify the image.

-sughosh

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

>
> For each firmware part that can be updated provide a unique GUID.
>
> Best regards
>
> Heinrich
>
> >>
> >> Yea I was mostly asking wrt to A/B updates.  Would the correct UUID be
> >> shown in the ESRT instead of EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID?
> >
> > Yes, the platform would have to define the fill_image_type_guid_array
> > function which would populate the ImageTypeId values in the
> > EFI_FIRMWARE_IMAGE_DESCRIPTOR array, and the image GUID values would
> > then show up as part of the ESRT table.
> >
> > As part of this patchset, I have added this function for the STM32MP1 DK2 board.
> >
> > -sughosh
> >
> >>
> >>>
> >>> The UpdateImageTypeId value from the capsule is used to compare with
> >>> the ImageTypeId values returned by the GetImageInfo function to check
> >>> if the given FMP protocol can be used for the update.
> >>>
> >>> -sughosh
> >>>
> >> [...]
> >>
> >>
> >> Regards
> >> /Ilias
>

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-02-26  9:54                             ` Sughosh Ganu
@ 2022-03-08 13:13                               ` AKASHI Takahiro
  2022-03-09  8:31                                 ` Ilias Apalodimas
  0 siblings, 1 reply; 64+ messages in thread
From: AKASHI Takahiro @ 2022-03-08 13:13 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Heinrich Schuchardt, u-boot, Masami Hiramatsu, Patrick Delaunay,
	Patrice Chotard, Alexander Graf, Simon Glass, Bin Meng,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere,
	Ilias Apalodimas

On Sat, Feb 26, 2022 at 03:24:10PM +0530, Sughosh Ganu wrote:
> hello Heinrich,
> 
> On Sat, 26 Feb 2022 at 12:24, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >
> > On 2/17/22 11:10, Sughosh Ganu wrote:
> > > On Thu, 17 Feb 2022 at 13:52, Ilias Apalodimas
> > > <ilias.apalodimas@linaro.org> wrote:
> > >>
> > >>>>>>>
> > >>
> > >> [...]
> > >>
> > >>>>>>> Yes, we can use --index when we know the index value corresponding to
> > >>>>>>> the firmware image that we need to update. But like I mentioned in my
> > >>>>>>> earlier reply, for A/B updates, we do not know what the index value is
> > >>>>>>> going to be. That is going to be determined at runtime.
> > >>>>>>
> > >>>>>> I don't think so. See below for alternative approach.
> > >>>>>>
> > >>>>>>> Also, the point I was making is that we can have a capsule which is
> > >>>>>>> consumed by an FMP protocol which has more than one image, and those
> > >>>>>>> images have different ImageTypeId/UpdateImageTypeId.
> > >>>>>>
> > >>>>>> Yes, but it is a design choice in my first implementation.
> > >>>>>> I didn't think that we need to "have a capsule which is consumed
> > >>>>>> by an FMP protocol which has more than one image" as long as we
> > >>>>>> use DFU framework (and FIT as standard format of aggregation on U-Boot).
> > >>>>>
> > >>>>> But this design can be extended without any hassle, and more
> > >>>>> importantly without any regression, no? What kind of a problem does it
> > >>>>> create if the FMP can handle more than one image type.
> > >>>>>
> > >>>>> Even as per the UEFI spec, we have the EFI_FIRMWARE_MANAGEMENT_CAPSULE
> > >>>>> header for all images to be managed by the FMP protocol which has
> > >>>>> multiple images with different UpdateImageTypeId.
> > >>>>>
> > >>>>>>
> > >>>>>>>>
> > >>>>>>>>> Please check the
> > >>>>>>>>> GenerateCapsule script in EDK2. In case of a multi payload based
> > >>>>>>>>> capsule, individual parameters like the UpdateImageTypeId are passed
> > >>>>>>>>> through the json file, where each of the UpdateImageTypeId has a
> > >>>>>>>>> different value per payload.
> > >>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>>>> 2) Each firmware object handled by a given FMP driver can further be
> > >>>>>>>>>>>>     identified by ImageIndex.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> My implementation of efi_fmp_find() does (1) and Raw FMP driver does
> > >>>>>>>>>>>> (2) in efi_firmware_raw_set_image() which takes "image_index" as
> > >>>>>>>>>>>> a parameter.
> > >>>>>>>>>>>>
> > >>>>>>>>>>>> Using ImageTypeId as an identifier is simply wrong in my opinion and
> > >>>>>>>>>>>> doesn't meet the UEFI specification.
> > >>>>>>>>>>>
> > >>>>>>>>>>> So, as per what you are stating, all payloads under a given
> > >>>>>>>>>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER should have the same
> > >>>>>>>>>>> ImageTypeId, either EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > >>>>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID. Same applies for all images in
> > >>>>>>>>>>> the EFI_FIRMWARE_IMAGE_DESCRIPTOR. Because, without one of the two
> > >>>>>>>>>>> values, > the check in efi_fmp_find to compare the UpdateImageTypeId
> > >>>>>>>>>>> with the ImageTypeId retrieved from the image descriptor would simply
> > >>>>>>>>>>> fail.
> > >>>>>>>>>>
> > >>>>>>>>>> I don't follow your point.
> > >>>>>>>>>> Please elaborate a bit more.
> > >>>>>>>>>
> > >>>>>>>>> The current implementation of GetImageInfo, passes either of
> > >>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > >>>>>>>>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID for all the images of the image
> > >>>>>>>>> descriptor array. So, in case the capsule is generated with a '--guid'
> > >>>>>>>>> value which is different from these two values, the check in
> > >>>>>>>>> efi_fmp_find on line 204 will fail.
> > >>>>>>>>
> > >>>>>>>> That is an expected behavior, isn't it?
> > >>>>>>>
> > >>>>>>> Yes it is. Do not contest that.
> > >>>>>>>
> > >>>>>>>> If you want to use a different FMP driver (with another GUID),
> > >>>>>>>> you naturally need to add your own FMP driver.
> > >>>>>>>
> > >>>>>>> This is where I differ. We can use the same FMP protocol instance for
> > >>>>>>> any type of ImageTypeId. I do not see why we need to define a
> > >>>>>>> different FMP protocol instance for a GUID value other than what has
> > >>>>>>> been defined for u-boot raw and u-boot FIT GUIDs.
> > >>>>>>
> > >>>>>> I do understand part of your concern a bit.
> > >>>>>> I thought of using the same ImageType GUID, say IMAGE_TYPE_DFU_GUID, at first
> > >>>>>> but we needed different GUIDs here simply because we need to determine
> > >>>>>> the format of payload, FIT format or raw binary.
> > >>>>>>
> > >>>>>>> The platform can give us the image descriptor array, and with that,
> > >>>>>>> the same FMP instance can be used for any type of image(ImageTypeId).
> > >>>>>>
> > >>>>>> "any type of image"? Really?
> > >>>>>
> > >>>>> The raw FMP instance can certainly handle any type of binary payloads
> > >>>>> right. There is no restriction on what type of payload it is as long
> > >>>>> as it is all going as a single entity to a given dfu partition.
> > >>>>>
> > >>>>>>>
> > >>>>>>>>
> > >>>>>>>>
> > >>>>>>>>> This means that unless the --guid
> > >>>>>>>>> value passed to the capsule generation is either of u-boot FIT or
> > >>>>>>>>> u-boot raw, the current FMP protocol for raw devices cannot be used.
> > >>>>>>>>> Why do we need that restriction. It should be possible to use the raw
> > >>>>>>>>> FMP protocol for any other type of image types as well.
> > >>>>>>>>>
> > >>>>>>>>>
> > >>>>>>>>>>
> > >>>>>>>>>>> I think this interpretation of the UEFI spec is incorrect, since the
> > >>>>>>>>>>> spec states that the ImageTypeId and the UpdateImageTypeId are fields
> > >>>>>>>>>>> used to identify the firmware component targeted for the update. If
> > >>>>>>>>>>> all values in the image descriptor array and the UpdateImageTypeId are
> > >>>>>>>>>>> the same, why have this field in the first place for individual
> > >>>>>>>>>>> images.
> > >>>>>>>>>>
> > >>>>>>>>>> As I said, ImageIndex is for that purpose.
> > >>>>>>>>>
> > >>>>>>>>> Yes, that is one possible way in the scenario where the ImageIndex is
> > >>>>>>>>> determined at the capsule generation time. But, for the A/B update
> > >>>>>>>>> scenario, we do not know the ImageIndex at build time
> > >>>>>>>>
> > >>>>>>>> "Build time" of what?
> > >>>>>>>
> > >>>>>>> Of the capsule.
> > >>>>>>>
> > >>>>>>>> I think that users should know how "dfu_alt_info" is defined
> > >>>>>>>> (in other words, where the firmware be located on the target system)
> > >>>>>>>> when capsule files are created.
> > >>>>>>>
> > >>>>>>> That is true for a non A/B scenario. And that is how it works in the
> > >>>>>>> non A/B updates case. But for A/B updates, since the determination of
> > >>>>>>> the "location" where the firmware image has to be written will be done
> > >>>>>>> only at runtime, we cannot use the --index to differentiate.
> > >>>>>>
> > >>>>>> Yes, we can :)
> > >>>>>
> > >>>>> You know what I mean -- if we could use the same logic, I would not
> > >>>>> have added all that code :)
> > >>>>>
> > >>>>>>
> > >>>>>> First of all, my essential assumption in either FIT or RAW FMP driver
> > >>>>>> is that U-Boot has (somehow conceptually) single firmware blob represented
> > >>>>>> by DFU or dfu_alt_info. As I said, each object or location in
> > >>>>>> dfu_alt_info can be further identified by index or "UpdateImageIndex".
> > >>>>>>
> > >>>>>> Let's assume that we have two locations of firmware, fw1 and fw2, and
> > >>>>>> that we have two bank A and B.
> > >>>>>> Then we will define dfu_alt_info as follows:
> > >>>>>>    <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> > >>>>>>    |<---      1st set               --->|<---       2nd set               --->|
> > >>>>>>
> > >>>>>> When you want to update bank A, we can use the first set of dfu_alt_info,
> > >>>>>> and use the second set of dfu_alt_info for bank B.
> > >>>>>> At runtime, you should know which bank you're working on, and therefore
> > >>>>>> you should know the exact physical location from dfu_alt_info.
> > >>>>>>
> > >>>>>> Please note that you don't have to change the syntax of dfu_alt_info
> > >>>>>> at all. Simply offset the location with 0 for bank A and with 2 for bank B.
> > >>>>
> > >>>> I'll try digging a bit more, but I think the current approach is not
> > >>>> working as it was intended wrt to the EFI spec.  My reading of the spec
> > >>>> and specifically section 23.3.2 is that a Capsule consists of an
> > >>>> EFI capsule header and a payload.  The payload now has an
> > >>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
> > >>>> firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
> > >>>>
> > >>>> An FMP implementation should read the  UpdateImageTypeId's used to identify
> > >>>> the image you are updating and from that derive the UpdateImageIndex
> > >>>> which SetImage will use. That would give you the ability to update the
> > >>>> all the firmware components with a single capsule.
> > >>>>
> > >>>> Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
> > >>>> those should be reflected on the ESRT tables from the OS
> > >>>
> > >>> That would depend on the values populated in the
> > >>> EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
> > >>> image descriptor structure has an ImageTypeId field. The value of
> > >>> ImageTypeId is what will be reflected in the ESRT table.
> > >>>
> > >>> In the current implementation, all the images in the ESRT table will
> > >>> show the same ImageTypeId value, either
> > >>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > >>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.
> >
> > This is wrong. According to the the UEFI 2.9 specification the
> > UpdateImageTypeId is used to "identify (the) device firmware targeted by
> > this update". It does not identify the format in which the firmware is
> > delivered.
> >
> > So this needs to be fixed in the next revision of this patch series.
> 
> This patch series is actually adding that platform function which
> populates the image descriptor array with the image GUID's -- patch 6
> of this series[1] actually does that for the ST DK2 platform. This
> discussion was because Takahiro wanted to use the same image
> GUID(u-boot raw/FIT) for all the images, and use the image index for
> identifying where the image is to be written.

The discussion depends on what the *firmware* means.
With my FMP drivers (either FIT or raw), I intended a *set of firmware*
managed with a *single* "dfu_alt_info", which may include various *images*
for different target *components* as the original DFU framework does.

-Takahiro Akashi


> I guess with what you are stating, along with Ilias's opinion on this,
> I will send the next version with the same approach, i.e. using a
> platform function to populate the image GUIDs in the firmware image
> descriptor array. With this, each firmware image will have a different
> GUID which can be used to identify the image.
> 
> -sughosh
> 
> [1] - https://lists.denx.de/pipermail/u-boot/2022-February/474434.html
> 
> >
> > For each firmware part that can be updated provide a unique GUID.
> >
> > Best regards
> >
> > Heinrich
> >
> > >>
> > >> Yea I was mostly asking wrt to A/B updates.  Would the correct UUID be
> > >> shown in the ESRT instead of EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID?
> > >
> > > Yes, the platform would have to define the fill_image_type_guid_array
> > > function which would populate the ImageTypeId values in the
> > > EFI_FIRMWARE_IMAGE_DESCRIPTOR array, and the image GUID values would
> > > then show up as part of the ESRT table.
> > >
> > > As part of this patchset, I have added this function for the STM32MP1 DK2 board.
> > >
> > > -sughosh
> > >
> > >>
> > >>>
> > >>> The UpdateImageTypeId value from the capsule is used to compare with
> > >>> the ImageTypeId values returned by the GetImageInfo function to check
> > >>> if the given FMP protocol can be used for the update.
> > >>>
> > >>> -sughosh
> > >>>
> > >> [...]
> > >>
> > >>
> > >> Regards
> > >> /Ilias
> >

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

* Re: [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-03-08 13:13                               ` AKASHI Takahiro
@ 2022-03-09  8:31                                 ` Ilias Apalodimas
  0 siblings, 0 replies; 64+ messages in thread
From: Ilias Apalodimas @ 2022-03-09  8:31 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, Heinrich Schuchardt, u-boot,
	Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, Simon Glass, Bin Meng, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Ilias Apalodimas

Akashi-san

[...]
> > > >>>>>>>> I think that users should know how "dfu_alt_info" is defined
> > > >>>>>>>> (in other words, where the firmware be located on the target system)
> > > >>>>>>>> when capsule files are created.
> > > >>>>>>>
> > > >>>>>>> That is true for a non A/B scenario. And that is how it works in the
> > > >>>>>>> non A/B updates case. But for A/B updates, since the determination of
> > > >>>>>>> the "location" where the firmware image has to be written will be done
> > > >>>>>>> only at runtime, we cannot use the --index to differentiate.
> > > >>>>>>
> > > >>>>>> Yes, we can :)
> > > >>>>>
> > > >>>>> You know what I mean -- if we could use the same logic, I would not
> > > >>>>> have added all that code :)
> > > >>>>>
> > > >>>>>>
> > > >>>>>> First of all, my essential assumption in either FIT or RAW FMP driver
> > > >>>>>> is that U-Boot has (somehow conceptually) single firmware blob represented
> > > >>>>>> by DFU or dfu_alt_info. As I said, each object or location in
> > > >>>>>> dfu_alt_info can be further identified by index or "UpdateImageIndex".
> > > >>>>>>
> > > >>>>>> Let's assume that we have two locations of firmware, fw1 and fw2, and
> > > >>>>>> that we have two bank A and B.
> > > >>>>>> Then we will define dfu_alt_info as follows:
> > > >>>>>>    <loc of fw1 for A>;<loc of fw2 for A>;<loc of fw1 for B>;<loc of fw2 for B>;
> > > >>>>>>    |<---      1st set               --->|<---       2nd set               --->|
> > > >>>>>>
> > > >>>>>> When you want to update bank A, we can use the first set of dfu_alt_info,
> > > >>>>>> and use the second set of dfu_alt_info for bank B.
> > > >>>>>> At runtime, you should know which bank you're working on, and therefore
> > > >>>>>> you should know the exact physical location from dfu_alt_info.
> > > >>>>>>
> > > >>>>>> Please note that you don't have to change the syntax of dfu_alt_info
> > > >>>>>> at all. Simply offset the location with 0 for bank A and with 2 for bank B.
> > > >>>>
> > > >>>> I'll try digging a bit more, but I think the current approach is not
> > > >>>> working as it was intended wrt to the EFI spec.  My reading of the spec
> > > >>>> and specifically section 23.3.2 is that a Capsule consists of an
> > > >>>> EFI capsule header and a payload.  The payload now has an
> > > >>>> EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER which in it's turn can host multiple
> > > >>>> firmware images of different type described in EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
> > > >>>>
> > > >>>> An FMP implementation should read the  UpdateImageTypeId's used to identify
> > > >>>> the image you are updating and from that derive the UpdateImageIndex
> > > >>>> which SetImage will use. That would give you the ability to update the
> > > >>>> all the firmware components with a single capsule.
> > > >>>>
> > > >>>> Sughosh what about the ESRT table generation?  If you use different UpdateImageTypeId
> > > >>>> those should be reflected on the ESRT tables from the OS
> > > >>>
> > > >>> That would depend on the values populated in the
> > > >>> EFI_FIRMWARE_IMAGE_DESCRIPTOR array by the GetImageInfo function. The
> > > >>> image descriptor structure has an ImageTypeId field. The value of
> > > >>> ImageTypeId is what will be reflected in the ESRT table.
> > > >>>
> > > >>> In the current implementation, all the images in the ESRT table will
> > > >>> show the same ImageTypeId value, either
> > > >>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID or
> > > >>> EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID.
> > >
> > > This is wrong. According to the the UEFI 2.9 specification the
> > > UpdateImageTypeId is used to "identify (the) device firmware targeted by
> > > this update". It does not identify the format in which the firmware is
> > > delivered.
> > >
> > > So this needs to be fixed in the next revision of this patch series.
> >
> > This patch series is actually adding that platform function which
> > populates the image descriptor array with the image GUID's -- patch 6
> > of this series[1] actually does that for the ST DK2 platform. This
> > discussion was because Takahiro wanted to use the same image
> > GUID(u-boot raw/FIT) for all the images, and use the image index for
> > identifying where the image is to be written.
>
> The discussion depends on what the *firmware* means.
> With my FMP drivers (either FIT or raw), I intended a *set of firmware*
> managed with a *single* "dfu_alt_info", which may include various *images*
> for different target *components* as the original DFU framework does.

I still think we should fix that.  The current code is working, but
it's not what the EFI spec describes.  I think we should do it the
other way around.

IOW the board defines the UUID's for the firmware partitions it needs
to update.  The FMP driver should then populate those properly in an
ESRT table and also generate an appropriate dfu_alt_info (or similar)
on the fly.

Regards
/Ilias
>
> -Takahiro Akashi
>
>
> > I guess with what you are stating, along with Ilias's opinion on this,
> > I will send the next version with the same approach, i.e. using a
> > platform function to populate the image GUIDs in the firmware image
> > descriptor array. With this, each firmware image will have a different
> > GUID which can be used to identify the image.
> >
> > -sughosh
> >
> > [1] - https://lists.denx.de/pipermail/u-boot/2022-February/474434.html
> >
> > >
> > > For each firmware part that can be updated provide a unique GUID.
> > >
> > > Best regards
> > >
> > > Heinrich
> > >
> > > >>
> > > >> Yea I was mostly asking wrt to A/B updates.  Would the correct UUID be
> > > >> shown in the ESRT instead of EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID?
> > > >
> > > > Yes, the platform would have to define the fill_image_type_guid_array
> > > > function which would populate the ImageTypeId values in the
> > > > EFI_FIRMWARE_IMAGE_DESCRIPTOR array, and the image GUID values would
> > > > then show up as part of the ESRT table.
> > > >
> > > > As part of this patchset, I have added this function for the STM32MP1 DK2 board.
> > > >
> > > > -sughosh
> > > >
> > > >>
> > > >>>
> > > >>> The UpdateImageTypeId value from the capsule is used to compare with
> > > >>> the ImageTypeId values returned by the GetImageInfo function to check
> > > >>> if the given FMP protocol can be used for the update.
> > > >>>
> > > >>> -sughosh
> > > >>>
> > > >> [...]
> > > >>
> > > >>
> > > >> Regards
> > > >> /Ilias
> > >

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

end of thread, other threads:[~2022-03-09  8:32 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-07 18:19 [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 01/11] FWU: Add FWU metadata structure and driver for accessing metadata Sughosh Ganu
2022-02-08  9:33   ` Masami Hiramatsu
2022-02-08 10:24     ` Sughosh Ganu
2022-02-08 11:23       ` Masami Hiramatsu
2022-02-08 10:56   ` Michal Simek
2022-02-08 11:35     ` Sughosh Ganu
2022-02-08 11:39       ` Michal Simek
2022-02-08 13:36       ` Masami Hiramatsu
2022-02-08 13:45         ` Michal Simek
2022-02-08 14:14           ` Masami Hiramatsu
2022-02-08 14:27             ` Michal Simek
2022-02-08 23:39               ` Masami Hiramatsu
2022-02-09  7:21                 ` Michal Simek
2022-02-08 11:31   ` Michal Simek
2022-02-08 11:38     ` Sughosh Ganu
2022-02-08 11:44       ` Michal Simek
2022-02-08 11:54         ` Sughosh Ganu
2022-02-08 11:59           ` Michal Simek
2022-02-08 12:07             ` Sughosh Ganu
2022-02-08 12:14               ` Michal Simek
2022-02-08 12:49                 ` Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 02/11] FWU: Add FWU metadata access driver for GPT partitioned block devices Sughosh Ganu
2022-02-09  4:56   ` Masami Hiramatsu
2022-02-09  9:03     ` Sughosh Ganu
2022-02-09 11:47       ` Masami Hiramatsu
2022-02-09 18:40         ` Sughosh Ganu
2022-02-10  1:43           ` Masami Hiramatsu
2022-02-10  3:14             ` Masami Hiramatsu
2022-02-10 12:25               ` Sughosh Ganu
2022-02-11  1:58                 ` Masami Hiramatsu
2022-02-07 18:19 ` [PATCH v4 03/11] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 04/11] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 05/11] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
2022-02-10  2:48   ` AKASHI Takahiro
2022-02-10  7:18     ` Sughosh Ganu
2022-02-10  7:58       ` AKASHI Takahiro
2022-02-10 10:10         ` Sughosh Ganu
2022-02-14  3:24           ` AKASHI Takahiro
2022-02-14  5:42             ` Sughosh Ganu
2022-02-15  1:51               ` AKASHI Takahiro
2022-02-15  6:38                 ` Sughosh Ganu
2022-02-15 14:40                   ` Ilias Apalodimas
2022-02-15 17:19                     ` Sughosh Ganu
2022-02-17  8:22                       ` Ilias Apalodimas
2022-02-17 10:10                         ` Sughosh Ganu
2022-02-26  6:54                           ` Heinrich Schuchardt
2022-02-26  9:54                             ` Sughosh Ganu
2022-03-08 13:13                               ` AKASHI Takahiro
2022-03-09  8:31                                 ` Ilias Apalodimas
2022-02-07 18:19 ` [PATCH v4 06/11] stm32mp1: Populate ImageTypeId values in EFI_FIRMWARE_IMAGE_DESCRIPTOR array Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 07/11] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
2022-02-08 10:53   ` Michal Simek
2022-02-11 10:46     ` Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 08/11] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
2022-02-07 18:19 ` [PATCH v4 09/11] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
2022-02-07 18:20 ` [PATCH v4 10/11] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
2022-02-09  3:05   ` AKASHI Takahiro
2022-02-10  1:27     ` AKASHI Takahiro
2022-02-11 13:27       ` Sughosh Ganu
2022-02-11 13:25     ` Sughosh Ganu
2022-02-07 18:20 ` [PATCH v4 11/11] FWU: doc: Add documentation for the FWU feature Sughosh Ganu
2022-02-08 11:05 ` [PATCH v4 00/11] FWU: Add support for FWU Multi Bank Update feature Michal Simek
2022-02-08 12:09   ` Sughosh Ganu

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.