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


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
are under review currently[3].

These patches are based on top of the series from Takahiro to add
Authentication support to mkeficapsule utility[4]

[1] - https://developer.arm.com/documentation/den0118/a
[2] - https://staging-git.codelinaro.org/linaro/firmware-dual-banked-updates/test
[3] - https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/12566
[4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549

Changes since V2:
* Use uint*_t types in fwu_mdata.h since the file is to be reused in
  other projects
* Keep only the FWU metadata structures in fwu_mdata.h
* Move all other function and macro declarations in fwu.h
* Keep common implementations of fwu_update_active_index and
  fwu_revert_boot_index in fwu_mdata.c
* Add a update_mdata function pointer in the fwu_mdata_ops structure
* Move the function definition of fwu_verify_mdata to fwu_mdata.c to
  facilitate reuse
* Remove the block device specific desc->devnum parameter for the
  fwu_plat_get_alt_num function call
* Change the implementation of fwu_plat_get_alt_num to get the devnum
  in the function before calling gpt_plat_get_alt_num
* Add logic to delete the TrialStateCtr variable if system is not in
  Trial State
* Add logic to check if bit 15(OS Acceptance) of the Flags member in
  the capsule header is set
* Add logic to set the accept bit of all images from a capsule if the
  OS Acceptance bit in the capsule header is not set
* Include the log.h and stdio.h header files

Sughosh Ganu (9):
  FWU: Add FWU metadata structure and functions for accessing metadata
  FWU: Add FWU metadata access functions 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
  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

 board/st/stm32mp1/stm32mp1.c        | 183 ++++++++++
 cmd/Kconfig                         |   7 +
 cmd/Makefile                        |   1 +
 cmd/fwu_mdata.c                     |  67 ++++
 common/board_r.c                    |   6 +
 include/fwu.h                       |  81 +++++
 include/fwu_mdata.h                 |  69 ++++
 lib/Kconfig                         |   6 +
 lib/Makefile                        |   1 +
 lib/efi_loader/efi_capsule.c        | 233 ++++++++++++-
 lib/efi_loader/efi_firmware.c       |  90 ++++-
 lib/efi_loader/efi_setup.c          |   3 +-
 lib/fwu_updates/Kconfig             |  31 ++
 lib/fwu_updates/Makefile            |  11 +
 lib/fwu_updates/fwu.c               | 198 +++++++++++
 lib/fwu_updates/fwu_mdata.c         | 358 +++++++++++++++++++
 lib/fwu_updates/fwu_mdata_gpt_blk.c | 521 ++++++++++++++++++++++++++++
 tools/eficapsule.h                  |   8 +
 tools/mkeficapsule.c                | 102 +++++-
 19 files changed, 1955 insertions(+), 21 deletions(-)
 create mode 100644 cmd/fwu_mdata.c
 create mode 100644 include/fwu.h
 create mode 100644 include/fwu_mdata.h
 create mode 100644 lib/fwu_updates/Kconfig
 create mode 100644 lib/fwu_updates/Makefile
 create mode 100644 lib/fwu_updates/fwu.c
 create mode 100644 lib/fwu_updates/fwu_mdata.c
 create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c

-- 
2.17.1



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

* [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20  5:53   ` Masami Hiramatsu
                     ` (2 more replies)
  2022-01-19 18:55 ` [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
                   ` (9 subsequent siblings)
  10 siblings, 3 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 functions to
access the metadata. These are generic API's, and implementations can
be added based on parameters like how the metadata partition is
accessed and what type of storage device houses the metadata.

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

Changes since V2:
* Use uint*_t types in fwu_mdata.h since the file is to be reused in
  other projects
* Keep only the FWU metadata structures in fwu_mdata.h
* Move all other function and macro declarations in fwu.h
* Keep common implementations of fwu_update_active_index and
  fwu_revert_boot_index in fwu_mdata.c
* Add a update_mdata function pointer in the fwu_mdata_ops structure

 include/fwu.h               |  61 +++++++
 include/fwu_mdata.h         |  67 ++++++++
 lib/fwu_updates/fwu_mdata.c | 329 ++++++++++++++++++++++++++++++++++++
 3 files changed, 457 insertions(+)
 create mode 100644 include/fwu.h
 create mode 100644 include/fwu_mdata.h
 create mode 100644 lib/fwu_updates/fwu_mdata.c

diff --git a/include/fwu.h b/include/fwu.h
new file mode 100644
index 0000000000..acba725bc8
--- /dev/null
+++ b/include/fwu.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#if !defined _FWU_H_
+#define _FWU_H_
+
+#include <blk.h>
+#include <efi.h>
+
+#include <linux/types.h>
+
+struct fwu_mdata;
+
+/**
+ * @get_active_index: get the current active_index value
+ * @get_image_alt_num: get the alt number to be used for the image
+ * @mdata_check: check the validity of the FWU metadata partitions
+ * @set_accept_image: set the accepted bit for the image
+ * @clear_accept_image: clear the accepted bit for the image
+ * @get_mdata() - Get a FWU metadata copy
+ * @update_mdata() - Update the FWU metadata copy
+ */
+struct fwu_mdata_ops {
+	int (*get_active_index)(u32 *active_idx);
+
+	int (*get_image_alt_num)(efi_guid_t image_type_id, u32 update_bank,
+				 int *alt_num);
+
+	int (*mdata_check)(void);
+
+	int (*set_accept_image)(efi_guid_t *img_type_id, u32 bank);
+
+	int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
+
+	int (*get_mdata)(struct fwu_mdata **mdata);
+
+	int (*update_mdata)(struct fwu_mdata *mdata);
+};
+
+struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
+
+#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..d788eb69e7
--- /dev/null
+++ b/include/fwu_mdata.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021, 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_ */
diff --git a/lib/fwu_updates/fwu_mdata.c b/lib/fwu_updates/fwu_mdata.c
new file mode 100644
index 0000000000..58e838fe28
--- /dev/null
+++ b/lib/fwu_updates/fwu_mdata.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#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>
+
+static struct fwu_mdata_ops *get_fwu_mdata_ops(void)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops =  get_plat_fwu_mdata_ops();
+	if (!ops) {
+		log_err("Unable to get fwu ops\n");
+		return NULL;
+	}
+
+	return ops;
+}
+
+/**
+ * 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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->get_active_index) {
+		log_err("get_active_index() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->get_active_index(active_idx);
+}
+
+/**
+ * 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) {
+		printf("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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->get_image_alt_num) {
+		log_err("get_image_alt_num() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->get_image_alt_num(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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->mdata_check) {
+		log_err("mdata_check() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->mdata_check();
+}
+
+/**
+ * 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_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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->set_accept_image) {
+		log_err("set_accept_image() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->set_accept_image(img_type_id, bank);
+}
+
+/**
+ * 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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->clear_accept_image) {
+		log_err("clear_accept_image() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->clear_accept_image(img_type_id, bank);
+}
+
+/**
+ * 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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->get_mdata) {
+		log_err("get_mdata() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->get_mdata(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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->update_mdata) {
+		log_err("get_mdata() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->update_mdata(mdata);
+}
-- 
2.17.1


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

* [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2022-01-19 18:55 ` [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20  8:43   ` Masami Hiramatsu
  2022-01-20 11:27   ` Heinrich Schuchardt
  2022-01-19 18:55 ` [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 functions 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 V2:
* Move the function definition of fwu_verify_mdata to fwu_mdata.c to
  facilitate reuse
* Remove the block device specific desc->devnum parameter for the
  fwu_plat_get_alt_num function call

 include/fwu.h                       |   1 +
 include/fwu_mdata.h                 |   2 +
 lib/fwu_updates/fwu_mdata.c         |  29 ++
 lib/fwu_updates/fwu_mdata_gpt_blk.c | 520 ++++++++++++++++++++++++++++
 4 files changed, 552 insertions(+)
 create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c

diff --git a/include/fwu.h b/include/fwu.h
index acba725bc8..12f7eecdb0 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -53,6 +53,7 @@ int fwu_get_active_index(u32 *active_idx);
 int fwu_update_active_index(u32 active_idx);
 int fwu_get_image_alt_num(efi_guid_t image_type_id, u32 update_bank,
 			  int *alt_num);
+int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part);
 int fwu_mdata_check(void);
 int fwu_revert_boot_index(void);
 int fwu_accept_image(efi_guid_t *img_type_id, u32 bank);
diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
index d788eb69e7..53e39f9af6 100644
--- a/include/fwu_mdata.h
+++ b/include/fwu_mdata.h
@@ -64,4 +64,6 @@ struct fwu_mdata {
 	struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
 } __attribute__((__packed__));
 
+extern struct fwu_mdata_ops fwu_gpt_blk_ops;
+
 #endif /* _FWU_MDATA_H_ */
diff --git a/lib/fwu_updates/fwu_mdata.c b/lib/fwu_updates/fwu_mdata.c
index 58e838fe28..252fcf50f6 100644
--- a/lib/fwu_updates/fwu_mdata.c
+++ b/lib/fwu_updates/fwu_mdata.c
@@ -25,6 +25,35 @@ static struct fwu_mdata_ops *get_fwu_mdata_ops(void)
 	return ops;
 }
 
+/**
+ * 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
diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
new file mode 100644
index 0000000000..cb47ddf4a7
--- /dev/null
+++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#include <blk.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 <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)
+
+#define IMAGE_ACCEPT_SET	BIT(0)
+#define IMAGE_ACCEPT_CLEAR	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;
+
+	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 fwu_mdata *mdata)
+{
+	int ret;
+	struct blk_desc *desc;
+	u16 primary_mpart = 0, secondary_mpart = 0;
+
+	ret = fwu_plat_get_blk_desc(&desc);
+	if (ret < 0) {
+		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 fwu_mdata **mdata)
+{
+	int ret;
+	struct blk_desc *desc;
+	u16 primary_mpart = 0, secondary_mpart = 0;
+
+	ret = fwu_plat_get_blk_desc(&desc);
+	if (ret < 0) {
+		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;
+	}
+
+	*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(void)
+{
+	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;
+
+	ret = fwu_plat_get_blk_desc(&desc);
+	if (ret < 0) {
+		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;
+}
+
+int fwu_gpt_get_active_index(u32 *active_idx)
+{
+	int ret;
+	struct fwu_mdata *mdata;
+
+	ret = gpt_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) {
+		printf("Active index value read is incorrect\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+static int gpt_get_image_alt_num(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;
+	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(&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(&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(efi_guid_t image_type_id, u32 update_bank,
+			      int *alt_no)
+{
+	int ret;
+	struct blk_desc *desc;
+
+	ret = fwu_plat_get_blk_desc(&desc);
+	if (ret < 0) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return gpt_get_image_alt_num(desc, image_type_id, update_bank, alt_no);
+}
+
+int fwu_gpt_mdata_check(void)
+{
+	/*
+	 * 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();
+}
+
+int fwu_gpt_get_mdata(struct fwu_mdata **mdata)
+{
+	return gpt_get_mdata(mdata);
+}
+
+static int fwu_gpt_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;
+	struct fwu_image_entry *img_entry;
+	struct fwu_image_bank_info *img_bank_info;
+
+	ret = gpt_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_gpt_update_mdata(mdata);
+			goto out;
+		}
+	}
+
+	/* Image not found */
+	ret = -EINVAL;
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+static int fwu_gpt_accept_image(efi_guid_t *img_type_id, u32 bank)
+{
+	return fwu_gpt_set_clear_image_accept(img_type_id, bank,
+					      IMAGE_ACCEPT_SET);
+}
+
+static int fwu_gpt_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
+{
+	return fwu_gpt_set_clear_image_accept(img_type_id, bank,
+					      IMAGE_ACCEPT_CLEAR);
+}
+
+struct fwu_mdata_ops fwu_gpt_blk_ops = {
+	.get_active_index = fwu_gpt_get_active_index,
+	.get_image_alt_num = fwu_gpt_get_image_alt_num,
+	.mdata_check = fwu_gpt_mdata_check,
+	.set_accept_image = fwu_gpt_accept_image,
+	.clear_accept_image = fwu_gpt_clear_accept_image,
+	.get_mdata = fwu_gpt_get_mdata,
+	.update_mdata = fwu_gpt_update_mdata,
+};
-- 
2.17.1


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

* [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2022-01-19 18:55 ` [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
  2022-01-19 18:55 ` [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20 10:59   ` Heinrich Schuchardt
                     ` (2 more replies)
  2022-01-19 18:55 ` [RFC PATCH v3 4/9] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
                   ` (7 subsequent siblings)
  10 siblings, 3 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2:
* Change the implementation of fwu_plat_get_alt_num to get the devnum
  in the function before calling gpt_plat_get_alt_num

 board/st/stm32mp1/stm32mp1.c        | 176 ++++++++++++++++++++++++++++
 include/fwu.h                       |   5 +
 lib/fwu_updates/fwu_mdata_gpt_blk.c |   7 +-
 3 files changed, 185 insertions(+), 3 deletions(-)

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 84592677e4..66cbe3f798 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,174 @@ 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(void *identifier)
+{
+	int ret;
+	struct blk_desc *desc;
+
+	ret = fwu_plat_get_blk_desc(&desc);
+	if (ret < 0) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return gpt_plat_get_alt_num(desc->devnum, identifier);
+}
+
+static int plat_fill_gpt_partition_guids(struct blk_desc *desc,
+					 efi_guid_t **part_guid_arr)
+{
+	int i, ret = 0;
+	u32 part;
+	struct dfu_entity *dfu;
+	struct disk_partition info;
+	efi_guid_t part_type_guid;
+	int alt_num = dfu_get_alt_number();
+
+	dfu_init_env_entities(NULL, NULL);
+
+	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++;
+	}
+
+	dfu_free_entities();
+
+	return ret;
+}
+
+int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr)
+{
+	int ret;
+	struct blk_desc *desc;
+
+	ret = fwu_plat_get_blk_desc(&desc);
+	if (ret < 0) {
+		log_err("Block device not found\n");
+		return -ENODEV;
+	}
+
+	return plat_fill_gpt_partition_guids(desc, part_guid_arr);
+}
+
+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;
+}
+
+int fwu_plat_get_blk_desc(struct blk_desc **desc)
+{
+	int ret;
+	struct mmc *mmc;
+	struct udevice *dev;
+
+	/*
+	 * Initial support is being added for the DK2
+	 * platform
+	 */
+	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
+	    (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
+		ret = uclass_get_device(UCLASS_MMC, 0, &dev);
+		if (ret)
+			return -1;
+
+		mmc = mmc_get_mmc_dev(dev);
+		if (!mmc)
+			return -1;
+
+		if (mmc_init(mmc))
+			return -1;
+
+		*desc = mmc_get_blk_desc(mmc);
+		if (!*desc)
+			return -1;
+	}
+
+	return 0;
+}
+
+struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
+{
+	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
+	    (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
+		return &fwu_gpt_blk_ops;
+	}
+
+	return NULL;
+}
+#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
diff --git a/include/fwu.h b/include/fwu.h
index 12f7eecdb0..b23a93ac40 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -59,4 +59,9 @@ 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_blk_desc(struct blk_desc **desc);
+int fwu_plat_get_alt_num(void *identifier);
+int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
+
 #endif /* _FWU_H_ */
diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
index cb47ddf4a7..796b08e76f 100644
--- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
+++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
@@ -37,6 +37,7 @@ static int gpt_get_mdata_partitions(struct blk_desc *desc,
 	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;
@@ -324,7 +325,7 @@ out:
 int fwu_gpt_get_active_index(u32 *active_idx)
 {
 	int ret;
-	struct fwu_mdata *mdata;
+	struct fwu_mdata *mdata = NULL;
 
 	ret = gpt_get_mdata(&mdata);
 	if (ret < 0) {
@@ -355,7 +356,7 @@ static int gpt_get_image_alt_num(struct blk_desc *desc,
 {
 	int ret, i;
 	u32 part;
-	struct fwu_mdata *mdata;
+	struct fwu_mdata *mdata = NULL;
 	struct fwu_image_entry *img_entry;
 	struct fwu_image_bank_info *img_bank_info;
 	struct disk_partition info;
@@ -459,7 +460,7 @@ static int fwu_gpt_set_clear_image_accept(efi_guid_t *img_type_id,
 	void *buf;
 	int ret, i;
 	u32 nimages;
-	struct fwu_mdata *mdata;
+	struct fwu_mdata *mdata = NULL;
 	struct fwu_image_entry *img_entry;
 	struct fwu_image_bank_info *img_bank_info;
 
-- 
2.17.1


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

* [RFC PATCH v3 4/9] FWU: STM32MP1: Add support to read boot index from backup register
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (2 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20 12:24   ` Heinrich Schuchardt
  2022-01-19 18:55 ` [RFC PATCH v3 5/9] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2: None

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

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 66cbe3f798..6e7aaaa8a4 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -1104,6 +1104,13 @@ int fwu_plat_get_blk_desc(struct blk_desc **desc)
 	return 0;
 }
 
+void fwu_plat_get_bootidx(void *boot_idx)
+{
+	u32 *bootidx = boot_idx;
+
+	*bootidx = readl(TAMP_BOOTCOUNT);
+}
+
 struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
 {
 	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
diff --git a/include/fwu.h b/include/fwu.h
index b23a93ac40..6393a1dbb5 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -63,5 +63,6 @@ int fwu_plat_get_update_index(u32 *update_idx);
 int fwu_plat_get_blk_desc(struct blk_desc **desc);
 int fwu_plat_get_alt_num(void *identifier);
 int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
+void fwu_plat_get_bootidx(void *boot_idx);
 
 #endif /* _FWU_H_ */
-- 
2.17.1


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

* [RFC PATCH v3 5/9] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (3 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 4/9] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20  5:24   ` AKASHI Takahiro
  2022-01-19 18:55 ` [RFC PATCH v3 6/9] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2: None

 lib/efi_loader/efi_firmware.c | 90 ++++++++++++++++++++++++++++++++---
 1 file changed, 83 insertions(+), 7 deletions(-)

diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index a1b88dbfc2..648342ae72 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -10,6 +10,7 @@
 #include <charset.h>
 #include <dfu.h>
 #include <efi_loader.h>
+#include <fwu.h>
 #include <image.h>
 #include <signatures.h>
 
@@ -96,6 +97,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
 	return EFI_EXIT(EFI_UNSUPPORTED);
 }
 
+static efi_status_t fill_part_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 +145,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 +163,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 +213,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 +291,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 +306,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_part_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);
 }
 
@@ -358,7 +407,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	u32 *package_version,
 	u16 **package_version_name)
 {
+	int status;
 	efi_status_t ret = EFI_SUCCESS;
+	const efi_guid_t null_guid = NULL_GUID;
+	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 +425,36 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
 	     !descriptor_size || !package_version || !package_version_name))
 		return EFI_EXIT(EFI_INVALID_PARAMETER);
 
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		ret = fill_part_guid_array(&null_guid, &part_guid_arr);
+		if (ret != EFI_SUCCESS)
+			goto out;
+
+		/*
+		 * Call the platform function to fill the GUID array
+		 * with the corresponding partition GUID values
+		 */
+		status = fwu_plat_fill_partition_guids(&part_guid_arr);
+		if (status < 0) {
+			log_err("Unable to get partiion guid's\n");
+			ret = EFI_DEVICE_ERROR;
+			goto out;
+		}
+	} else {
+		ret = fill_part_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] 45+ messages in thread

* [RFC PATCH v3 6/9] FWU: Add boot time checks as highlighted by the FWU specification
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (4 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 5/9] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-21 13:15   ` Ilias Apalodimas
  2022-01-19 18:55 ` [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2:
* Add logic to delete the TrialStateCtr variable if system is not in
  Trial State

 common/board_r.c      |   6 ++
 include/fwu.h         |   3 +
 lib/fwu_updates/fwu.c | 171 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 180 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 6393a1dbb5..950a816dbd 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -47,6 +47,9 @@ struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
 	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..906b5e622a
--- /dev/null
+++ b/lib/fwu_updates/fwu.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#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 |
+			EFI_VARIABLE_RUNTIME_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;
+	u32 boot_idx, active_idx;
+
+	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] 45+ messages in thread

* [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (5 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 6/9] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20  6:07   ` Masami Hiramatsu
  2022-01-19 18:55 ` [RFC PATCH v3 8/9] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2:
* Add logic to check if bit 15(OS Acceptance) of the Flags member in
  the capsule header is set
* Add logic to set the accept bit of all images from a capsule if the
  OS Acceptance bit in the capsule header is not set

 include/fwu.h                |  12 +-
 lib/Kconfig                  |   6 +
 lib/Makefile                 |   1 +
 lib/efi_loader/efi_capsule.c | 233 ++++++++++++++++++++++++++++++++++-
 lib/efi_loader/efi_setup.c   |   3 +-
 lib/fwu_updates/Kconfig      |  31 +++++
 lib/fwu_updates/Makefile     |  11 ++
 lib/fwu_updates/fwu.c        |  27 ++++
 8 files changed, 319 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 950a816dbd..6c9b64a9f1 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -42,13 +42,23 @@ struct fwu_mdata_ops {
 struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
 
 #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 8301eed631..83c89a0cbb 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 */
@@ -403,10 +414,13 @@ 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;
 
 	/* sanity check */
 	if (capsule_data->header_size < sizeof(*capsule) ||
@@ -481,8 +495,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 +535,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:
@@ -527,6 +601,9 @@ efi_status_t EFIAPI efi_update_capsule(
 		u64 scatter_gather_list)
 {
 	struct efi_capsule_header *capsule;
+	efi_guid_t *image_guid;
+	u32 active_idx;
+	int status;
 	unsigned int i;
 	efi_status_t ret;
 
@@ -538,6 +615,16 @@ efi_status_t EFIAPI efi_update_capsule(
 		goto out;
 	}
 
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+		/* 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");
+			ret = EFI_DEVICE_ERROR;
+			goto out;
+		}
+	}
+
 	ret = EFI_SUCCESS;
 	for (i = 0, capsule = *capsule_header_array; i < capsule_count;
 	     i++, capsule = *(++capsule_header_array)) {
@@ -552,7 +639,82 @@ efi_status_t EFIAPI efi_update_capsule(
 			  i, &capsule->capsule_guid);
 		if (!guidcmp(&capsule->capsule_guid,
 			     &efi_guid_firmware_management_capsule_id)) {
+			if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+				if (!fwu_update_checks_pass()) {
+					log_err("FWU checks failed. Cannot start update\n");
+					ret = EFI_INVALID_PARAMETER;
+					goto out;
+				}
+				if (capsule->flags & FW_ACCEPT_OS)
+					fw_accept_os = 0x1;
+			}
+
 			ret  = efi_capsule_update_firmware(capsule);
+			capsule_update = true;
+		} else if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+			capsule_update = false;
+			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;
+					goto out;
+				}
+
+				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;
+				}
+			}
 		} else {
 			log_err("Unsupported capsule type: %pUl\n",
 				&capsule->capsule_guid);
@@ -563,6 +725,36 @@ efi_status_t EFIAPI efi_update_capsule(
 			goto out;
 	}
 
+	/*
+	 * Update the FWU metadata once all the capsules have
+	 * been updated. This is done only for the Runtime
+	 * capsule update service.
+	 * The update_index value now gets written to the
+	 * active_index and the update_index value also
+	 * gets updated.
+	 * For the capsule-on-disk feature, the updation
+	 * of the FWU metadata happens in efi_launch_capsules
+	 */
+	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE) &&
+	    !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK)) {
+		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 {
+			status = fwu_trial_state_ctr_start();
+			if (status < 0)
+				ret = EFI_DEVICE_ERROR;
+			else
+				ret = EFI_SUCCESS;
+		}
+	}
+
 	if (IS_ENABLED(CONFIG_EFI_ESRT)) {
 		/* Rebuild the ESRT to reflect any updated FW images. */
 		ret = efi_esrt_populate();
@@ -1090,8 +1282,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 +1313,11 @@ efi_status_t efi_launch_capsules(void)
 		ret = efi_capsule_read_file(files[i], &capsule);
 		if (ret == EFI_SUCCESS) {
 			ret = EFI_CALL(efi_update_capsule(&capsule, 1, 0));
-			if (ret != EFI_SUCCESS)
+			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 +1325,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 +1333,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..73099a30cb
--- /dev/null
+++ b/lib/fwu_updates/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2021, Linaro Limited
+#
+
+obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_mdata.o
+obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu.o
+
+ifdef CONFIG_EFI_PARTITION
+obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_mdata_gpt_blk.o
+endif
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 906b5e622a..fd0eccd5c6 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -115,6 +115,33 @@ 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 |
+		EFI_VARIABLE_RUNTIME_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] 45+ messages in thread

* [RFC PATCH v3 8/9] FWU: cmd: Add a command to read FWU metadata
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (6 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20 12:28   ` Heinrich Schuchardt
  2022-01-19 18:55 ` [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2:
* Include the log.h and stdio.h header files

 cmd/Kconfig     |  7 ++++++
 cmd/Makefile    |  1 +
 cmd/fwu_mdata.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 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..81e4850442
--- /dev/null
+++ b/cmd/fwu_mdata.c
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#include <command.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 Read\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[])
+{
+	int ret = CMD_RET_SUCCESS;
+	struct fwu_mdata *mdata = NULL;
+
+	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] 45+ messages in thread

* [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (7 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 8/9] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
@ 2022-01-19 18:55 ` Sughosh Ganu
  2022-01-20  2:13   ` AKASHI Takahiro
  2022-01-21 13:00   ` Ilias Apalodimas
  2022-01-20  5:31 ` [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature AKASHI Takahiro
  2022-01-20 10:08 ` Heinrich Schuchardt
  10 siblings, 2 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-19 18:55 UTC (permalink / raw)
  To: u-boot
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Tom Rini, Etienne Carriere, Sughosh Ganu

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 V2:
* New patch for generating empty capsules

 tools/eficapsule.h   |   8 ++++
 tools/mkeficapsule.c | 102 ++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 100 insertions(+), 10 deletions(-)

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..643da3849d 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -29,6 +29,7 @@
 #include "eficapsule.h"
 
 static const char *tool_name = "mkeficapsule";
+static unsigned char 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,15 +56,23 @@ 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"
+	if (empty_capsule) {
+		fprintf(stderr, "Usage: %s [options]  <output file>\n",
+			tool_name);
+	} 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"
@@ -75,8 +84,9 @@ static void print_usage(void)
 		"\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 +608,59 @@ 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;
+	int ret;
+	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 = NULL;
+	ret = -1;
+
+	f = fopen(path, "w");
+	if (!f) {
+		printf("cannot open %s\n", path);
+		goto err;
+	}
+
+	if (fw_accept)
+		capsule_guid = fw_accept_guid;
+	else
+		capsule_guid = fw_revert_guid;
+
+	memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
+	header.header_size = sizeof(header);
+	header.flags = 0;
+
+	if (fw_accept) {
+		header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
+	} else {
+		header.capsule_image_size = 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
@@ -616,6 +679,7 @@ int main(int argc, char **argv)
 	unsigned char uuid_buf[16];
 	unsigned long index, instance;
 	uint64_t mcount;
+	unsigned char accept_fw_capsule, revert_fw_capsule;
 	char *privkey_file, *cert_file;
 	int c, idx;
 
@@ -625,6 +689,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 +757,38 @@ 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);
 		}
 	}
 
+	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) {
+			printf("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] 45+ messages in thread

* Re: [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-19 18:55 ` [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
@ 2022-01-20  2:13   ` AKASHI Takahiro
  2022-01-21  6:48     ` Sughosh Ganu
  2022-01-21 13:00   ` Ilias Apalodimas
  1 sibling, 1 reply; 45+ messages in thread
From: AKASHI Takahiro @ 2022-01-20  2:13 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

From user's point of view,

On Thu, Jan 20, 2022 at 12:25:48AM +0530, Sughosh Ganu wrote:
> The Dependable Boot specification describes the structure of the

May we have a pointer or reference to it?

> 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 V2:
> * New patch for generating empty capsules
> 
>  tools/eficapsule.h   |   8 ++++
>  tools/mkeficapsule.c | 102 ++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 100 insertions(+), 10 deletions(-)
> 
> 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..643da3849d 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,6 +29,7 @@
>  #include "eficapsule.h"
>  
>  static const char *tool_name = "mkeficapsule";
> +static unsigned char 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,15 +56,23 @@ 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"
> +	if (empty_capsule) {
> +		fprintf(stderr, "Usage: %s [options]  <output file>\n",
> +			tool_name);
> +	} else {
> +		fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> +			tool_name);
> +	}

We should always show both cases regardless of "empty_capsule".

Or if you have any restrictions on a combination of options,
you'd better describe them more specifically in help message.

I'd also like to encourage you to update the man page as well as uefi.rst.

> +	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"
> @@ -75,8 +84,9 @@ static void print_usage(void)
>  		"\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 +608,59 @@ 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;
> +	int ret;
> +	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 = NULL;
> +	ret = -1;
> +
> +	f = fopen(path, "w");
> +	if (!f) {
> +		printf("cannot open %s\n", path);

To stderr as Heinrich has requested.

> +		goto err;
> +	}
> +
> +	if (fw_accept)
> +		capsule_guid = fw_accept_guid;
> +	else
> +		capsule_guid = fw_revert_guid;
> +
> +	memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
> +	header.header_size = sizeof(header);
> +	header.flags = 0;
> +
> +	if (fw_accept) {
> +		header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
> +	} else {
> +		header.capsule_image_size = sizeof(header);
> +	}

I wonder why we don't need GUID in revert case (and why need GUID
in fw case. Since we want to add A/B update, there seems to be
no ambiguity.

> +	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
> @@ -616,6 +679,7 @@ int main(int argc, char **argv)
>  	unsigned char uuid_buf[16];
>  	unsigned long index, instance;
>  	uint64_t mcount;
> +	unsigned char accept_fw_capsule, revert_fw_capsule;
>  	char *privkey_file, *cert_file;
>  	int c, idx;
>  
> @@ -625,6 +689,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 +757,38 @@ 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);
>  		}
>  	}
>  
> +	empty_capsule = (accept_fw_capsule || revert_fw_capsule);

Please check that two options are exclusive here.

>  	/* 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) {
> +			printf("Creating empty capsule failed\n");

To stderr

-Takahiro Akashi

> +			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] 45+ messages in thread

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

On Thu, Jan 20, 2022 at 12:25:44AM +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.
> 
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> 
> Changes since V2: None
> 
>  lib/efi_loader/efi_firmware.c | 90 ++++++++++++++++++++++++++++++++---
>  1 file changed, 83 insertions(+), 7 deletions(-)
> 
> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> index a1b88dbfc2..648342ae72 100644
> --- a/lib/efi_loader/efi_firmware.c
> +++ b/lib/efi_loader/efi_firmware.c
> @@ -10,6 +10,7 @@
>  #include <charset.h>
>  #include <dfu.h>
>  #include <efi_loader.h>
> +#include <fwu.h>
>  #include <image.h>
>  #include <signatures.h>
>  
> @@ -96,6 +97,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
>  	return EFI_EXIT(EFI_UNSUPPORTED);
>  }
>  
> +static efi_status_t fill_part_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 +145,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 +163,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 +213,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 +291,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 +306,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_part_guid_array(&efi_firmware_image_type_uboot_fit,
> +				   &part_guid_arr);
> +	if (ret != EFI_SUCCESS)
> +		goto out;

Why do you not call fwu_plat_fill_partition_guids() for FIT FMP driver?
If you have a specific reason, please describe it.

> +
>  	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);
>  }
>  
> @@ -358,7 +407,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
>  	u32 *package_version,
>  	u16 **package_version_name)
>  {
> +	int status;
>  	efi_status_t ret = EFI_SUCCESS;
> +	const efi_guid_t null_guid = NULL_GUID;
> +	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 +425,36 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
>  	     !descriptor_size || !package_version || !package_version_name))
>  		return EFI_EXIT(EFI_INVALID_PARAMETER);
>  
> +	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> +		ret = fill_part_guid_array(&null_guid, &part_guid_arr);
> +		if (ret != EFI_SUCCESS)
> +			goto out;
> +
> +		/*
> +		 * Call the platform function to fill the GUID array
> +		 * with the corresponding partition GUID values
> +		 */
> +		status = fwu_plat_fill_partition_guids(&part_guid_arr);
> +		if (status < 0) {
> +			log_err("Unable to get partiion guid's\n");
> +			ret = EFI_DEVICE_ERROR;
> +			goto out;
> +		}
> +	} else {
> +		ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
> +					   &part_guid_arr);
> +		if (ret != EFI_SUCCESS)
> +			goto out;
> +	}

The code:
        ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
                                   &part_guid_arr);
	if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
		status = fwu_plat_fill_partition_guids(&part_guid_arr);

would be much simpler here.

But I don't know why you want to call fwu_plat_fill_partition_guids()
only in case of CONFIG_FWU_MULTI_BANK_UPDATE. The functionality should
be the same whether A/B update or not.

-Takahiro Akashi

> +
>  	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] 45+ messages in thread

* Re: [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (8 preceding siblings ...)
  2022-01-19 18:55 ` [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
@ 2022-01-20  5:31 ` AKASHI Takahiro
  2022-01-21  7:10   ` Sughosh Ganu
  2022-01-20 10:08 ` Heinrich Schuchardt
  10 siblings, 1 reply; 45+ messages in thread
From: AKASHI Takahiro @ 2022-01-20  5:31 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Sughosh,

On Thu, Jan 20, 2022 at 12:25:39AM +0530, Sughosh Ganu wrote:
> 
> 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.

Do you have a plan to develop any test cases for sandbox,
especially in pytest framework?

I don't see much difficulty to do so and it would be very
helpful for U-Boot CI process.

-Takahiro Akashi

> 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
> are under review currently[3].
> 
> These patches are based on top of the series from Takahiro to add
> Authentication support to mkeficapsule utility[4]
> 
> [1] - https://developer.arm.com/documentation/den0118/a
> [2] - https://staging-git.codelinaro.org/linaro/firmware-dual-banked-updates/test
> [3] - https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/12566
> [4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> 
> Changes since V2:
> * Use uint*_t types in fwu_mdata.h since the file is to be reused in
>   other projects
> * Keep only the FWU metadata structures in fwu_mdata.h
> * Move all other function and macro declarations in fwu.h
> * Keep common implementations of fwu_update_active_index and
>   fwu_revert_boot_index in fwu_mdata.c
> * Add a update_mdata function pointer in the fwu_mdata_ops structure
> * Move the function definition of fwu_verify_mdata to fwu_mdata.c to
>   facilitate reuse
> * Remove the block device specific desc->devnum parameter for the
>   fwu_plat_get_alt_num function call
> * Change the implementation of fwu_plat_get_alt_num to get the devnum
>   in the function before calling gpt_plat_get_alt_num
> * Add logic to delete the TrialStateCtr variable if system is not in
>   Trial State
> * Add logic to check if bit 15(OS Acceptance) of the Flags member in
>   the capsule header is set
> * Add logic to set the accept bit of all images from a capsule if the
>   OS Acceptance bit in the capsule header is not set
> * Include the log.h and stdio.h header files
> 
> Sughosh Ganu (9):
>   FWU: Add FWU metadata structure and functions for accessing metadata
>   FWU: Add FWU metadata access functions 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
>   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
> 
>  board/st/stm32mp1/stm32mp1.c        | 183 ++++++++++
>  cmd/Kconfig                         |   7 +
>  cmd/Makefile                        |   1 +
>  cmd/fwu_mdata.c                     |  67 ++++
>  common/board_r.c                    |   6 +
>  include/fwu.h                       |  81 +++++
>  include/fwu_mdata.h                 |  69 ++++
>  lib/Kconfig                         |   6 +
>  lib/Makefile                        |   1 +
>  lib/efi_loader/efi_capsule.c        | 233 ++++++++++++-
>  lib/efi_loader/efi_firmware.c       |  90 ++++-
>  lib/efi_loader/efi_setup.c          |   3 +-
>  lib/fwu_updates/Kconfig             |  31 ++
>  lib/fwu_updates/Makefile            |  11 +
>  lib/fwu_updates/fwu.c               | 198 +++++++++++
>  lib/fwu_updates/fwu_mdata.c         | 358 +++++++++++++++++++
>  lib/fwu_updates/fwu_mdata_gpt_blk.c | 521 ++++++++++++++++++++++++++++
>  tools/eficapsule.h                  |   8 +
>  tools/mkeficapsule.c                | 102 +++++-
>  19 files changed, 1955 insertions(+), 21 deletions(-)
>  create mode 100644 cmd/fwu_mdata.c
>  create mode 100644 include/fwu.h
>  create mode 100644 include/fwu_mdata.h
>  create mode 100644 lib/fwu_updates/Kconfig
>  create mode 100644 lib/fwu_updates/Makefile
>  create mode 100644 lib/fwu_updates/fwu.c
>  create mode 100644 lib/fwu_updates/fwu_mdata.c
>  create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c
> 
> -- 
> 2.17.1
> 
> 

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

* Re: [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata
  2022-01-19 18:55 ` [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
@ 2022-01-20  5:53   ` Masami Hiramatsu
  2022-01-24  6:59     ` Sughosh Ganu
  2022-01-20  6:05   ` Masami Hiramatsu
  2022-01-20 12:18   ` Heinrich Schuchardt
  2 siblings, 1 reply; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-20  5:53 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hello Sughosh,

2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> 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 functions to
> access the metadata. These are generic API's, and implementations can
> be added based on parameters like how the metadata partition is
> accessed and what type of storage device houses the metadata.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>
> Changes since V2:
> * Use uint*_t types in fwu_mdata.h since the file is to be reused in
>   other projects
> * Keep only the FWU metadata structures in fwu_mdata.h
> * Move all other function and macro declarations in fwu.h
> * Keep common implementations of fwu_update_active_index and
>   fwu_revert_boot_index in fwu_mdata.c
> * Add a update_mdata function pointer in the fwu_mdata_ops structure
>
>  include/fwu.h               |  61 +++++++
>  include/fwu_mdata.h         |  67 ++++++++
>  lib/fwu_updates/fwu_mdata.c | 329 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 457 insertions(+)
>  create mode 100644 include/fwu.h
>  create mode 100644 include/fwu_mdata.h
>  create mode 100644 lib/fwu_updates/fwu_mdata.c
>
> diff --git a/include/fwu.h b/include/fwu.h
> new file mode 100644
> index 0000000000..acba725bc8
> --- /dev/null
> +++ b/include/fwu.h
> @@ -0,0 +1,61 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#if !defined _FWU_H_
> +#define _FWU_H_
> +
> +#include <blk.h>
> +#include <efi.h>
> +
> +#include <linux/types.h>
> +
> +struct fwu_mdata;
> +
> +/**
> + * @get_active_index: get the current active_index value
> + * @get_image_alt_num: get the alt number to be used for the image
> + * @mdata_check: check the validity of the FWU metadata partitions
> + * @set_accept_image: set the accepted bit for the image
> + * @clear_accept_image: clear the accepted bit for the image
> + * @get_mdata() - Get a FWU metadata copy
> + * @update_mdata() - Update the FWU metadata copy
> + */
> +struct fwu_mdata_ops {
> +       int (*get_active_index)(u32 *active_idx);
> +
> +       int (*get_image_alt_num)(efi_guid_t image_type_id, u32 update_bank,
> +                                int *alt_num);
> +
> +       int (*mdata_check)(void);
> +
> +       int (*set_accept_image)(efi_guid_t *img_type_id, u32 bank);
> +
> +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> +
> +       int (*get_mdata)(struct fwu_mdata **mdata);
> +
> +       int (*update_mdata)(struct fwu_mdata *mdata);
> +};

We also can remove
- get_active_index
- set_accept_image
- clear_accept_image
from these operations, because those are just reading or modifying metadata.
Such functions can be written as below

ops()
{
   op->get_mdata(&mdata);
   do_some_operation(mdata);
   if (updated)
     op->update_mdata(mdata);
}

I'll make a series of patches on top of your series for DeveloperBox,
which does not use GPT.

Thank you,

-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata
  2022-01-19 18:55 ` [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
  2022-01-20  5:53   ` Masami Hiramatsu
@ 2022-01-20  6:05   ` Masami Hiramatsu
  2022-01-24  7:07     ` Sughosh Ganu
  2022-01-20 12:18   ` Heinrich Schuchardt
  2 siblings, 1 reply; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-20  6:05 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

I have another comment on this patch.

2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:

> +/**
> + * 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) {

Since active_index must be 0 .. CONFIG_FWU_NUM_BANKS - 1, it should
cap the new active_index with "CONFIG_FWU_NUM_BANKS - 1" instead of
"CONFIG_FWU_NUM_BANKS".

> +               printf("Active index value to be updated is incorrect\n");

Could you use log_err() instead of printf() for error messages?

Thank you,


-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-19 18:55 ` [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2022-01-20  6:07   ` Masami Hiramatsu
  2022-01-21  7:17     ` Sughosh Ganu
  0 siblings, 1 reply; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-20  6:07 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hello Sughosh,

2022年1月20日(木) 3:57 Sughosh Ganu <sughosh.ganu@linaro.org>:

> 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

It is clear that the FWU_MULTI_BANK_UPDATE depends on
EFI_CAPSULE_FIRMWARE_RAW, please select it here.

Thank you,


--
Masami Hiramatsu

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

* Re: [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-19 18:55 ` [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
@ 2022-01-20  8:43   ` Masami Hiramatsu
  2022-01-24  6:58     ` Sughosh Ganu
  2022-01-20 11:27   ` Heinrich Schuchardt
  1 sibling, 1 reply; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-20  8:43 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:

> +static int fwu_gpt_update_mdata(struct fwu_mdata *mdata)
> +{
> +       int ret;
> +       struct blk_desc *desc;
> +       u16 primary_mpart = 0, secondary_mpart = 0;
> +

I think this update_mdata() method (or fwu_update_mdata() wrapper)
should always update mdata::crc32. calculate crc32 at each call site is
inefficient and easy to introduce bugs.

> +       ret = fwu_plat_get_blk_desc(&desc);
> +       if (ret < 0) {
> +               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 fwu_mdata **mdata)
> +{
> +       int ret;
> +       struct blk_desc *desc;
> +       u16 primary_mpart = 0, secondary_mpart = 0;
> +
> +       ret = fwu_plat_get_blk_desc(&desc);
> +       if (ret < 0) {
> +               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;
> +       }
> +
> +       *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");

Also, please release mdata inside the gpt_get_mdata() itself.

I think it is not a good design to ask caller to free mdata if get_mdata()
operation is failed because mdata may or may not allocated in error case.

In success case, user must free it because it is allocated (user accessed it),
and in error case, user can ignore it because it should not be allocated.
This is simpler mind model and less memory leak chance.

Thank you,
-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (9 preceding siblings ...)
  2022-01-20  5:31 ` [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature AKASHI Takahiro
@ 2022-01-20 10:08 ` Heinrich Schuchardt
  2022-01-21  7:15   ` Sughosh Ganu
  10 siblings, 1 reply; 45+ messages in thread
From: Heinrich Schuchardt @ 2022-01-20 10:08 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

On 1/19/22 19:55, Sughosh Ganu wrote:
> 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 document "Platform Security Firmware Update for the A-profile Arm
Architecture Beta" [1] that you relate to describes updating using FF-A
[5] as a communication protocol between a normal world client and an
update agent in the secure world. [1] further describes an API for this
communication. I cannot see that you are implementing this:

* U-Boot is living in the normal world, so it cannot be the update agent
of [1].
* Implementing the client of [1] in U-Boot would not require board
specific changes.

This patch set comes without any documentation update. We need a patch
which adds documents to U-Boot describing

* the design of the update mechanism
* the usage of the update mechanism

before we can start the review of the patches.

Best regards

Heinrich

[1] Platform Security Firmware Update for the A-profile Arm Architecture
Beta
https://developer.arm.com/documentation/den0118/a

[5] Arm Firmware Framework for Arm A-profile
https://developer.arm.com/documentation/den0077/latest

>
> 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
> are under review currently[3].
  >
> These patches are based on top of the series from Takahiro to add
> Authentication support to mkeficapsule utility[4]
>
> [1] - https://developer.arm.com/documentation/den0118/a
> [2] - https://staging-git.codelinaro.org/linaro/firmware-dual-banked-updates/test
> [3] - https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/12566
> [4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
>
> Changes since V2:
> * Use uint*_t types in fwu_mdata.h since the file is to be reused in
>    other projects
> * Keep only the FWU metadata structures in fwu_mdata.h
> * Move all other function and macro declarations in fwu.h
> * Keep common implementations of fwu_update_active_index and
>    fwu_revert_boot_index in fwu_mdata.c
> * Add a update_mdata function pointer in the fwu_mdata_ops structure
> * Move the function definition of fwu_verify_mdata to fwu_mdata.c to
>    facilitate reuse
> * Remove the block device specific desc->devnum parameter for the
>    fwu_plat_get_alt_num function call
> * Change the implementation of fwu_plat_get_alt_num to get the devnum
>    in the function before calling gpt_plat_get_alt_num
> * Add logic to delete the TrialStateCtr variable if system is not in
>    Trial State
> * Add logic to check if bit 15(OS Acceptance) of the Flags member in
>    the capsule header is set
> * Add logic to set the accept bit of all images from a capsule if the
>    OS Acceptance bit in the capsule header is not set
> * Include the log.h and stdio.h header files
>
> Sughosh Ganu (9):
>    FWU: Add FWU metadata structure and functions for accessing metadata
>    FWU: Add FWU metadata access functions 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
>    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
>
>   board/st/stm32mp1/stm32mp1.c        | 183 ++++++++++
>   cmd/Kconfig                         |   7 +
>   cmd/Makefile                        |   1 +
>   cmd/fwu_mdata.c                     |  67 ++++
>   common/board_r.c                    |   6 +
>   include/fwu.h                       |  81 +++++
>   include/fwu_mdata.h                 |  69 ++++
>   lib/Kconfig                         |   6 +
>   lib/Makefile                        |   1 +
>   lib/efi_loader/efi_capsule.c        | 233 ++++++++++++-
>   lib/efi_loader/efi_firmware.c       |  90 ++++-
>   lib/efi_loader/efi_setup.c          |   3 +-
>   lib/fwu_updates/Kconfig             |  31 ++
>   lib/fwu_updates/Makefile            |  11 +
>   lib/fwu_updates/fwu.c               | 198 +++++++++++
>   lib/fwu_updates/fwu_mdata.c         | 358 +++++++++++++++++++
>   lib/fwu_updates/fwu_mdata_gpt_blk.c | 521 ++++++++++++++++++++++++++++
>   tools/eficapsule.h                  |   8 +
>   tools/mkeficapsule.c                | 102 +++++-
>   19 files changed, 1955 insertions(+), 21 deletions(-)
>   create mode 100644 cmd/fwu_mdata.c
>   create mode 100644 include/fwu.h
>   create mode 100644 include/fwu_mdata.h
>   create mode 100644 lib/fwu_updates/Kconfig
>   create mode 100644 lib/fwu_updates/Makefile
>   create mode 100644 lib/fwu_updates/fwu.c
>   create mode 100644 lib/fwu_updates/fwu_mdata.c
>   create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c
>


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

* Re: [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-01-19 18:55 ` [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2022-01-20 10:59   ` Heinrich Schuchardt
  2022-01-21 10:05     ` Sughosh Ganu
  2022-01-21 11:52   ` Ilias Apalodimas
  2022-01-24  2:46   ` Masami Hiramatsu
  2 siblings, 1 reply; 45+ messages in thread
From: Heinrich Schuchardt @ 2022-01-20 10:59 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

On 1/19/22 19:55, Sughosh Ganu wrote:
> 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>

It is unclear why you are creating platform specific code here.

All of this metadata can be put into the control devicetree? If not
create a driver class for it.

Unfortunately you don't provide any design document.


Best regards

Heinrich


> ---
>
> Changes since V2:
> * Change the implementation of fwu_plat_get_alt_num to get the devnum
>    in the function before calling gpt_plat_get_alt_num
>
>   board/st/stm32mp1/stm32mp1.c        | 176 ++++++++++++++++++++++++++++
>   include/fwu.h                       |   5 +
>   lib/fwu_updates/fwu_mdata_gpt_blk.c |   7 +-
>   3 files changed, 185 insertions(+), 3 deletions(-)
>
> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> index 84592677e4..66cbe3f798 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,174 @@ 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(void *identifier)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		log_err("Block device not found\n");
> +		return -ENODEV;
> +	}
> +
> +	return gpt_plat_get_alt_num(desc->devnum, identifier);
> +}
> +
> +static int plat_fill_gpt_partition_guids(struct blk_desc *desc,
> +					 efi_guid_t **part_guid_arr)
> +{
> +	int i, ret = 0;
> +	u32 part;
> +	struct dfu_entity *dfu;
> +	struct disk_partition info;
> +	efi_guid_t part_type_guid;
> +	int alt_num = dfu_get_alt_number();
> +
> +	dfu_init_env_entities(NULL, NULL);
> +
> +	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++;
> +	}
> +
> +	dfu_free_entities();
> +
> +	return ret;
> +}
> +
> +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		log_err("Block device not found\n");
> +		return -ENODEV;
> +	}
> +
> +	return plat_fill_gpt_partition_guids(desc, part_guid_arr);
> +}
> +
> +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;
> +}
> +
> +int fwu_plat_get_blk_desc(struct blk_desc **desc)
> +{
> +	int ret;
> +	struct mmc *mmc;
> +	struct udevice *dev;
> +
> +	/*
> +	 * Initial support is being added for the DK2
> +	 * platform
> +	 */
> +	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> +	    (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> +		ret = uclass_get_device(UCLASS_MMC, 0, &dev);
> +		if (ret)
> +			return -1;
> +
> +		mmc = mmc_get_mmc_dev(dev);
> +		if (!mmc)
> +			return -1;
> +
> +		if (mmc_init(mmc))
> +			return -1;
> +
> +		*desc = mmc_get_blk_desc(mmc);
> +		if (!*desc)
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
> +{
> +	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> +	    (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> +		return &fwu_gpt_blk_ops;
> +	}
> +
> +	return NULL;
> +}
> +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
> diff --git a/include/fwu.h b/include/fwu.h
> index 12f7eecdb0..b23a93ac40 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -59,4 +59,9 @@ 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_blk_desc(struct blk_desc **desc);
> +int fwu_plat_get_alt_num(void *identifier);
> +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
> +
>   #endif /* _FWU_H_ */
> diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> index cb47ddf4a7..796b08e76f 100644
> --- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
> +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> @@ -37,6 +37,7 @@ static int gpt_get_mdata_partitions(struct blk_desc *desc,
>   	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;
> @@ -324,7 +325,7 @@ out:
>   int fwu_gpt_get_active_index(u32 *active_idx)
>   {
>   	int ret;
> -	struct fwu_mdata *mdata;
> +	struct fwu_mdata *mdata = NULL;
>
>   	ret = gpt_get_mdata(&mdata);
>   	if (ret < 0) {
> @@ -355,7 +356,7 @@ static int gpt_get_image_alt_num(struct blk_desc *desc,
>   {
>   	int ret, i;
>   	u32 part;
> -	struct fwu_mdata *mdata;
> +	struct fwu_mdata *mdata = NULL;
>   	struct fwu_image_entry *img_entry;
>   	struct fwu_image_bank_info *img_bank_info;
>   	struct disk_partition info;
> @@ -459,7 +460,7 @@ static int fwu_gpt_set_clear_image_accept(efi_guid_t *img_type_id,
>   	void *buf;
>   	int ret, i;
>   	u32 nimages;
> -	struct fwu_mdata *mdata;
> +	struct fwu_mdata *mdata = NULL;
>   	struct fwu_image_entry *img_entry;
>   	struct fwu_image_bank_info *img_bank_info;
>


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

* Re: [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-19 18:55 ` [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
  2022-01-20  8:43   ` Masami Hiramatsu
@ 2022-01-20 11:27   ` Heinrich Schuchardt
  2022-01-21 10:20     ` Sughosh Ganu
  1 sibling, 1 reply; 45+ messages in thread
From: Heinrich Schuchardt @ 2022-01-20 11:27 UTC (permalink / raw)
  To: Sughosh Ganu, u-boot
  Cc: 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 1/19/22 19:55, Sughosh Ganu wrote:
> In the FWU Multi Bank Update feature, the information about the
> updatable images is stored as part of the metadata, on a separate
> partition. Add functions 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>

Will a GPT partition remain the only place to store that information?
Should this be implemented according to the dirver model?

> ---
>
> Changes since V2:
> * Move the function definition of fwu_verify_mdata to fwu_mdata.c to
>    facilitate reuse
> * Remove the block device specific desc->devnum parameter for the
>    fwu_plat_get_alt_num function call
>
>   include/fwu.h                       |   1 +
>   include/fwu_mdata.h                 |   2 +
>   lib/fwu_updates/fwu_mdata.c         |  29 ++
>   lib/fwu_updates/fwu_mdata_gpt_blk.c | 520 ++++++++++++++++++++++++++++
>   4 files changed, 552 insertions(+)
>   create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c
>
> diff --git a/include/fwu.h b/include/fwu.h
> index acba725bc8..12f7eecdb0 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -53,6 +53,7 @@ int fwu_get_active_index(u32 *active_idx);
>   int fwu_update_active_index(u32 active_idx);
>   int fwu_get_image_alt_num(efi_guid_t image_type_id, u32 update_bank,
>   			  int *alt_num);
> +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part);
>   int fwu_mdata_check(void);
>   int fwu_revert_boot_index(void);
>   int fwu_accept_image(efi_guid_t *img_type_id, u32 bank);
> diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> index d788eb69e7..53e39f9af6 100644
> --- a/include/fwu_mdata.h
> +++ b/include/fwu_mdata.h
> @@ -64,4 +64,6 @@ struct fwu_mdata {
>   	struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
>   } __attribute__((__packed__));
>
> +extern struct fwu_mdata_ops fwu_gpt_blk_ops;
> +
>   #endif /* _FWU_MDATA_H_ */
> diff --git a/lib/fwu_updates/fwu_mdata.c b/lib/fwu_updates/fwu_mdata.c
> index 58e838fe28..252fcf50f6 100644
> --- a/lib/fwu_updates/fwu_mdata.c
> +++ b/lib/fwu_updates/fwu_mdata.c
> @@ -25,6 +25,35 @@ static struct fwu_mdata_ops *get_fwu_mdata_ops(void)
>   	return ops;
>   }
>
> +/**
> + * 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));

CRC32 does not offer any security against manipulation.
What are the security implications?

Best regards

Heinrich

> +
> +	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
> diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> new file mode 100644
> index 0000000000..cb47ddf4a7
> --- /dev/null
> +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> @@ -0,0 +1,520 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#include <blk.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 <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)
> +
> +#define IMAGE_ACCEPT_SET	BIT(0)
> +#define IMAGE_ACCEPT_CLEAR	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;
> +
> +	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 fwu_mdata *mdata)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +	u16 primary_mpart = 0, secondary_mpart = 0;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		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 fwu_mdata **mdata)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +	u16 primary_mpart = 0, secondary_mpart = 0;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		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;
> +	}
> +
> +	*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(void)
> +{
> +	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;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		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;
> +}
> +
> +int fwu_gpt_get_active_index(u32 *active_idx)
> +{
> +	int ret;
> +	struct fwu_mdata *mdata;
> +
> +	ret = gpt_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) {
> +		printf("Active index value read is incorrect\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +out:
> +	free(mdata);
> +
> +	return ret;
> +}
> +
> +static int gpt_get_image_alt_num(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;
> +	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(&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(&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(efi_guid_t image_type_id, u32 update_bank,
> +			      int *alt_no)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		log_err("Block device not found\n");
> +		return -ENODEV;
> +	}
> +
> +	return gpt_get_image_alt_num(desc, image_type_id, update_bank, alt_no);
> +}
> +
> +int fwu_gpt_mdata_check(void)
> +{
> +	/*
> +	 * 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();
> +}
> +
> +int fwu_gpt_get_mdata(struct fwu_mdata **mdata)
> +{
> +	return gpt_get_mdata(mdata);
> +}
> +
> +static int fwu_gpt_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;
> +	struct fwu_image_entry *img_entry;
> +	struct fwu_image_bank_info *img_bank_info;
> +
> +	ret = gpt_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_gpt_update_mdata(mdata);
> +			goto out;
> +		}
> +	}
> +
> +	/* Image not found */
> +	ret = -EINVAL;
> +
> +out:
> +	free(mdata);
> +
> +	return ret;
> +}
> +
> +static int fwu_gpt_accept_image(efi_guid_t *img_type_id, u32 bank)
> +{
> +	return fwu_gpt_set_clear_image_accept(img_type_id, bank,
> +					      IMAGE_ACCEPT_SET);
> +}
> +
> +static int fwu_gpt_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
> +{
> +	return fwu_gpt_set_clear_image_accept(img_type_id, bank,
> +					      IMAGE_ACCEPT_CLEAR);
> +}
> +
> +struct fwu_mdata_ops fwu_gpt_blk_ops = {
> +	.get_active_index = fwu_gpt_get_active_index,
> +	.get_image_alt_num = fwu_gpt_get_image_alt_num,
> +	.mdata_check = fwu_gpt_mdata_check,
> +	.set_accept_image = fwu_gpt_accept_image,
> +	.clear_accept_image = fwu_gpt_clear_accept_image,
> +	.get_mdata = fwu_gpt_get_mdata,
> +	.update_mdata = fwu_gpt_update_mdata,
> +};


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

* Re: [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata
  2022-01-19 18:55 ` [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
  2022-01-20  5:53   ` Masami Hiramatsu
  2022-01-20  6:05   ` Masami Hiramatsu
@ 2022-01-20 12:18   ` Heinrich Schuchardt
  2 siblings, 0 replies; 45+ messages in thread
From: Heinrich Schuchardt @ 2022-01-20 12:18 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

On 1/19/22 19:55, Sughosh Ganu wrote:
> In the FWU Multi Bank Update feature, the information about the
> updatable images is stored as part of the metadata, which is stored on
> a dedicated partition. Add the metadata structure, and functions to
> access the metadata. These are generic API's, and implementations can
> be added based on parameters like how the metadata partition is
> accessed and what type of storage device houses the metadata.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>

I would have expected a new uclass implementing

* FFA_PARTITION_INFO_GET()

as defined in [1] and suggested by [2].

Reading the data from a partition could be implemented in one of the
drivers.

Please, have a look at
https://u-boot.readthedocs.io/en/latest/develop/driver-model/index.html

[1] Arm Firmware Framework for Arm A-profile
(https://developer.arm.com/documentation/den0077/latest)
[2] Platform Security Firmware Update for the A-profile Arm Architecture
Beta
(https://developer.arm.com/documentation/den0118/a)

Best regards

Heinrich

> ---
>
> Changes since V2:
> * Use uint*_t types in fwu_mdata.h since the file is to be reused in
>    other projects
> * Keep only the FWU metadata structures in fwu_mdata.h
> * Move all other function and macro declarations in fwu.h
> * Keep common implementations of fwu_update_active_index and
>    fwu_revert_boot_index in fwu_mdata.c
> * Add a update_mdata function pointer in the fwu_mdata_ops structure
>
>   include/fwu.h               |  61 +++++++
>   include/fwu_mdata.h         |  67 ++++++++
>   lib/fwu_updates/fwu_mdata.c | 329 ++++++++++++++++++++++++++++++++++++
>   3 files changed, 457 insertions(+)
>   create mode 100644 include/fwu.h
>   create mode 100644 include/fwu_mdata.h
>   create mode 100644 lib/fwu_updates/fwu_mdata.c
>
> diff --git a/include/fwu.h b/include/fwu.h
> new file mode 100644
> index 0000000000..acba725bc8
> --- /dev/null
> +++ b/include/fwu.h
> @@ -0,0 +1,61 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#if !defined _FWU_H_
> +#define _FWU_H_
> +
> +#include <blk.h>
> +#include <efi.h>
> +
> +#include <linux/types.h>
> +
> +struct fwu_mdata;
> +
> +/**
> + * @get_active_index: get the current active_index value
> + * @get_image_alt_num: get the alt number to be used for the image
> + * @mdata_check: check the validity of the FWU metadata partitions
> + * @set_accept_image: set the accepted bit for the image
> + * @clear_accept_image: clear the accepted bit for the image
> + * @get_mdata() - Get a FWU metadata copy
> + * @update_mdata() - Update the FWU metadata copy
> + */
> +struct fwu_mdata_ops {
> +	int (*get_active_index)(u32 *active_idx);
> +
> +	int (*get_image_alt_num)(efi_guid_t image_type_id, u32 update_bank,
> +				 int *alt_num);
> +
> +	int (*mdata_check)(void);
> +
> +	int (*set_accept_image)(efi_guid_t *img_type_id, u32 bank);
> +
> +	int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> +
> +	int (*get_mdata)(struct fwu_mdata **mdata);
> +
> +	int (*update_mdata)(struct fwu_mdata *mdata);
> +};
> +
> +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
> +
> +#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..d788eb69e7
> --- /dev/null
> +++ b/include/fwu_mdata.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2021, 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_ */
> diff --git a/lib/fwu_updates/fwu_mdata.c b/lib/fwu_updates/fwu_mdata.c
> new file mode 100644
> index 0000000000..58e838fe28
> --- /dev/null
> +++ b/lib/fwu_updates/fwu_mdata.c
> @@ -0,0 +1,329 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#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>
> +
> +static struct fwu_mdata_ops *get_fwu_mdata_ops(void)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops =  get_plat_fwu_mdata_ops();
> +	if (!ops) {
> +		log_err("Unable to get fwu ops\n");
> +		return NULL;
> +	}
> +
> +	return ops;
> +}
> +
> +/**
> + * 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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->get_active_index) {
> +		log_err("get_active_index() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->get_active_index(active_idx);
> +}
> +
> +/**
> + * 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) {
> +		printf("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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->get_image_alt_num) {
> +		log_err("get_image_alt_num() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->get_image_alt_num(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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->mdata_check) {
> +		log_err("mdata_check() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->mdata_check();
> +}
> +
> +/**
> + * 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_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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->set_accept_image) {
> +		log_err("set_accept_image() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->set_accept_image(img_type_id, bank);
> +}
> +
> +/**
> + * 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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->clear_accept_image) {
> +		log_err("clear_accept_image() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->clear_accept_image(img_type_id, bank);
> +}
> +
> +/**
> + * 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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->get_mdata) {
> +		log_err("get_mdata() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->get_mdata(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)
> +{
> +	struct fwu_mdata_ops *ops;
> +
> +	ops = get_fwu_mdata_ops();
> +	if (!ops)
> +		return -EPROTONOSUPPORT;
> +
> +	if (!ops->update_mdata) {
> +		log_err("get_mdata() method not defined for the platform\n");
> +		return -ENOSYS;
> +	}
> +
> +	return ops->update_mdata(mdata);
> +}


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

* Re: [RFC PATCH v3 4/9] FWU: STM32MP1: Add support to read boot index from backup register
  2022-01-19 18:55 ` [RFC PATCH v3 4/9] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
@ 2022-01-20 12:24   ` Heinrich Schuchardt
  0 siblings, 0 replies; 45+ messages in thread
From: Heinrich Schuchardt @ 2022-01-20 12:24 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

On 1/19/22 19:55, Sughosh Ganu wrote:
> 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 V2: None
>
>   board/st/stm32mp1/stm32mp1.c | 7 +++++++
>   include/fwu.h                | 1 +
>   2 files changed, 8 insertions(+)
>
> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> index 66cbe3f798..6e7aaaa8a4 100644
> --- a/board/st/stm32mp1/stm32mp1.c
> +++ b/board/st/stm32mp1/stm32mp1.c
> @@ -1104,6 +1104,13 @@ int fwu_plat_get_blk_desc(struct blk_desc **desc)
>   	return 0;
>   }
>
> +void fwu_plat_get_bootidx(void *boot_idx)
> +{
> +	u32 *bootidx = boot_idx;
> +
> +	*bootidx = readl(TAMP_BOOTCOUNT);
> +}
> +

Please, follow the driver model in your implementation.

https://u-boot.readthedocs.io/en/latest/develop/driver-model/index.html

Best regards

Heinrich

>   struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
>   {
>   	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> diff --git a/include/fwu.h b/include/fwu.h
> index b23a93ac40..6393a1dbb5 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -63,5 +63,6 @@ int fwu_plat_get_update_index(u32 *update_idx);
>   int fwu_plat_get_blk_desc(struct blk_desc **desc);
>   int fwu_plat_get_alt_num(void *identifier);
>   int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
> +void fwu_plat_get_bootidx(void *boot_idx);
>
>   #endif /* _FWU_H_ */


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

* Re: [RFC PATCH v3 8/9] FWU: cmd: Add a command to read FWU metadata
  2022-01-19 18:55 ` [RFC PATCH v3 8/9] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
@ 2022-01-20 12:28   ` Heinrich Schuchardt
  0 siblings, 0 replies; 45+ messages in thread
From: Heinrich Schuchardt @ 2022-01-20 12:28 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

On 1/19/22 19:55, Sughosh Ganu wrote:
> Add a command to read the metadata as specified in the FWU
> specification and print the fields of the metadata.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
>
> Changes since V2:
> * Include the log.h and stdio.h header files
>
>   cmd/Kconfig     |  7 ++++++
>   cmd/Makefile    |  1 +
>   cmd/fwu_mdata.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 75 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..81e4850442
> --- /dev/null
> +++ b/cmd/fwu_mdata.c
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#include <command.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 Read\n");

:%/ Read//

Nobody expects that this is data written.

> +	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[])
> +{
> +	int ret = CMD_RET_SUCCESS;
> +	struct fwu_mdata *mdata = NULL;
> +
> +	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",
> +	""
> +);

For any new command, please, add documentation in /doc/usage/.

Best regards

Heinrich


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

* Re: [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-20  2:13   ` AKASHI Takahiro
@ 2022-01-21  6:48     ` Sughosh Ganu
  2022-01-24  2:08       ` AKASHI Takahiro
  0 siblings, 1 reply; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-21  6:48 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

hi Takahiro,

On Thu, 20 Jan 2022 at 07:43, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Hi Sughosh,
>
> From user's point of view,
>
> On Thu, Jan 20, 2022 at 12:25:48AM +0530, Sughosh Ganu wrote:
> > The Dependable Boot specification describes the structure of the
>
> May we have a pointer or reference to it?

Okay.

>
> > 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 V2:
> > * New patch for generating empty capsules
> >
> >  tools/eficapsule.h   |   8 ++++
> >  tools/mkeficapsule.c | 102 ++++++++++++++++++++++++++++++++++++++-----
> >  2 files changed, 100 insertions(+), 10 deletions(-)
> >
> > 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..643da3849d 100644
> > --- a/tools/mkeficapsule.c
> > +++ b/tools/mkeficapsule.c
> > @@ -29,6 +29,7 @@
> >  #include "eficapsule.h"
> >
> >  static const char *tool_name = "mkeficapsule";
> > +static unsigned char 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,15 +56,23 @@ 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"
> > +     if (empty_capsule) {
> > +             fprintf(stderr, "Usage: %s [options]  <output file>\n",
> > +                     tool_name);
> > +     } else {
> > +             fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> > +                     tool_name);
> > +     }
>
> We should always show both cases regardless of "empty_capsule".
>
> Or if you have any restrictions on a combination of options,
> you'd better describe them more specifically in help message.

Yes, there are restrictions on the combination of options. I will call
a separate function, like empty_capsule_usage for these.

>
> I'd also like to encourage you to update the man page as well as uefi.rst.

Okay

>
> > +     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"
> > @@ -75,8 +84,9 @@ static void print_usage(void)
> >               "\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 +608,59 @@ 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;
> > +     int ret;
> > +     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 = NULL;
> > +     ret = -1;
> > +
> > +     f = fopen(path, "w");
> > +     if (!f) {
> > +             printf("cannot open %s\n", path);
>
> To stderr as Heinrich has requested.

I thought I saw an email from Heinrich in which he said that he did
not want a fprintf call, and was going to revert those hunks from your
patch. I will recheck this bit.

>
> > +             goto err;
> > +     }
> > +
> > +     if (fw_accept)
> > +             capsule_guid = fw_accept_guid;
> > +     else
> > +             capsule_guid = fw_revert_guid;
> > +
> > +     memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
> > +     header.header_size = sizeof(header);
> > +     header.flags = 0;
> > +
> > +     if (fw_accept) {
> > +             header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
> > +     } else {
> > +             header.capsule_image_size = sizeof(header);
> > +     }
>
> I wonder why we don't need GUID in revert case (and why need GUID
> in fw case. Since we want to add A/B update, there seems to be
> no ambiguity.

The revert capsule is used not as a rejection of a specific individual
image, but for reverting the platform to the other bank. Which does
not require a image specific GUID.

>
> > +     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
> > @@ -616,6 +679,7 @@ int main(int argc, char **argv)
> >       unsigned char uuid_buf[16];
> >       unsigned long index, instance;
> >       uint64_t mcount;
> > +     unsigned char accept_fw_capsule, revert_fw_capsule;
> >       char *privkey_file, *cert_file;
> >       int c, idx;
> >
> > @@ -625,6 +689,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 +757,38 @@ 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);
> >               }
> >       }
> >
> > +     empty_capsule = (accept_fw_capsule || revert_fw_capsule);
>
> Please check that two options are exclusive here.

Okay

>
> >       /* 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) {
> > +                     printf("Creating empty capsule failed\n");
>
> To stderr

Okay, will check.

-sughosh

>
> -Takahiro Akashi
>
> > +                     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] 45+ messages in thread

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

hi Takahiro,

On Thu, 20 Jan 2022 at 10:54, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> On Thu, Jan 20, 2022 at 12:25:44AM +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.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >
> > Changes since V2: None
> >
> >  lib/efi_loader/efi_firmware.c | 90 ++++++++++++++++++++++++++++++++---
> >  1 file changed, 83 insertions(+), 7 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > index a1b88dbfc2..648342ae72 100644
> > --- a/lib/efi_loader/efi_firmware.c
> > +++ b/lib/efi_loader/efi_firmware.c
> > @@ -10,6 +10,7 @@
> >  #include <charset.h>
> >  #include <dfu.h>
> >  #include <efi_loader.h>
> > +#include <fwu.h>
> >  #include <image.h>
> >  #include <signatures.h>
> >
> > @@ -96,6 +97,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> >       return EFI_EXIT(EFI_UNSUPPORTED);
> >  }
> >
> > +static efi_status_t fill_part_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 +145,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 +163,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 +213,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 +291,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 +306,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_part_guid_array(&efi_firmware_image_type_uboot_fit,
> > +                                &part_guid_arr);
> > +     if (ret != EFI_SUCCESS)
> > +             goto out;
>
> Why do you not call fwu_plat_fill_partition_guids() for FIT FMP driver?
> If you have a specific reason, please describe it.

The idea here was to retain the current behaviour for the non FWU use
case, where for both raw and FIT images, the same ImageTypeId is being
used. Do you want to have a weak function which fills the array with a
specific ImageTypeId value. Then, if any platform wants to have a
different implementation, they can define a function which fills the
array with relevant GUID values.

>
> > +
> >       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);
> >  }
> >
> > @@ -358,7 +407,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> >       u32 *package_version,
> >       u16 **package_version_name)
> >  {
> > +     int status;
> >       efi_status_t ret = EFI_SUCCESS;
> > +     const efi_guid_t null_guid = NULL_GUID;
> > +     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 +425,36 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> >            !descriptor_size || !package_version || !package_version_name))
> >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> >
> > +     if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > +             ret = fill_part_guid_array(&null_guid, &part_guid_arr);
> > +             if (ret != EFI_SUCCESS)
> > +                     goto out;
> > +
> > +             /*
> > +              * Call the platform function to fill the GUID array
> > +              * with the corresponding partition GUID values
> > +              */
> > +             status = fwu_plat_fill_partition_guids(&part_guid_arr);
> > +             if (status < 0) {
> > +                     log_err("Unable to get partiion guid's\n");
> > +                     ret = EFI_DEVICE_ERROR;
> > +                     goto out;
> > +             }
> > +     } else {
> > +             ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
> > +                                        &part_guid_arr);
> > +             if (ret != EFI_SUCCESS)
> > +                     goto out;
> > +     }
>
> The code:
>         ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
>                                    &part_guid_arr);
>         if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
>                 status = fwu_plat_fill_partition_guids(&part_guid_arr);
>
> would be much simpler here.

Yep, will change.

>
> But I don't know why you want to call fwu_plat_fill_partition_guids()
> only in case of CONFIG_FWU_MULTI_BANK_UPDATE. The functionality should
> be the same whether A/B update or not.

Let me know if you are okay with what I have proposed above.

-sughosh

>
> -Takahiro Akashi
>
> > +
> >       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] 45+ messages in thread

* Re: [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-20  5:31 ` [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature AKASHI Takahiro
@ 2022-01-21  7:10   ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-21  7:10 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

hi Takahiro,

On Thu, 20 Jan 2022 at 11:01, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Sughosh,
>
> On Thu, Jan 20, 2022 at 12:25:39AM +0530, Sughosh Ganu wrote:
> >
> > 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.
>
> Do you have a plan to develop any test cases for sandbox,
> especially in pytest framework?
>
> I don't see much difficulty to do so and it would be very
> helpful for U-Boot CI process.

Okay, will check on adding the test cases.

-sughosh

>
> -Takahiro Akashi
>
> > 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
> > are under review currently[3].
> >
> > These patches are based on top of the series from Takahiro to add
> > Authentication support to mkeficapsule utility[4]
> >
> > [1] - https://developer.arm.com/documentation/den0118/a
> > [2] - https://staging-git.codelinaro.org/linaro/firmware-dual-banked-updates/test
> > [3] - https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/12566
> > [4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> >
> > Changes since V2:
> > * Use uint*_t types in fwu_mdata.h since the file is to be reused in
> >   other projects
> > * Keep only the FWU metadata structures in fwu_mdata.h
> > * Move all other function and macro declarations in fwu.h
> > * Keep common implementations of fwu_update_active_index and
> >   fwu_revert_boot_index in fwu_mdata.c
> > * Add a update_mdata function pointer in the fwu_mdata_ops structure
> > * Move the function definition of fwu_verify_mdata to fwu_mdata.c to
> >   facilitate reuse
> > * Remove the block device specific desc->devnum parameter for the
> >   fwu_plat_get_alt_num function call
> > * Change the implementation of fwu_plat_get_alt_num to get the devnum
> >   in the function before calling gpt_plat_get_alt_num
> > * Add logic to delete the TrialStateCtr variable if system is not in
> >   Trial State
> > * Add logic to check if bit 15(OS Acceptance) of the Flags member in
> >   the capsule header is set
> > * Add logic to set the accept bit of all images from a capsule if the
> >   OS Acceptance bit in the capsule header is not set
> > * Include the log.h and stdio.h header files
> >
> > Sughosh Ganu (9):
> >   FWU: Add FWU metadata structure and functions for accessing metadata
> >   FWU: Add FWU metadata access functions 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
> >   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
> >
> >  board/st/stm32mp1/stm32mp1.c        | 183 ++++++++++
> >  cmd/Kconfig                         |   7 +
> >  cmd/Makefile                        |   1 +
> >  cmd/fwu_mdata.c                     |  67 ++++
> >  common/board_r.c                    |   6 +
> >  include/fwu.h                       |  81 +++++
> >  include/fwu_mdata.h                 |  69 ++++
> >  lib/Kconfig                         |   6 +
> >  lib/Makefile                        |   1 +
> >  lib/efi_loader/efi_capsule.c        | 233 ++++++++++++-
> >  lib/efi_loader/efi_firmware.c       |  90 ++++-
> >  lib/efi_loader/efi_setup.c          |   3 +-
> >  lib/fwu_updates/Kconfig             |  31 ++
> >  lib/fwu_updates/Makefile            |  11 +
> >  lib/fwu_updates/fwu.c               | 198 +++++++++++
> >  lib/fwu_updates/fwu_mdata.c         | 358 +++++++++++++++++++
> >  lib/fwu_updates/fwu_mdata_gpt_blk.c | 521 ++++++++++++++++++++++++++++
> >  tools/eficapsule.h                  |   8 +
> >  tools/mkeficapsule.c                | 102 +++++-
> >  19 files changed, 1955 insertions(+), 21 deletions(-)
> >  create mode 100644 cmd/fwu_mdata.c
> >  create mode 100644 include/fwu.h
> >  create mode 100644 include/fwu_mdata.h
> >  create mode 100644 lib/fwu_updates/Kconfig
> >  create mode 100644 lib/fwu_updates/Makefile
> >  create mode 100644 lib/fwu_updates/fwu.c
> >  create mode 100644 lib/fwu_updates/fwu_mdata.c
> >  create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c
> >
> > --
> > 2.17.1
> >
> >

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

* Re: [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-20 10:08 ` Heinrich Schuchardt
@ 2022-01-21  7:15   ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-21  7:15 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

hi Heinrich,

On Thu, 20 Jan 2022 at 15:39, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 1/19/22 19:55, Sughosh Ganu wrote:
> > 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 document "Platform Security Firmware Update for the A-profile Arm
> Architecture Beta" [1] that you relate to describes updating using FF-A
> [5] as a communication protocol between a normal world client and an
> update agent in the secure world. [1] further describes an API for this
> communication. I cannot see that you are implementing this:
>
> * U-Boot is living in the normal world, so it cannot be the update agent
> of [1].
> * Implementing the client of [1] in U-Boot would not require board
> specific changes.

This document also describes, in brief, the scenario where the
firmware store is controlled by Normal World firmware. Please check
"Normal World Controlled Firmware Store" on pg 39 of this document.
This section mentions that for such a scenario the Client is the
Update Agent.

>
> This patch set comes without any documentation update. We need a patch
> which adds documents to U-Boot describing
>
> * the design of the update mechanism
> * the usage of the update mechanism
>
> before we can start the review of the patches.

Okay. Will add some documentation for this patch series in my next version.

-sughosh

>
> Best regards
>
> Heinrich
>
> [1] Platform Security Firmware Update for the A-profile Arm Architecture
> Beta
> https://developer.arm.com/documentation/den0118/a
>
> [5] Arm Firmware Framework for Arm A-profile
> https://developer.arm.com/documentation/den0077/latest
>
> >
> > 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
> > are under review currently[3].
>   >
> > These patches are based on top of the series from Takahiro to add
> > Authentication support to mkeficapsule utility[4]
> >
> > [1] - https://developer.arm.com/documentation/den0118/a
> > [2] - https://staging-git.codelinaro.org/linaro/firmware-dual-banked-updates/test
> > [3] - https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/12566
> > [4] - https://patchwork.ozlabs.org/project/uboot/list/?series=281549
> >
> > Changes since V2:
> > * Use uint*_t types in fwu_mdata.h since the file is to be reused in
> >    other projects
> > * Keep only the FWU metadata structures in fwu_mdata.h
> > * Move all other function and macro declarations in fwu.h
> > * Keep common implementations of fwu_update_active_index and
> >    fwu_revert_boot_index in fwu_mdata.c
> > * Add a update_mdata function pointer in the fwu_mdata_ops structure
> > * Move the function definition of fwu_verify_mdata to fwu_mdata.c to
> >    facilitate reuse
> > * Remove the block device specific desc->devnum parameter for the
> >    fwu_plat_get_alt_num function call
> > * Change the implementation of fwu_plat_get_alt_num to get the devnum
> >    in the function before calling gpt_plat_get_alt_num
> > * Add logic to delete the TrialStateCtr variable if system is not in
> >    Trial State
> > * Add logic to check if bit 15(OS Acceptance) of the Flags member in
> >    the capsule header is set
> > * Add logic to set the accept bit of all images from a capsule if the
> >    OS Acceptance bit in the capsule header is not set
> > * Include the log.h and stdio.h header files
> >
> > Sughosh Ganu (9):
> >    FWU: Add FWU metadata structure and functions for accessing metadata
> >    FWU: Add FWU metadata access functions 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
> >    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
> >
> >   board/st/stm32mp1/stm32mp1.c        | 183 ++++++++++
> >   cmd/Kconfig                         |   7 +
> >   cmd/Makefile                        |   1 +
> >   cmd/fwu_mdata.c                     |  67 ++++
> >   common/board_r.c                    |   6 +
> >   include/fwu.h                       |  81 +++++
> >   include/fwu_mdata.h                 |  69 ++++
> >   lib/Kconfig                         |   6 +
> >   lib/Makefile                        |   1 +
> >   lib/efi_loader/efi_capsule.c        | 233 ++++++++++++-
> >   lib/efi_loader/efi_firmware.c       |  90 ++++-
> >   lib/efi_loader/efi_setup.c          |   3 +-
> >   lib/fwu_updates/Kconfig             |  31 ++
> >   lib/fwu_updates/Makefile            |  11 +
> >   lib/fwu_updates/fwu.c               | 198 +++++++++++
> >   lib/fwu_updates/fwu_mdata.c         | 358 +++++++++++++++++++
> >   lib/fwu_updates/fwu_mdata_gpt_blk.c | 521 ++++++++++++++++++++++++++++
> >   tools/eficapsule.h                  |   8 +
> >   tools/mkeficapsule.c                | 102 +++++-
> >   19 files changed, 1955 insertions(+), 21 deletions(-)
> >   create mode 100644 cmd/fwu_mdata.c
> >   create mode 100644 include/fwu.h
> >   create mode 100644 include/fwu_mdata.h
> >   create mode 100644 lib/fwu_updates/Kconfig
> >   create mode 100644 lib/fwu_updates/Makefile
> >   create mode 100644 lib/fwu_updates/fwu.c
> >   create mode 100644 lib/fwu_updates/fwu_mdata.c
> >   create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c
> >
>

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

* Re: [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature
  2022-01-20  6:07   ` Masami Hiramatsu
@ 2022-01-21  7:17     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-21  7:17 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Thu, 20 Jan 2022 at 11:37, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hello Sughosh,
>
> 2022年1月20日(木) 3:57 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> > 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
>
> It is clear that the FWU_MULTI_BANK_UPDATE depends on
> EFI_CAPSULE_FIRMWARE_RAW, please select it here.

I can do that, but are you sure that this functionality will not be
used for FIT images? Or do I use an imply instead of select?

-sughosh

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

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

* Re: [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-01-20 10:59   ` Heinrich Schuchardt
@ 2022-01-21 10:05     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-21 10:05 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere, u-boot

On Thu, 20 Jan 2022 at 16:29, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 1/19/22 19:55, Sughosh Ganu wrote:
> > 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>
>
> It is unclear why you are creating platform specific code here.

This is primarily code that will be dependent on the platform. For
e.g. the number of banks of firmware is a decision of the platform.
So, there is a function, fwu_plat_get_update_index which will return
the bank number which should be used for updating the firmware images.
Similarly for getting the DFU alt_num. This will depend on things like
the device that the platform uses for storing the firmware images.
There aren't too many functions defined here. I will cover this aspect
in the documentation patch which you have asked for.

>
> All of this metadata can be put into the control devicetree? If not
> create a driver class for it.

Creating a driver class for accessing the metadata seems like a decent
solution to me. I will work on this.

-sughosh

>
> Unfortunately you don't provide any design document.
>
>
> Best regards
>
> Heinrich
>
>
> > ---
> >
> > Changes since V2:
> > * Change the implementation of fwu_plat_get_alt_num to get the devnum
> >    in the function before calling gpt_plat_get_alt_num
> >
> >   board/st/stm32mp1/stm32mp1.c        | 176 ++++++++++++++++++++++++++++
> >   include/fwu.h                       |   5 +
> >   lib/fwu_updates/fwu_mdata_gpt_blk.c |   7 +-
> >   3 files changed, 185 insertions(+), 3 deletions(-)
> >
> > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> > index 84592677e4..66cbe3f798 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,174 @@ 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(void *identifier)
> > +{
> > +     int ret;
> > +     struct blk_desc *desc;
> > +
> > +     ret = fwu_plat_get_blk_desc(&desc);
> > +     if (ret < 0) {
> > +             log_err("Block device not found\n");
> > +             return -ENODEV;
> > +     }
> > +
> > +     return gpt_plat_get_alt_num(desc->devnum, identifier);
> > +}
> > +
> > +static int plat_fill_gpt_partition_guids(struct blk_desc *desc,
> > +                                      efi_guid_t **part_guid_arr)
> > +{
> > +     int i, ret = 0;
> > +     u32 part;
> > +     struct dfu_entity *dfu;
> > +     struct disk_partition info;
> > +     efi_guid_t part_type_guid;
> > +     int alt_num = dfu_get_alt_number();
> > +
> > +     dfu_init_env_entities(NULL, NULL);
> > +
> > +     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++;
> > +     }
> > +
> > +     dfu_free_entities();
> > +
> > +     return ret;
> > +}
> > +
> > +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr)
> > +{
> > +     int ret;
> > +     struct blk_desc *desc;
> > +
> > +     ret = fwu_plat_get_blk_desc(&desc);
> > +     if (ret < 0) {
> > +             log_err("Block device not found\n");
> > +             return -ENODEV;
> > +     }
> > +
> > +     return plat_fill_gpt_partition_guids(desc, part_guid_arr);
> > +}
> > +
> > +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;
> > +}
> > +
> > +int fwu_plat_get_blk_desc(struct blk_desc **desc)
> > +{
> > +     int ret;
> > +     struct mmc *mmc;
> > +     struct udevice *dev;
> > +
> > +     /*
> > +      * Initial support is being added for the DK2
> > +      * platform
> > +      */
> > +     if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> > +         (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> > +             ret = uclass_get_device(UCLASS_MMC, 0, &dev);
> > +             if (ret)
> > +                     return -1;
> > +
> > +             mmc = mmc_get_mmc_dev(dev);
> > +             if (!mmc)
> > +                     return -1;
> > +
> > +             if (mmc_init(mmc))
> > +                     return -1;
> > +
> > +             *desc = mmc_get_blk_desc(mmc);
> > +             if (!*desc)
> > +                     return -1;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
> > +{
> > +     if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> > +         (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> > +             return &fwu_gpt_blk_ops;
> > +     }
> > +
> > +     return NULL;
> > +}
> > +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
> > diff --git a/include/fwu.h b/include/fwu.h
> > index 12f7eecdb0..b23a93ac40 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -59,4 +59,9 @@ 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_blk_desc(struct blk_desc **desc);
> > +int fwu_plat_get_alt_num(void *identifier);
> > +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
> > +
> >   #endif /* _FWU_H_ */
> > diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > index cb47ddf4a7..796b08e76f 100644
> > --- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > @@ -37,6 +37,7 @@ static int gpt_get_mdata_partitions(struct blk_desc *desc,
> >       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;
> > @@ -324,7 +325,7 @@ out:
> >   int fwu_gpt_get_active_index(u32 *active_idx)
> >   {
> >       int ret;
> > -     struct fwu_mdata *mdata;
> > +     struct fwu_mdata *mdata = NULL;
> >
> >       ret = gpt_get_mdata(&mdata);
> >       if (ret < 0) {
> > @@ -355,7 +356,7 @@ static int gpt_get_image_alt_num(struct blk_desc *desc,
> >   {
> >       int ret, i;
> >       u32 part;
> > -     struct fwu_mdata *mdata;
> > +     struct fwu_mdata *mdata = NULL;
> >       struct fwu_image_entry *img_entry;
> >       struct fwu_image_bank_info *img_bank_info;
> >       struct disk_partition info;
> > @@ -459,7 +460,7 @@ static int fwu_gpt_set_clear_image_accept(efi_guid_t *img_type_id,
> >       void *buf;
> >       int ret, i;
> >       u32 nimages;
> > -     struct fwu_mdata *mdata;
> > +     struct fwu_mdata *mdata = NULL;
> >       struct fwu_image_entry *img_entry;
> >       struct fwu_image_bank_info *img_bank_info;
> >
>

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

* Re: [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-20 11:27   ` Heinrich Schuchardt
@ 2022-01-21 10:20     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-21 10:20 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: u-boot, 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 Thu, 20 Jan 2022 at 16:57, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 1/19/22 19:55, Sughosh Ganu wrote:
> > In the FWU Multi Bank Update feature, the information about the
> > updatable images is stored as part of the metadata, on a separate
> > partition. Add functions 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>
>
> Will a GPT partition remain the only place to store that information?
> Should this be implemented according to the dirver model?

Even the current implementation provides a fwu_mdata_ops structure
which contains function pointers for accessing the metadata. So there
can be multiple implementations of the access methods. I have
implemented the access methods for GPT partitioned block devices. But
it should not be very difficult to move the metadata access to driver
model. Let me know if you prefer that instead of the current
implementation.

>
> > ---
> >
> > Changes since V2:
> > * Move the function definition of fwu_verify_mdata to fwu_mdata.c to
> >    facilitate reuse
> > * Remove the block device specific desc->devnum parameter for the
> >    fwu_plat_get_alt_num function call
> >
> >   include/fwu.h                       |   1 +
> >   include/fwu_mdata.h                 |   2 +
> >   lib/fwu_updates/fwu_mdata.c         |  29 ++
> >   lib/fwu_updates/fwu_mdata_gpt_blk.c | 520 ++++++++++++++++++++++++++++
> >   4 files changed, 552 insertions(+)
> >   create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c
> >
> > diff --git a/include/fwu.h b/include/fwu.h
> > index acba725bc8..12f7eecdb0 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -53,6 +53,7 @@ int fwu_get_active_index(u32 *active_idx);
> >   int fwu_update_active_index(u32 active_idx);
> >   int fwu_get_image_alt_num(efi_guid_t image_type_id, u32 update_bank,
> >                         int *alt_num);
> > +int fwu_verify_mdata(struct fwu_mdata *mdata, bool pri_part);
> >   int fwu_mdata_check(void);
> >   int fwu_revert_boot_index(void);
> >   int fwu_accept_image(efi_guid_t *img_type_id, u32 bank);
> > diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
> > index d788eb69e7..53e39f9af6 100644
> > --- a/include/fwu_mdata.h
> > +++ b/include/fwu_mdata.h
> > @@ -64,4 +64,6 @@ struct fwu_mdata {
> >       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> >   } __attribute__((__packed__));
> >
> > +extern struct fwu_mdata_ops fwu_gpt_blk_ops;
> > +
> >   #endif /* _FWU_MDATA_H_ */
> > diff --git a/lib/fwu_updates/fwu_mdata.c b/lib/fwu_updates/fwu_mdata.c
> > index 58e838fe28..252fcf50f6 100644
> > --- a/lib/fwu_updates/fwu_mdata.c
> > +++ b/lib/fwu_updates/fwu_mdata.c
> > @@ -25,6 +25,35 @@ static struct fwu_mdata_ops *get_fwu_mdata_ops(void)
> >       return ops;
> >   }
> >
> > +/**
> > + * 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));
>
> CRC32 does not offer any security against manipulation.
> What are the security implications?

The CRC32 value I believe is used only for integrity check of the
metadata against any kind of bitflip type errors of the hardware
device which stores the metadata. The metadata itself is stored on a
non-secure storage medium.

-sughosh

>
> Best regards
>
> Heinrich
>
> > +
> > +     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
> > diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > new file mode 100644
> > index 0000000000..cb47ddf4a7
> > --- /dev/null
> > +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > @@ -0,0 +1,520 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2021, Linaro Limited
> > + */
> > +
> > +#include <blk.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 <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)
> > +
> > +#define IMAGE_ACCEPT_SET     BIT(0)
> > +#define IMAGE_ACCEPT_CLEAR   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;
> > +
> > +     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 fwu_mdata *mdata)
> > +{
> > +     int ret;
> > +     struct blk_desc *desc;
> > +     u16 primary_mpart = 0, secondary_mpart = 0;
> > +
> > +     ret = fwu_plat_get_blk_desc(&desc);
> > +     if (ret < 0) {
> > +             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 fwu_mdata **mdata)
> > +{
> > +     int ret;
> > +     struct blk_desc *desc;
> > +     u16 primary_mpart = 0, secondary_mpart = 0;
> > +
> > +     ret = fwu_plat_get_blk_desc(&desc);
> > +     if (ret < 0) {
> > +             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;
> > +     }
> > +
> > +     *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(void)
> > +{
> > +     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;
> > +
> > +     ret = fwu_plat_get_blk_desc(&desc);
> > +     if (ret < 0) {
> > +             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;
> > +}
> > +
> > +int fwu_gpt_get_active_index(u32 *active_idx)
> > +{
> > +     int ret;
> > +     struct fwu_mdata *mdata;
> > +
> > +     ret = gpt_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) {
> > +             printf("Active index value read is incorrect\n");
> > +             ret = -EINVAL;
> > +             goto out;
> > +     }
> > +
> > +out:
> > +     free(mdata);
> > +
> > +     return ret;
> > +}
> > +
> > +static int gpt_get_image_alt_num(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;
> > +     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(&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(&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(efi_guid_t image_type_id, u32 update_bank,
> > +                           int *alt_no)
> > +{
> > +     int ret;
> > +     struct blk_desc *desc;
> > +
> > +     ret = fwu_plat_get_blk_desc(&desc);
> > +     if (ret < 0) {
> > +             log_err("Block device not found\n");
> > +             return -ENODEV;
> > +     }
> > +
> > +     return gpt_get_image_alt_num(desc, image_type_id, update_bank, alt_no);
> > +}
> > +
> > +int fwu_gpt_mdata_check(void)
> > +{
> > +     /*
> > +      * 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();
> > +}
> > +
> > +int fwu_gpt_get_mdata(struct fwu_mdata **mdata)
> > +{
> > +     return gpt_get_mdata(mdata);
> > +}
> > +
> > +static int fwu_gpt_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;
> > +     struct fwu_image_entry *img_entry;
> > +     struct fwu_image_bank_info *img_bank_info;
> > +
> > +     ret = gpt_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_gpt_update_mdata(mdata);
> > +                     goto out;
> > +             }
> > +     }
> > +
> > +     /* Image not found */
> > +     ret = -EINVAL;
> > +
> > +out:
> > +     free(mdata);
> > +
> > +     return ret;
> > +}
> > +
> > +static int fwu_gpt_accept_image(efi_guid_t *img_type_id, u32 bank)
> > +{
> > +     return fwu_gpt_set_clear_image_accept(img_type_id, bank,
> > +                                           IMAGE_ACCEPT_SET);
> > +}
> > +
> > +static int fwu_gpt_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
> > +{
> > +     return fwu_gpt_set_clear_image_accept(img_type_id, bank,
> > +                                           IMAGE_ACCEPT_CLEAR);
> > +}
> > +
> > +struct fwu_mdata_ops fwu_gpt_blk_ops = {
> > +     .get_active_index = fwu_gpt_get_active_index,
> > +     .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > +     .mdata_check = fwu_gpt_mdata_check,
> > +     .set_accept_image = fwu_gpt_accept_image,
> > +     .clear_accept_image = fwu_gpt_clear_accept_image,
> > +     .get_mdata = fwu_gpt_get_mdata,
> > +     .update_mdata = fwu_gpt_update_mdata,
> > +};
>

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

* Re: [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-01-19 18:55 ` [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
  2022-01-20 10:59   ` Heinrich Schuchardt
@ 2022-01-21 11:52   ` Ilias Apalodimas
  2022-01-24  2:46   ` Masami Hiramatsu
  2 siblings, 0 replies; 45+ messages in thread
From: Ilias Apalodimas @ 2022-01-21 11:52 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh, 

[...]
>  }
>  
>  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;

And that's fine.  But can you add a pr_warn or something on this check?  So
if anyone tries to implement this on a non-sd card can get a clear
indication of what's not working?

> +
> +		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(void *identifier)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		log_err("Block device not found\n");
> +		return -ENODEV;
> +	}
> +
> +	return gpt_plat_get_alt_num(desc->devnum, identifier);
> +}
> +
> +static int plat_fill_gpt_partition_guids(struct blk_desc *desc,
> +					 efi_guid_t **part_guid_arr)
> +{
> +	int i, ret = 0;
> +	u32 part;
> +	struct dfu_entity *dfu;
> +	struct disk_partition info;
> +	efi_guid_t part_type_guid;
> +	int alt_num = dfu_get_alt_number();
> +
> +	dfu_init_env_entities(NULL, NULL);
> +
> +	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)

ditto 

> +			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++;
> +	}
> +
> +	dfu_free_entities();
> +
> +	return ret;
> +}
> +
> +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr)
> +{
> +	int ret;
> +	struct blk_desc *desc;
> +
> +	ret = fwu_plat_get_blk_desc(&desc);
> +	if (ret < 0) {
> +		log_err("Block device not found\n");
> +		return -ENODEV;
> +	}
> +
> +	return plat_fill_gpt_partition_guids(desc, part_guid_arr);
> +}
> +
> +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;
> +}
> +
> +int fwu_plat_get_blk_desc(struct blk_desc **desc)
> +{
> +	int ret;
> +	struct mmc *mmc;
> +	struct udevice *dev;
> +
> +	/*
> +	 * Initial support is being added for the DK2
> +	 * platform
> +	 */
> +	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> +	    (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> +		ret = uclass_get_device(UCLASS_MMC, 0, &dev);
> +		if (ret)
> +			return -1;
> +
> +		mmc = mmc_get_mmc_dev(dev);
> +		if (!mmc)
> +			return -1;
> +
> +		if (mmc_init(mmc))
> +			return -1;
> +
> +		*desc = mmc_get_blk_desc(mmc);
> +		if (!*desc)
> +			return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
> +{
> +	if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> +	    (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> +		return &fwu_gpt_blk_ops;
> +	}
> +
> +	return NULL;
> +}
> +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
> diff --git a/include/fwu.h b/include/fwu.h
> index 12f7eecdb0..b23a93ac40 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -59,4 +59,9 @@ 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_blk_desc(struct blk_desc **desc);
> +int fwu_plat_get_alt_num(void *identifier);
> +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
> +
>  #endif /* _FWU_H_ */
> diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> index cb47ddf4a7..796b08e76f 100644
> --- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
> +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> @@ -37,6 +37,7 @@ static int gpt_get_mdata_partitions(struct blk_desc *desc,
>  	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;
> @@ -324,7 +325,7 @@ out:
>  int fwu_gpt_get_active_index(u32 *active_idx)
>  {
>  	int ret;
> -	struct fwu_mdata *mdata;
> +	struct fwu_mdata *mdata = NULL;

Should these be part of the original patch?

>  
>  	ret = gpt_get_mdata(&mdata);
>  	if (ret < 0) {
> @@ -355,7 +356,7 @@ static int gpt_get_image_alt_num(struct blk_desc *desc,
>  {
>  	int ret, i;
>  	u32 part;
> -	struct fwu_mdata *mdata;
> +	struct fwu_mdata *mdata = NULL;
>  	struct fwu_image_entry *img_entry;
>  	struct fwu_image_bank_info *img_bank_info;
>  	struct disk_partition info;
> @@ -459,7 +460,7 @@ static int fwu_gpt_set_clear_image_accept(efi_guid_t *img_type_id,
>  	void *buf;
>  	int ret, i;
>  	u32 nimages;
> -	struct fwu_mdata *mdata;
> +	struct fwu_mdata *mdata = NULL;
>  	struct fwu_image_entry *img_entry;
>  	struct fwu_image_bank_info *img_bank_info;
>  
> -- 
> 2.17.1
> 

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

* Re: [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-19 18:55 ` [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
  2022-01-20  2:13   ` AKASHI Takahiro
@ 2022-01-21 13:00   ` Ilias Apalodimas
  2022-01-31 13:17     ` Sughosh Ganu
  1 sibling, 1 reply; 45+ messages in thread
From: Ilias Apalodimas @ 2022-01-21 13:00 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh, 

On Thu, Jan 20, 2022 at 12:25:48AM +0530, Sughosh Ganu wrote:
> 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 V2:
> * New patch for generating empty capsules
> 
>  tools/eficapsule.h   |   8 ++++
>  tools/mkeficapsule.c | 102 ++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 100 insertions(+), 10 deletions(-)
> 
> 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..643da3849d 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -29,6 +29,7 @@
>  #include "eficapsule.h"
>  
>  static const char *tool_name = "mkeficapsule";
> +static unsigned char 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,15 +56,23 @@ 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"
> +	if (empty_capsule) {
> +		fprintf(stderr, "Usage: %s [options]  <output file>\n",
> +			tool_name);
> +	} 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"
> @@ -75,8 +84,9 @@ static void print_usage(void)
>  		"\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 +608,59 @@ 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;
> +	int ret;
> +	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 = NULL;
> +	ret = -1;

Can we init those at their declaration?

> +
> +	f = fopen(path, "w");
> +	if (!f) {
> +		printf("cannot open %s\n", path);
> +		goto err;
> +	}
> +
> +	if (fw_accept)
> +		capsule_guid = fw_accept_guid;
> +	else
> +		capsule_guid = fw_revert_guid;

ternary operator would look better here.

> +
> +	memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
> +	header.header_size = sizeof(header);
> +	header.flags = 0;

Is it the flags only you need?  Or maybe memset the entire headeri to 0?
> +
> +	if (fw_accept) {
> +		header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
> +	} else {
> +		header.capsule_image_size = sizeof(header);
> +	}

ternary again?

> +
> +	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
> @@ -616,6 +679,7 @@ int main(int argc, char **argv)
>  	unsigned char uuid_buf[16];
>  	unsigned long index, instance;
>  	uint64_t mcount;
> +	unsigned char accept_fw_capsule, revert_fw_capsule;
>  	char *privkey_file, *cert_file;
>  	int c, idx;
>  
> @@ -625,6 +689,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 +757,38 @@ 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);
>  		}
>  	}
>  
> +	empty_capsule = (accept_fw_capsule || revert_fw_capsule);

Why do we need 3 variables here?
Would it be better to have an enum and just use a single variable like "is_accept_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) {
> +			printf("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
> 


Thanks
/Ilias

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

* Re: [RFC PATCH v3 6/9] FWU: Add boot time checks as highlighted by the FWU specification
  2022-01-19 18:55 ` [RFC PATCH v3 6/9] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2022-01-21 13:15   ` Ilias Apalodimas
  0 siblings, 0 replies; 45+ messages in thread
From: Ilias Apalodimas @ 2022-01-21 13:15 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh

[...]

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

That's personal preference and feel free to ignore it,  but I generally
find the code easier to read like 
if (!trial_state)
	do stuff;
	goto out;

<rest of the code follows here>

> +		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 |
> +			EFI_VARIABLE_RUNTIME_ACCESS;

Do we really need it with runtime 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);

We can't completely ignore the failed setvariable here, as it will affect
the entire code path from that point onwards.  Any checks after an update
will fail since the variable wont be there.


> +	}
> +
> +out:
> +	free(mdata);
> +	return ret;
> +}
> +
> +u8 fwu_update_checks_pass(void)
> +{
> +	return !trial_state && boottime_check;
> +}
> +
> +int fwu_boottime_checks(void)
> +{
> +	int ret;
> +	u32 boot_idx, active_idx;
> +
> +	ret = fwu_mdata_check();
> +	if (ret < 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;
> +}
> -- 

cheers
/Ilias
> 2.17.1
> 

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

* Re: [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-21  6:48     ` Sughosh Ganu
@ 2022-01-24  2:08       ` AKASHI Takahiro
  2022-01-24  2:48         ` Masami Hiramatsu
  0 siblings, 1 reply; 45+ messages in thread
From: AKASHI Takahiro @ 2022-01-24  2:08 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Fri, Jan 21, 2022 at 12:18:38PM +0530, Sughosh Ganu wrote:
> hi Takahiro,
> 
> On Thu, 20 Jan 2022 at 07:43, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > From user's point of view,
> >
> > On Thu, Jan 20, 2022 at 12:25:48AM +0530, Sughosh Ganu wrote:
> > > The Dependable Boot specification describes the structure of the
> >
> > May we have a pointer or reference to it?
> 
> Okay.
> 
> >
> > > 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 V2:
> > > * New patch for generating empty capsules
> > >
> > >  tools/eficapsule.h   |   8 ++++
> > >  tools/mkeficapsule.c | 102 ++++++++++++++++++++++++++++++++++++++-----
> > >  2 files changed, 100 insertions(+), 10 deletions(-)
> > >
> > > 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..643da3849d 100644
> > > --- a/tools/mkeficapsule.c
> > > +++ b/tools/mkeficapsule.c
> > > @@ -29,6 +29,7 @@
> > >  #include "eficapsule.h"
> > >
> > >  static const char *tool_name = "mkeficapsule";
> > > +static unsigned char 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,15 +56,23 @@ 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"
> > > +     if (empty_capsule) {
> > > +             fprintf(stderr, "Usage: %s [options]  <output file>\n",
> > > +                     tool_name);
> > > +     } else {
> > > +             fprintf(stderr, "Usage: %s [options] <image blob> <output file>\n",
> > > +                     tool_name);
> > > +     }
> >
> > We should always show both cases regardless of "empty_capsule".
> >
> > Or if you have any restrictions on a combination of options,
> > you'd better describe them more specifically in help message.
> 
> Yes, there are restrictions on the combination of options. I will call
> a separate function, like empty_capsule_usage for these.
> 
> >
> > I'd also like to encourage you to update the man page as well as uefi.rst.
> 
> Okay
> 
> >
> > > +     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"
> > > @@ -75,8 +84,9 @@ static void print_usage(void)
> > >               "\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 +608,59 @@ 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;
> > > +     int ret;
> > > +     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 = NULL;
> > > +     ret = -1;
> > > +
> > > +     f = fopen(path, "w");
> > > +     if (!f) {
> > > +             printf("cannot open %s\n", path);
> >
> > To stderr as Heinrich has requested.
> 
> I thought I saw an email from Heinrich in which he said that he did
> not want a fprintf call, and was going to revert those hunks from your
> patch. I will recheck this bit.

I think that his said comment goes only against the help message.
(I object it though.)

> >
> > > +             goto err;
> > > +     }
> > > +
> > > +     if (fw_accept)
> > > +             capsule_guid = fw_accept_guid;
> > > +     else
> > > +             capsule_guid = fw_revert_guid;
> > > +
> > > +     memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
> > > +     header.header_size = sizeof(header);
> > > +     header.flags = 0;
> > > +
> > > +     if (fw_accept) {
> > > +             header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
> > > +     } else {
> > > +             header.capsule_image_size = sizeof(header);
> > > +     }
> >
> > I wonder why we don't need GUID in revert case (and why need GUID
> > in fw case. Since we want to add A/B update, there seems to be
> > no ambiguity.
> 
> The revert capsule is used not as a rejection of a specific individual
> image, but for reverting the platform to the other bank. Which does
> not require a image specific GUID.

If so, why not apply the same rule to *accept* case to make the change
permanent?

-Takahiro Akashi

> >
> > > +     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
> > > @@ -616,6 +679,7 @@ int main(int argc, char **argv)
> > >       unsigned char uuid_buf[16];
> > >       unsigned long index, instance;
> > >       uint64_t mcount;
> > > +     unsigned char accept_fw_capsule, revert_fw_capsule;
> > >       char *privkey_file, *cert_file;
> > >       int c, idx;
> > >
> > > @@ -625,6 +689,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 +757,38 @@ 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);
> > >               }
> > >       }
> > >
> > > +     empty_capsule = (accept_fw_capsule || revert_fw_capsule);
> >
> > Please check that two options are exclusive here.
> 
> Okay
> 
> >
> > >       /* 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) {
> > > +                     printf("Creating empty capsule failed\n");
> >
> > To stderr
> 
> Okay, will check.
> 
> -sughosh
> 
> >
> > -Takahiro Akashi
> >
> > > +                     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] 45+ messages in thread

* Re: [RFC PATCH v3 5/9] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-01-21  7:02     ` Sughosh Ganu
@ 2022-01-24  2:33       ` AKASHI Takahiro
  2022-01-24  6:27         ` Sughosh Ganu
  0 siblings, 1 reply; 45+ messages in thread
From: AKASHI Takahiro @ 2022-01-24  2:33 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Fri, Jan 21, 2022 at 12:32:04PM +0530, Sughosh Ganu wrote:
> hi Takahiro,
> 
> On Thu, 20 Jan 2022 at 10:54, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > On Thu, Jan 20, 2022 at 12:25:44AM +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.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > ---
> > >
> > > Changes since V2: None
> > >
> > >  lib/efi_loader/efi_firmware.c | 90 ++++++++++++++++++++++++++++++++---
> > >  1 file changed, 83 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > index a1b88dbfc2..648342ae72 100644
> > > --- a/lib/efi_loader/efi_firmware.c
> > > +++ b/lib/efi_loader/efi_firmware.c
> > > @@ -10,6 +10,7 @@
> > >  #include <charset.h>
> > >  #include <dfu.h>
> > >  #include <efi_loader.h>
> > > +#include <fwu.h>
> > >  #include <image.h>
> > >  #include <signatures.h>
> > >
> > > @@ -96,6 +97,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > >  }
> > >
> > > +static efi_status_t fill_part_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 +145,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 +163,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 +213,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 +291,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 +306,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_part_guid_array(&efi_firmware_image_type_uboot_fit,
> > > +                                &part_guid_arr);
> > > +     if (ret != EFI_SUCCESS)
> > > +             goto out;
> >
> > Why do you not call fwu_plat_fill_partition_guids() for FIT FMP driver?
> > If you have a specific reason, please describe it.
> 
> The idea here was to retain the current behaviour for the non FWU use
> case, where for both raw and FIT images, the same ImageTypeId is being
> used.

What I meant to say was fwu_plat_fill_partition_guids() is not called
even in case of CONFIG_FWU_MULTI_BANK_UPDATE.

> Do you want to have a weak function which fills the array with a
> specific ImageTypeId value. Then, if any platform wants to have a
> different implementation, they can define a function which fills the
> array with relevant GUID values.
> 
> >
> > > +
> > >       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);
> > >  }
> > >
> > > @@ -358,7 +407,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > >       u32 *package_version,
> > >       u16 **package_version_name)
> > >  {
> > > +     int status;
> > >       efi_status_t ret = EFI_SUCCESS;
> > > +     const efi_guid_t null_guid = NULL_GUID;
> > > +     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 +425,36 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > >            !descriptor_size || !package_version || !package_version_name))
> > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > >
> > > +     if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > > +             ret = fill_part_guid_array(&null_guid, &part_guid_arr);
> > > +             if (ret != EFI_SUCCESS)
> > > +                     goto out;
> > > +
> > > +             /*
> > > +              * Call the platform function to fill the GUID array
> > > +              * with the corresponding partition GUID values
> > > +              */
> > > +             status = fwu_plat_fill_partition_guids(&part_guid_arr);
> > > +             if (status < 0) {
> > > +                     log_err("Unable to get partiion guid's\n");
> > > +                     ret = EFI_DEVICE_ERROR;
> > > +                     goto out;
> > > +             }
> > > +     } else {
> > > +             ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
> > > +                                        &part_guid_arr);
> > > +             if (ret != EFI_SUCCESS)
> > > +                     goto out;
> > > +     }
> >
> > The code:
> >         ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
> >                                    &part_guid_arr);
> >         if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
> >                 status = fwu_plat_fill_partition_guids(&part_guid_arr);
> >
> > would be much simpler here.
> 
> Yep, will change.
> 
> >
> > But I don't know why you want to call fwu_plat_fill_partition_guids()
> > only in case of CONFIG_FWU_MULTI_BANK_UPDATE. The functionality should
> > be the same whether A/B update or not.
> 
> Let me know if you are okay with what I have proposed above.

Yes. The weak "plat" function will be expected to be optimized away.

-Takahiro Akashi


> -sughosh
> 
> >
> > -Takahiro Akashi
> >
> > > +
> > >       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] 45+ messages in thread

* Re: [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-01-19 18:55 ` [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
  2022-01-20 10:59   ` Heinrich Schuchardt
  2022-01-21 11:52   ` Ilias Apalodimas
@ 2022-01-24  2:46   ` Masami Hiramatsu
  2022-01-24  7:17     ` Sughosh Ganu
  2 siblings, 1 reply; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-24  2:46 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

BTW, I can't find the definition of CONFIG_FWU_NUM_IMAGES_PER_BANK and
CONFIG_FWU_NUM_BANKS for this platform.
Is it really possible to build this platform with FWU_MULTI_BANK_UPDATE?

Thank you,

2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:

>
> 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 V2:
> * Change the implementation of fwu_plat_get_alt_num to get the devnum
>   in the function before calling gpt_plat_get_alt_num
>
>  board/st/stm32mp1/stm32mp1.c        | 176 ++++++++++++++++++++++++++++
>  include/fwu.h                       |   5 +
>  lib/fwu_updates/fwu_mdata_gpt_blk.c |   7 +-
>  3 files changed, 185 insertions(+), 3 deletions(-)
>
> diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> index 84592677e4..66cbe3f798 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,174 @@ 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(void *identifier)
> +{
> +       int ret;
> +       struct blk_desc *desc;
> +
> +       ret = fwu_plat_get_blk_desc(&desc);
> +       if (ret < 0) {
> +               log_err("Block device not found\n");
> +               return -ENODEV;
> +       }
> +
> +       return gpt_plat_get_alt_num(desc->devnum, identifier);
> +}
> +
> +static int plat_fill_gpt_partition_guids(struct blk_desc *desc,
> +                                        efi_guid_t **part_guid_arr)
> +{
> +       int i, ret = 0;
> +       u32 part;
> +       struct dfu_entity *dfu;
> +       struct disk_partition info;
> +       efi_guid_t part_type_guid;
> +       int alt_num = dfu_get_alt_number();
> +
> +       dfu_init_env_entities(NULL, NULL);
> +
> +       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++;
> +       }
> +
> +       dfu_free_entities();
> +
> +       return ret;
> +}
> +
> +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr)
> +{
> +       int ret;
> +       struct blk_desc *desc;
> +
> +       ret = fwu_plat_get_blk_desc(&desc);
> +       if (ret < 0) {
> +               log_err("Block device not found\n");
> +               return -ENODEV;
> +       }
> +
> +       return plat_fill_gpt_partition_guids(desc, part_guid_arr);
> +}
> +
> +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;
> +}
> +
> +int fwu_plat_get_blk_desc(struct blk_desc **desc)
> +{
> +       int ret;
> +       struct mmc *mmc;
> +       struct udevice *dev;
> +
> +       /*
> +        * Initial support is being added for the DK2
> +        * platform
> +        */
> +       if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> +           (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> +               ret = uclass_get_device(UCLASS_MMC, 0, &dev);
> +               if (ret)
> +                       return -1;
> +
> +               mmc = mmc_get_mmc_dev(dev);
> +               if (!mmc)
> +                       return -1;
> +
> +               if (mmc_init(mmc))
> +                       return -1;
> +
> +               *desc = mmc_get_blk_desc(mmc);
> +               if (!*desc)
> +                       return -1;
> +       }
> +
> +       return 0;
> +}
> +
> +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
> +{
> +       if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> +           (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> +               return &fwu_gpt_blk_ops;
> +       }
> +
> +       return NULL;
> +}
> +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
> diff --git a/include/fwu.h b/include/fwu.h
> index 12f7eecdb0..b23a93ac40 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -59,4 +59,9 @@ 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_blk_desc(struct blk_desc **desc);
> +int fwu_plat_get_alt_num(void *identifier);
> +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
> +
>  #endif /* _FWU_H_ */
> diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> index cb47ddf4a7..796b08e76f 100644
> --- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
> +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> @@ -37,6 +37,7 @@ static int gpt_get_mdata_partitions(struct blk_desc *desc,
>         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;
> @@ -324,7 +325,7 @@ out:
>  int fwu_gpt_get_active_index(u32 *active_idx)
>  {
>         int ret;
> -       struct fwu_mdata *mdata;
> +       struct fwu_mdata *mdata = NULL;
>
>         ret = gpt_get_mdata(&mdata);
>         if (ret < 0) {
> @@ -355,7 +356,7 @@ static int gpt_get_image_alt_num(struct blk_desc *desc,
>  {
>         int ret, i;
>         u32 part;
> -       struct fwu_mdata *mdata;
> +       struct fwu_mdata *mdata = NULL;
>         struct fwu_image_entry *img_entry;
>         struct fwu_image_bank_info *img_bank_info;
>         struct disk_partition info;
> @@ -459,7 +460,7 @@ static int fwu_gpt_set_clear_image_accept(efi_guid_t *img_type_id,
>         void *buf;
>         int ret, i;
>         u32 nimages;
> -       struct fwu_mdata *mdata;
> +       struct fwu_mdata *mdata = NULL;
>         struct fwu_image_entry *img_entry;
>         struct fwu_image_bank_info *img_bank_info;
>
> --
> 2.17.1
>


--
Masami Hiramatsu

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

* Re: [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-24  2:08       ` AKASHI Takahiro
@ 2022-01-24  2:48         ` Masami Hiramatsu
  0 siblings, 0 replies; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-24  2:48 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

Hi,

2022年1月24日(月) 11:08 AKASHI Takahiro <takahiro.akashi@linaro.org>:

> > > > +     memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
> > > > +     header.header_size = sizeof(header);
> > > > +     header.flags = 0;
> > > > +
> > > > +     if (fw_accept) {
> > > > +             header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
> > > > +     } else {
> > > > +             header.capsule_image_size = sizeof(header);
> > > > +     }
> > >
> > > I wonder why we don't need GUID in revert case (and why need GUID
> > > in fw case. Since we want to add A/B update, there seems to be
> > > no ambiguity.
> >
> > The revert capsule is used not as a rejection of a specific individual
> > image, but for reverting the platform to the other bank. Which does
> > not require a image specific GUID.
>
> If so, why not apply the same rule to *accept* case to make the change
> permanent?

Perhaps, we can make a special "acceptance" capsule file which accept
all image types. I guess originally it is considered to test each image by
the image provider and each provider decides the firmware is acceptable
or not. For example, TF-A test program passed the test but U-Boot test
program doesn't. In that case, we may need a partial acceptance flags.

However, at least the DeveloperBox has only one image type and maybe
most of platforms doesn't want to split it. Thus the acceptance image-type
uuid can be optional.

Thank you,

>
> -Takahiro Akashi
>
> > >
> > > > +     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
> > > > @@ -616,6 +679,7 @@ int main(int argc, char **argv)
> > > >       unsigned char uuid_buf[16];
> > > >       unsigned long index, instance;
> > > >       uint64_t mcount;
> > > > +     unsigned char accept_fw_capsule, revert_fw_capsule;
> > > >       char *privkey_file, *cert_file;
> > > >       int c, idx;
> > > >
> > > > @@ -625,6 +689,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 +757,38 @@ 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);
> > > >               }
> > > >       }
> > > >
> > > > +     empty_capsule = (accept_fw_capsule || revert_fw_capsule);
> > >
> > > Please check that two options are exclusive here.
> >
> > Okay
> >
> > >
> > > >       /* 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) {
> > > > +                     printf("Creating empty capsule failed\n");
> > >
> > > To stderr
> >
> > Okay, will check.
> >
> > -sughosh
> >
> > >
> > > -Takahiro Akashi
> > >
> > > > +                     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
> > > >



--
Masami Hiramatsu

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

* Re: [RFC PATCH v3 5/9] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2022-01-24  2:33       ` AKASHI Takahiro
@ 2022-01-24  6:27         ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-24  6:27 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Masami Hiramatsu,
	Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Tom Rini, Etienne Carriere

On Mon, 24 Jan 2022 at 08:03, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> On Fri, Jan 21, 2022 at 12:32:04PM +0530, Sughosh Ganu wrote:
> > hi Takahiro,
> >
> > On Thu, 20 Jan 2022 at 10:54, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > On Thu, Jan 20, 2022 at 12:25:44AM +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.
> > > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > ---
> > > >
> > > > Changes since V2: None
> > > >
> > > >  lib/efi_loader/efi_firmware.c | 90 ++++++++++++++++++++++++++++++++---
> > > >  1 file changed, 83 insertions(+), 7 deletions(-)
> > > >
> > > > diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
> > > > index a1b88dbfc2..648342ae72 100644
> > > > --- a/lib/efi_loader/efi_firmware.c
> > > > +++ b/lib/efi_loader/efi_firmware.c
> > > > @@ -10,6 +10,7 @@
> > > >  #include <charset.h>
> > > >  #include <dfu.h>
> > > >  #include <efi_loader.h>
> > > > +#include <fwu.h>
> > > >  #include <image.h>
> > > >  #include <signatures.h>
> > > >
> > > > @@ -96,6 +97,46 @@ efi_status_t EFIAPI efi_firmware_set_package_info_unsupported(
> > > >       return EFI_EXIT(EFI_UNSUPPORTED);
> > > >  }
> > > >
> > > > +static efi_status_t fill_part_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 +145,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 +163,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 +213,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 +291,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 +306,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_part_guid_array(&efi_firmware_image_type_uboot_fit,
> > > > +                                &part_guid_arr);
> > > > +     if (ret != EFI_SUCCESS)
> > > > +             goto out;
> > >
> > > Why do you not call fwu_plat_fill_partition_guids() for FIT FMP driver?
> > > If you have a specific reason, please describe it.
> >
> > The idea here was to retain the current behaviour for the non FWU use
> > case, where for both raw and FIT images, the same ImageTypeId is being
> > used.
>
> What I meant to say was fwu_plat_fill_partition_guids() is not called
> even in case of CONFIG_FWU_MULTI_BANK_UPDATE.

Ah, that is because I am testing the FWU code with the raw capsules
and not FIT. I will add a weak function. If there is FWU support added
for FIT based capsules in the future, the relevant plat function will
have to be added.

-sughosh

>
> > Do you want to have a weak function which fills the array with a
> > specific ImageTypeId value. Then, if any platform wants to have a
> > different implementation, they can define a function which fills the
> > array with relevant GUID values.
> >
> > >
> > > > +
> > > >       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);
> > > >  }
> > > >
> > > > @@ -358,7 +407,10 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > >       u32 *package_version,
> > > >       u16 **package_version_name)
> > > >  {
> > > > +     int status;
> > > >       efi_status_t ret = EFI_SUCCESS;
> > > > +     const efi_guid_t null_guid = NULL_GUID;
> > > > +     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 +425,36 @@ efi_status_t EFIAPI efi_firmware_raw_get_image_info(
> > > >            !descriptor_size || !package_version || !package_version_name))
> > > >               return EFI_EXIT(EFI_INVALID_PARAMETER);
> > > >
> > > > +     if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > > > +             ret = fill_part_guid_array(&null_guid, &part_guid_arr);
> > > > +             if (ret != EFI_SUCCESS)
> > > > +                     goto out;
> > > > +
> > > > +             /*
> > > > +              * Call the platform function to fill the GUID array
> > > > +              * with the corresponding partition GUID values
> > > > +              */
> > > > +             status = fwu_plat_fill_partition_guids(&part_guid_arr);
> > > > +             if (status < 0) {
> > > > +                     log_err("Unable to get partiion guid's\n");
> > > > +                     ret = EFI_DEVICE_ERROR;
> > > > +                     goto out;
> > > > +             }
> > > > +     } else {
> > > > +             ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
> > > > +                                        &part_guid_arr);
> > > > +             if (ret != EFI_SUCCESS)
> > > > +                     goto out;
> > > > +     }
> > >
> > > The code:
> > >         ret = fill_part_guid_array(&efi_firmware_image_type_uboot_raw,
> > >                                    &part_guid_arr);
> > >         if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE))
> > >                 status = fwu_plat_fill_partition_guids(&part_guid_arr);
> > >
> > > would be much simpler here.
> >
> > Yep, will change.
> >
> > >
> > > But I don't know why you want to call fwu_plat_fill_partition_guids()
> > > only in case of CONFIG_FWU_MULTI_BANK_UPDATE. The functionality should
> > > be the same whether A/B update or not.
> >
> > Let me know if you are okay with what I have proposed above.
>
> Yes. The weak "plat" function will be expected to be optimized away.
>
> -Takahiro Akashi
>
>
> > -sughosh
> >
> > >
> > > -Takahiro Akashi
> > >
> > > > +
> > > >       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] 45+ messages in thread

* Re: [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-20  8:43   ` Masami Hiramatsu
@ 2022-01-24  6:58     ` Sughosh Ganu
  2022-01-24  7:17       ` Masami Hiramatsu
  2022-01-24  7:38       ` AKASHI Takahiro
  0 siblings, 2 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-24  6:58 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Thu, 20 Jan 2022 at 14:13, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> 2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> > +static int fwu_gpt_update_mdata(struct fwu_mdata *mdata)
> > +{
> > +       int ret;
> > +       struct blk_desc *desc;
> > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > +
>
> I think this update_mdata() method (or fwu_update_mdata() wrapper)
> should always update mdata::crc32. calculate crc32 at each call site is
> inefficient and easy to introduce bugs.

Okay. Will do.

>
> > +       ret = fwu_plat_get_blk_desc(&desc);
> > +       if (ret < 0) {
> > +               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 fwu_mdata **mdata)
> > +{
> > +       int ret;
> > +       struct blk_desc *desc;
> > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > +
> > +       ret = fwu_plat_get_blk_desc(&desc);
> > +       if (ret < 0) {
> > +               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;
> > +       }
> > +
> > +       *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");
>
> Also, please release mdata inside the gpt_get_mdata() itself.
>
> I think it is not a good design to ask caller to free mdata if get_mdata()
> operation is failed because mdata may or may not allocated in error case.
>
> In success case, user must free it because it is allocated (user accessed it),
> and in error case, user can ignore it because it should not be allocated.
> This is simpler mind model and less memory leak chance.

I think this is confusing. It would be better to be consistent and
have the caller free up the allocated/not allocated memory. If you
check, the mdata pointer is being initialised to NULL in every
instance. Calling free with a NULL pointer is a valid case, which the
free call handles. There are multiple places in u-boot where the
caller is freeing up the allocated memory. So i think this should not
be an issue.

-sughosh

>
> Thank you,
> --
> Masami Hiramatsu

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

* Re: [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata
  2022-01-20  5:53   ` Masami Hiramatsu
@ 2022-01-24  6:59     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-24  6:59 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Thu, 20 Jan 2022 at 11:23, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hello Sughosh,
>
> 2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > 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 functions to
> > access the metadata. These are generic API's, and implementations can
> > be added based on parameters like how the metadata partition is
> > accessed and what type of storage device houses the metadata.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> >
> > Changes since V2:
> > * Use uint*_t types in fwu_mdata.h since the file is to be reused in
> >   other projects
> > * Keep only the FWU metadata structures in fwu_mdata.h
> > * Move all other function and macro declarations in fwu.h
> > * Keep common implementations of fwu_update_active_index and
> >   fwu_revert_boot_index in fwu_mdata.c
> > * Add a update_mdata function pointer in the fwu_mdata_ops structure
> >
> >  include/fwu.h               |  61 +++++++
> >  include/fwu_mdata.h         |  67 ++++++++
> >  lib/fwu_updates/fwu_mdata.c | 329 ++++++++++++++++++++++++++++++++++++
> >  3 files changed, 457 insertions(+)
> >  create mode 100644 include/fwu.h
> >  create mode 100644 include/fwu_mdata.h
> >  create mode 100644 lib/fwu_updates/fwu_mdata.c
> >
> > diff --git a/include/fwu.h b/include/fwu.h
> > new file mode 100644
> > index 0000000000..acba725bc8
> > --- /dev/null
> > +++ b/include/fwu.h
> > @@ -0,0 +1,61 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2021, Linaro Limited
> > + */
> > +
> > +#if !defined _FWU_H_
> > +#define _FWU_H_
> > +
> > +#include <blk.h>
> > +#include <efi.h>
> > +
> > +#include <linux/types.h>
> > +
> > +struct fwu_mdata;
> > +
> > +/**
> > + * @get_active_index: get the current active_index value
> > + * @get_image_alt_num: get the alt number to be used for the image
> > + * @mdata_check: check the validity of the FWU metadata partitions
> > + * @set_accept_image: set the accepted bit for the image
> > + * @clear_accept_image: clear the accepted bit for the image
> > + * @get_mdata() - Get a FWU metadata copy
> > + * @update_mdata() - Update the FWU metadata copy
> > + */
> > +struct fwu_mdata_ops {
> > +       int (*get_active_index)(u32 *active_idx);
> > +
> > +       int (*get_image_alt_num)(efi_guid_t image_type_id, u32 update_bank,
> > +                                int *alt_num);
> > +
> > +       int (*mdata_check)(void);
> > +
> > +       int (*set_accept_image)(efi_guid_t *img_type_id, u32 bank);
> > +
> > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> > +
> > +       int (*get_mdata)(struct fwu_mdata **mdata);
> > +
> > +       int (*update_mdata)(struct fwu_mdata *mdata);
> > +};
>
> We also can remove
> - get_active_index
> - set_accept_image
> - clear_accept_image
> from these operations, because those are just reading or modifying metadata.
> Such functions can be written as below
>
> ops()
> {
>    op->get_mdata(&mdata);
>    do_some_operation(mdata);
>    if (updated)
>      op->update_mdata(mdata);
> }
>
> I'll make a series of patches on top of your series for DeveloperBox,
> which does not use GPT.

I will check how these functions can be put in the common fwu_mdata.c
file. Thanks.

-sughosh

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

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

* Re: [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata
  2022-01-20  6:05   ` Masami Hiramatsu
@ 2022-01-24  7:07     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-24  7:07 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Thu, 20 Jan 2022 at 11:35, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> I have another comment on this patch.
>
> 2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> > +/**
> > + * 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) {
>
> Since active_index must be 0 .. CONFIG_FWU_NUM_BANKS - 1, it should
> cap the new active_index with "CONFIG_FWU_NUM_BANKS - 1" instead of
> "CONFIG_FWU_NUM_BANKS".

Will update the check. Thanks.

>
> > +               printf("Active index value to be updated is incorrect\n");
>
> Could you use log_err() instead of printf() for error messages?

Will do.

-sughosh

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

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

* Re: [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-24  6:58     ` Sughosh Ganu
@ 2022-01-24  7:17       ` Masami Hiramatsu
  2022-01-24  7:38       ` AKASHI Takahiro
  1 sibling, 0 replies; 45+ messages in thread
From: Masami Hiramatsu @ 2022-01-24  7:17 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

Hi Sughosh,

2022年1月24日(月) 15:58 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> hi Masami,
>
> On Thu, 20 Jan 2022 at 14:13, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > 2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > > +static int fwu_gpt_update_mdata(struct fwu_mdata *mdata)
> > > +{
> > > +       int ret;
> > > +       struct blk_desc *desc;
> > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > > +
> >
> > I think this update_mdata() method (or fwu_update_mdata() wrapper)
> > should always update mdata::crc32. calculate crc32 at each call site is
> > inefficient and easy to introduce bugs.
>
> Okay. Will do.
>
> >
> > > +       ret = fwu_plat_get_blk_desc(&desc);
> > > +       if (ret < 0) {
> > > +               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 fwu_mdata **mdata)
> > > +{
> > > +       int ret;
> > > +       struct blk_desc *desc;
> > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > > +
> > > +       ret = fwu_plat_get_blk_desc(&desc);
> > > +       if (ret < 0) {
> > > +               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;
> > > +       }
> > > +
> > > +       *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");
> >
> > Also, please release mdata inside the gpt_get_mdata() itself.
> >
> > I think it is not a good design to ask caller to free mdata if get_mdata()
> > operation is failed because mdata may or may not allocated in error case.
> >
> > In success case, user must free it because it is allocated (user accessed it),
> > and in error case, user can ignore it because it should not be allocated.
> > This is simpler mind model and less memory leak chance.
>
> I think this is confusing. It would be better to be consistent and
> have the caller free up the allocated/not allocated memory. If you
> check, the mdata pointer is being initialised to NULL in every
> instance. Calling free with a NULL pointer is a valid case, which the
> free call handles. There are multiple places in u-boot where the
> caller is freeing up the allocated memory. So i think this should not
> be an issue.

Of course it is sane. What I was that is easier to introduce mistakes.

If it requires the caller to prepare mdata = NULL as an input,
it easily causes memory leak or other issues, because it seems
not an input but just an output parameter.

My concern is that this method is not a local one, but it is directly
exported via fwu_mdata_opts. That is a problem because this means
other developers can use it. And also, it forces the other backend
driver (like my fwu_mdata_sf.c) to do so.

Thank you,

-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2022-01-24  2:46   ` Masami Hiramatsu
@ 2022-01-24  7:17     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-24  7:17 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Masami,

On Mon, 24 Jan 2022 at 08:16, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> BTW, I can't find the definition of CONFIG_FWU_NUM_IMAGES_PER_BANK and
> CONFIG_FWU_NUM_BANKS for this platform.
> Is it really possible to build this platform with FWU_MULTI_BANK_UPDATE?

Yes, I have actually tested my code :). The reason I did not add that
particular patch to this series is that the number of images per bank
and number of banks might change on a case by case basis. It is
expected that the user will set these to the values that she is using
on the platform.

-sughosh

>
> Thank you,
>
> 2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> >
> > 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 V2:
> > * Change the implementation of fwu_plat_get_alt_num to get the devnum
> >   in the function before calling gpt_plat_get_alt_num
> >
> >  board/st/stm32mp1/stm32mp1.c        | 176 ++++++++++++++++++++++++++++
> >  include/fwu.h                       |   5 +
> >  lib/fwu_updates/fwu_mdata_gpt_blk.c |   7 +-
> >  3 files changed, 185 insertions(+), 3 deletions(-)
> >
> > diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
> > index 84592677e4..66cbe3f798 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,174 @@ 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(void *identifier)
> > +{
> > +       int ret;
> > +       struct blk_desc *desc;
> > +
> > +       ret = fwu_plat_get_blk_desc(&desc);
> > +       if (ret < 0) {
> > +               log_err("Block device not found\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       return gpt_plat_get_alt_num(desc->devnum, identifier);
> > +}
> > +
> > +static int plat_fill_gpt_partition_guids(struct blk_desc *desc,
> > +                                        efi_guid_t **part_guid_arr)
> > +{
> > +       int i, ret = 0;
> > +       u32 part;
> > +       struct dfu_entity *dfu;
> > +       struct disk_partition info;
> > +       efi_guid_t part_type_guid;
> > +       int alt_num = dfu_get_alt_number();
> > +
> > +       dfu_init_env_entities(NULL, NULL);
> > +
> > +       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++;
> > +       }
> > +
> > +       dfu_free_entities();
> > +
> > +       return ret;
> > +}
> > +
> > +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr)
> > +{
> > +       int ret;
> > +       struct blk_desc *desc;
> > +
> > +       ret = fwu_plat_get_blk_desc(&desc);
> > +       if (ret < 0) {
> > +               log_err("Block device not found\n");
> > +               return -ENODEV;
> > +       }
> > +
> > +       return plat_fill_gpt_partition_guids(desc, part_guid_arr);
> > +}
> > +
> > +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;
> > +}
> > +
> > +int fwu_plat_get_blk_desc(struct blk_desc **desc)
> > +{
> > +       int ret;
> > +       struct mmc *mmc;
> > +       struct udevice *dev;
> > +
> > +       /*
> > +        * Initial support is being added for the DK2
> > +        * platform
> > +        */
> > +       if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> > +           (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> > +               ret = uclass_get_device(UCLASS_MMC, 0, &dev);
> > +               if (ret)
> > +                       return -1;
> > +
> > +               mmc = mmc_get_mmc_dev(dev);
> > +               if (!mmc)
> > +                       return -1;
> > +
> > +               if (mmc_init(mmc))
> > +                       return -1;
> > +
> > +               *desc = mmc_get_blk_desc(mmc);
> > +               if (!*desc)
> > +                       return -1;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void)
> > +{
> > +       if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
> > +           (of_machine_is_compatible("st,stm32mp157c-dk2"))) {
> > +               return &fwu_gpt_blk_ops;
> > +       }
> > +
> > +       return NULL;
> > +}
> > +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */
> > diff --git a/include/fwu.h b/include/fwu.h
> > index 12f7eecdb0..b23a93ac40 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -59,4 +59,9 @@ 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_blk_desc(struct blk_desc **desc);
> > +int fwu_plat_get_alt_num(void *identifier);
> > +int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr);
> > +
> >  #endif /* _FWU_H_ */
> > diff --git a/lib/fwu_updates/fwu_mdata_gpt_blk.c b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > index cb47ddf4a7..796b08e76f 100644
> > --- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > +++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
> > @@ -37,6 +37,7 @@ static int gpt_get_mdata_partitions(struct blk_desc *desc,
> >         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;
> > @@ -324,7 +325,7 @@ out:
> >  int fwu_gpt_get_active_index(u32 *active_idx)
> >  {
> >         int ret;
> > -       struct fwu_mdata *mdata;
> > +       struct fwu_mdata *mdata = NULL;
> >
> >         ret = gpt_get_mdata(&mdata);
> >         if (ret < 0) {
> > @@ -355,7 +356,7 @@ static int gpt_get_image_alt_num(struct blk_desc *desc,
> >  {
> >         int ret, i;
> >         u32 part;
> > -       struct fwu_mdata *mdata;
> > +       struct fwu_mdata *mdata = NULL;
> >         struct fwu_image_entry *img_entry;
> >         struct fwu_image_bank_info *img_bank_info;
> >         struct disk_partition info;
> > @@ -459,7 +460,7 @@ static int fwu_gpt_set_clear_image_accept(efi_guid_t *img_type_id,
> >         void *buf;
> >         int ret, i;
> >         u32 nimages;
> > -       struct fwu_mdata *mdata;
> > +       struct fwu_mdata *mdata = NULL;
> >         struct fwu_image_entry *img_entry;
> >         struct fwu_image_bank_info *img_bank_info;
> >
> > --
> > 2.17.1
> >
>
>
> --
> Masami Hiramatsu

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

* Re: [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2022-01-24  6:58     ` Sughosh Ganu
  2022-01-24  7:17       ` Masami Hiramatsu
@ 2022-01-24  7:38       ` AKASHI Takahiro
  1 sibling, 0 replies; 45+ messages in thread
From: AKASHI Takahiro @ 2022-01-24  7:38 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: Masami Hiramatsu, u-boot, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

On Mon, Jan 24, 2022 at 12:28:24PM +0530, Sughosh Ganu wrote:
> hi Masami,
> 
> On Thu, 20 Jan 2022 at 14:13, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > 2022年1月20日(木) 3:56 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > > +static int fwu_gpt_update_mdata(struct fwu_mdata *mdata)
> > > +{
> > > +       int ret;
> > > +       struct blk_desc *desc;
> > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > > +
> >
> > I think this update_mdata() method (or fwu_update_mdata() wrapper)
> > should always update mdata::crc32. calculate crc32 at each call site is
> > inefficient and easy to introduce bugs.
> 
> Okay. Will do.
> 
> >
> > > +       ret = fwu_plat_get_blk_desc(&desc);
> > > +       if (ret < 0) {
> > > +               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 fwu_mdata **mdata)
> > > +{
> > > +       int ret;
> > > +       struct blk_desc *desc;
> > > +       u16 primary_mpart = 0, secondary_mpart = 0;
> > > +
> > > +       ret = fwu_plat_get_blk_desc(&desc);
> > > +       if (ret < 0) {
> > > +               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;
> > > +       }
> > > +
> > > +       *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");
> >
> > Also, please release mdata inside the gpt_get_mdata() itself.
> >
> > I think it is not a good design to ask caller to free mdata if get_mdata()
> > operation is failed because mdata may or may not allocated in error case.
> >
> > In success case, user must free it because it is allocated (user accessed it),
> > and in error case, user can ignore it because it should not be allocated.
> > This is simpler mind model and less memory leak chance.
> 
> I think this is confusing. It would be better to be consistent and
> have the caller free up the allocated/not allocated memory. If you
> check, the mdata pointer is being initialised to NULL in every
> instance. Calling free with a NULL pointer is a valid case, which the
> free call handles. There are multiple places in u-boot where the
> caller is freeing up the allocated memory. So i think this should not
> be an issue.

The simple rule should be that, if the function returns 0 (successfully),
the area will be allocated. If not (i.e. returns an error), the area
will not be allocated.

This will be a much more common behavior.

-Takahiro Akashi

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

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

* Re: [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules
  2022-01-21 13:00   ` Ilias Apalodimas
@ 2022-01-31 13:17     ` Sughosh Ganu
  0 siblings, 0 replies; 45+ messages in thread
From: Sughosh Ganu @ 2022-01-31 13:17 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: u-boot, Masami Hiramatsu, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, AKASHI Takahiro,
	Simon Glass, Bin Meng, Jose Marinho, Grant Likely, Tom Rini,
	Etienne Carriere

hi Ilias,

On Fri, 21 Jan 2022 at 18:30, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Sughosh,
>
> On Thu, Jan 20, 2022 at 12:25:48AM +0530, Sughosh Ganu wrote:
> > 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 V2:
> > * New patch for generating empty capsules
> >
> >  tools/eficapsule.h   |   8 ++++
> >  tools/mkeficapsule.c | 102 ++++++++++++++++++++++++++++++++++++++-----
> >  2 files changed, 100 insertions(+), 10 deletions(-)
> >
> > 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..643da3849d 100644
> > --- a/tools/mkeficapsule.c
> > +++ b/tools/mkeficapsule.c
> > @@ -29,6 +29,7 @@
> >  #include "eficapsule.h"
> >
> >  static const char *tool_name = "mkeficapsule";
> > +static unsigned char 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,15 +56,23 @@ 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"
> > +     if (empty_capsule) {
> > +             fprintf(stderr, "Usage: %s [options]  <output file>\n",
> > +                     tool_name);
> > +     } 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"
> > @@ -75,8 +84,9 @@ static void print_usage(void)
> >               "\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 +608,59 @@ 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;
> > +     int ret;
> > +     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 = NULL;
> > +     ret = -1;
>
> Can we init those at their declaration?

Okay. I followed the initialisation style that was used in other
functions. But I can init the variables like you mention.

>
> > +
> > +     f = fopen(path, "w");
> > +     if (!f) {
> > +             printf("cannot open %s\n", path);
> > +             goto err;
> > +     }
> > +
> > +     if (fw_accept)
> > +             capsule_guid = fw_accept_guid;
> > +     else
> > +             capsule_guid = fw_revert_guid;
>
> ternary operator would look better here.

Okay

>
> > +
> > +     memcpy(&header.capsule_guid, &capsule_guid, sizeof(efi_guid_t));
> > +     header.header_size = sizeof(header);
> > +     header.flags = 0;
>
> Is it the flags only you need?  Or maybe memset the entire headeri to 0?

All members of the capsule header structure are being initialised. So
no need to memset the struct to 0.

> > +
> > +     if (fw_accept) {
> > +             header.capsule_image_size = sizeof(header) + sizeof(efi_guid_t);
> > +     } else {
> > +             header.capsule_image_size = sizeof(header);
> > +     }
>
> ternary again?

Okay

>
> > +
> > +     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
> > @@ -616,6 +679,7 @@ int main(int argc, char **argv)
> >       unsigned char uuid_buf[16];
> >       unsigned long index, instance;
> >       uint64_t mcount;
> > +     unsigned char accept_fw_capsule, revert_fw_capsule;
> >       char *privkey_file, *cert_file;
> >       int c, idx;
> >
> > @@ -625,6 +689,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 +757,38 @@ 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);
> >               }
> >       }
> >
> > +     empty_capsule = (accept_fw_capsule || revert_fw_capsule);
>
> Why do we need 3 variables here?
> Would it be better to have an enum and just use a single variable like "is_accept_capsule"?

For printing the usage, I need to differentiate between an accept
capsule and revert capsule, since they take different options. If you
don't have a strong view on this, I will keep it as is.

-sughosh

>
> > +
> >       /* 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) {
> > +                     printf("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
> >
>
>
> Thanks
> /Ilias

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

end of thread, other threads:[~2022-01-31 13:18 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-19 18:55 [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
2022-01-19 18:55 ` [RFC PATCH v3 1/9] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
2022-01-20  5:53   ` Masami Hiramatsu
2022-01-24  6:59     ` Sughosh Ganu
2022-01-20  6:05   ` Masami Hiramatsu
2022-01-24  7:07     ` Sughosh Ganu
2022-01-20 12:18   ` Heinrich Schuchardt
2022-01-19 18:55 ` [RFC PATCH v3 2/9] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
2022-01-20  8:43   ` Masami Hiramatsu
2022-01-24  6:58     ` Sughosh Ganu
2022-01-24  7:17       ` Masami Hiramatsu
2022-01-24  7:38       ` AKASHI Takahiro
2022-01-20 11:27   ` Heinrich Schuchardt
2022-01-21 10:20     ` Sughosh Ganu
2022-01-19 18:55 ` [RFC PATCH v3 3/9] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
2022-01-20 10:59   ` Heinrich Schuchardt
2022-01-21 10:05     ` Sughosh Ganu
2022-01-21 11:52   ` Ilias Apalodimas
2022-01-24  2:46   ` Masami Hiramatsu
2022-01-24  7:17     ` Sughosh Ganu
2022-01-19 18:55 ` [RFC PATCH v3 4/9] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
2022-01-20 12:24   ` Heinrich Schuchardt
2022-01-19 18:55 ` [RFC PATCH v3 5/9] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
2022-01-20  5:24   ` AKASHI Takahiro
2022-01-21  7:02     ` Sughosh Ganu
2022-01-24  2:33       ` AKASHI Takahiro
2022-01-24  6:27         ` Sughosh Ganu
2022-01-19 18:55 ` [RFC PATCH v3 6/9] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
2022-01-21 13:15   ` Ilias Apalodimas
2022-01-19 18:55 ` [RFC PATCH v3 7/9] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
2022-01-20  6:07   ` Masami Hiramatsu
2022-01-21  7:17     ` Sughosh Ganu
2022-01-19 18:55 ` [RFC PATCH v3 8/9] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
2022-01-20 12:28   ` Heinrich Schuchardt
2022-01-19 18:55 ` [RFC PATCH v3 9/9] mkeficapsule: Add support for generating empty capsules Sughosh Ganu
2022-01-20  2:13   ` AKASHI Takahiro
2022-01-21  6:48     ` Sughosh Ganu
2022-01-24  2:08       ` AKASHI Takahiro
2022-01-24  2:48         ` Masami Hiramatsu
2022-01-21 13:00   ` Ilias Apalodimas
2022-01-31 13:17     ` Sughosh Ganu
2022-01-20  5:31 ` [RFC PATCH v3 0/9] FWU: Add support for FWU Multi Bank Update feature AKASHI Takahiro
2022-01-21  7:10   ` Sughosh Ganu
2022-01-20 10:08 ` Heinrich Schuchardt
2022-01-21  7:15   ` 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.