All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature
@ 2021-12-19  7:05 Sughosh Ganu
  2021-12-19  7:05 ` [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
                   ` (7 more replies)
  0 siblings, 8 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:05 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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].

Changes since V1:
* Rename metadata with mdata for all symbols. Applicable for
  all patches
* Move all function declarations to a separate header fwu.h
* Drop the patch which added the get_gpt_hdr_parts api, as
  suggested by Patrick
* Use the logic suggested by Patrick to get the partition
  type guids and partition guid's instead of defining a new
  api
* Drop the parameter in the function fwu_revert_boot_index
  as suggested by Etienne
* Use BIT for all macros
* Call the platform function fwu_plat_get_alt_num for
  getting the alt_num for the image partition, instead of
  the earlier hard-coded approach.
* Change the logic in gpt_check_mdata_validity as suggested
  by Ilias.
* Other smaller code style changes suggested by Ilias
* Define a new function fwu_plat_get_alt_num using logic
  suggested by Patrick for returning the alt_num for the
  partition
* Define a new function plat_fill_gpt_partition_guids to
  fill the guid array with Partition Type guids
* Use the TAMP_BOOTCOUNT register as suggested by Yann
  Gautier instead of the earlier unused register 10
* Define a new function fwu_plat_get_alt_num for filling up
  all the dfu partitions with a preset ImageTypeId guid
* Remove the distinction made in the earlier version for
  setting image_type_id as suggested by Heinrich
* Define a funtion fwu_update_checks_pass to do the checks
  before initiating the update
* Log the status of the boottime checks using boottime_check
  variable and allow system to boot instead of hanging the
  platform(fwu_boottime_checks)
* Call function fwu_update_checks_pass to check if the
  update can be initiated
* Do not allow firmware update from efi_init_obj_list as the
  fwu boot-time checks need to be run

Todo's
------
1) Add a test(selftest) for the metadata access.
2) Add a tool for generation of the metadata. Not sure if this needs to
   be part of the u-boot repository though.
3) Add a tool for generation of the firmware accept/reject dummy
   capsule. Need to check if this can be added to the mkeficapsule
   tool in u-boot.

[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


Sughosh Ganu (8):
  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

 board/st/stm32mp1/stm32mp1.c        | 169 ++++++++
 cmd/Kconfig                         |   7 +
 cmd/Makefile                        |   1 +
 cmd/fwu_mdata.c                     |  64 +++
 common/board_r.c                    |   6 +
 include/fwu.h                       |  51 +++
 include/fwu_mdata.h                 | 104 +++++
 lib/Kconfig                         |  32 ++
 lib/Makefile                        |   1 +
 lib/efi_loader/efi_capsule.c        | 198 ++++++++-
 lib/efi_loader/efi_firmware.c       |  90 +++-
 lib/efi_loader/efi_setup.c          |   3 +-
 lib/fwu_updates/Makefile            |  11 +
 lib/fwu_updates/fwu.c               | 190 +++++++++
 lib/fwu_updates/fwu_mdata.c         | 236 +++++++++++
 lib/fwu_updates/fwu_mdata_gpt_blk.c | 635 ++++++++++++++++++++++++++++
 16 files changed, 1787 insertions(+), 11 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/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] 38+ messages in thread

* [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2021-12-19  7:05 ` Sughosh Ganu
  2021-12-21  0:10   ` Masami Hiramatsu
  2021-12-19  7:05 ` [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:05 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Move all function declarations to a separate header fwu.h
* Rename metadata with mdata for all symbols
* Drop the parameter in the function fwu_revert_boot_index
  as suggested by Etienne

 include/fwu.h               |  28 +++++
 include/fwu_mdata.h         | 102 ++++++++++++++++
 lib/fwu_updates/fwu_mdata.c | 236 ++++++++++++++++++++++++++++++++++++
 3 files changed, 366 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..e6bc3e6b73
--- /dev/null
+++ b/include/fwu.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#if !defined _FWU_H_
+#define _FWU_H_
+
+#include <efi.h>
+
+#include <linux/types.h>
+
+#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_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);
+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..11eb570012
--- /dev/null
+++ b/include/fwu_mdata.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#if !defined _FWU_MDATA_H_
+#define _FWU_MDATA_H_
+
+#include <efi.h>
+#include <uuid.h>
+
+#include <linux/types.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;
+	u32 accepted;
+	u32 reserved;
+};
+
+/**
+ * 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];
+};
+
+/**
+ * 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 {
+	u32 crc32;
+	u32 version;
+	u32 active_index;
+	u32 previous_active_index;
+
+	struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
+};
+
+/**
+ * @get_active_index: get the current active_index value
+ * @update_active_index: update the 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
+ * @revert_boot_index: set the active_index to previous_active_index
+ * @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
+ */
+struct fwu_mdata_ops {
+	int (*get_active_index)(u32 *active_idx);
+
+	int (*update_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 (*revert_boot_index)(void);
+
+	int (*set_accept_image)(efi_guid_t *img_type_id);
+
+	int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
+
+	int (*get_mdata)(struct fwu_mdata **mdata);
+};
+
+int fwu_get_mdata(struct fwu_mdata **mdata);
+struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
+
+#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..348e9c85f7
--- /dev/null
+++ b/lib/fwu_updates/fwu_mdata.c
@@ -0,0 +1,236 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#include <fwu_mdata.h>
+
+#include <linux/errno.h>
+#include <linux/types.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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->update_active_index) {
+		log_err("update_active_index() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->update_active_index(active_idx);
+}
+
+/**
+ * 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)
+{
+	struct fwu_mdata_ops *ops;
+
+	ops = get_fwu_mdata_ops();
+	if (!ops)
+		return -EPROTONOSUPPORT;
+
+	if (!ops->revert_boot_index) {
+		log_err("revert_boot_index() method not defined for the platform\n");
+		return -ENOSYS;
+	}
+
+	return ops->revert_boot_index();
+}
+
+/**
+ * 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
+ *
+ * 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)
+{
+	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);
+}
+
+/**
+ * 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
+ *
+ * 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);
+}
-- 
2.17.1


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

* [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2021-12-19  7:05 ` [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
@ 2021-12-19  7:05 ` Sughosh Ganu
  2021-12-24  9:59   ` Masami Hiramatsu
  2021-12-19  7:06 ` [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:05 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Rename metadata with mdata for all symbols
* Use BIT for all macros
* Use the logic suggested by Patrick to get the partition
  type guids and partition guid's instead of defining a new
  api
* Call the platform function fwu_plat_get_alt_num for
  getting the alt_num for the image partition, instead of
  the earlier hard-coded approach.
* Change the logic in gpt_check_mdata_validity as suggested
  by Ilias.
* Other smaller code style changes suggested by Ilias

 include/fwu_mdata.h                 |   2 +
 lib/fwu_updates/fwu_mdata_gpt_blk.c | 634 ++++++++++++++++++++++++++++
 2 files changed, 636 insertions(+)
 create mode 100644 lib/fwu_updates/fwu_mdata_gpt_blk.c

diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
index 11eb570012..9e24ab4047 100644
--- a/include/fwu_mdata.h
+++ b/include/fwu_mdata.h
@@ -99,4 +99,6 @@ struct fwu_mdata_ops {
 int fwu_get_mdata(struct fwu_mdata **mdata);
 struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
 
+extern struct fwu_mdata_ops fwu_gpt_blk_ops;
+
 #endif /* _FWU_MDATA_H_ */
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..2dcac0c3d4
--- /dev/null
+++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
@@ -0,0 +1,634 @@
+// 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 <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_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;
+}
+
+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 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 = gpt_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 = gpt_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 = gpt_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 = gpt_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(desc->devnum, &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_update_active_index(u32 active_idx)
+{
+	int ret;
+	void *buf;
+	struct fwu_mdata *mdata;
+
+	if (active_idx > CONFIG_FWU_NUM_BANKS) {
+		printf("Active index value to be updated is incorrect\n");
+		return -1;
+	}
+
+	ret = gpt_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 = gpt_update_mdata(mdata);
+	if (ret < 0) {
+		log_err("Failed to update FWU metadata partitions\n");
+		ret = -EIO;
+	}
+
+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);
+}
+
+int fwu_gpt_revert_boot_index(void)
+{
+	int ret;
+	void *buf;
+	u32 cur_active_index;
+	struct fwu_mdata *mdata;
+
+	ret = gpt_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 = gpt_update_mdata(mdata);
+	if (ret < 0) {
+		log_err("Failed to update FWU metadata partitions\n");
+		ret = -EIO;
+	}
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+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;
+	}
+
+	if (action == IMAGE_ACCEPT_SET)
+		bank = mdata->active_index;
+
+	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 = gpt_update_mdata(mdata);
+			goto out;
+		}
+	}
+
+	/* Image not found */
+	ret = -EINVAL;
+
+out:
+	free(mdata);
+
+	return ret;
+}
+
+int fwu_gpt_accept_image(efi_guid_t *img_type_id)
+{
+	return fwu_gpt_set_clear_image_accept(img_type_id, 0,
+					      IMAGE_ACCEPT_SET);
+}
+
+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,
+	.update_active_index = fwu_gpt_update_active_index,
+	.get_image_alt_num = fwu_gpt_get_image_alt_num,
+	.mdata_check = fwu_gpt_mdata_check,
+	.revert_boot_index = fwu_gpt_revert_boot_index,
+	.set_accept_image = fwu_gpt_accept_image,
+	.clear_accept_image = fwu_gpt_clear_accept_image,
+	.get_mdata = fwu_gpt_get_mdata,
+};
-- 
2.17.1


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

* [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2021-12-19  7:05 ` [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
  2021-12-19  7:05 ` [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
@ 2021-12-19  7:06 ` Sughosh Ganu
  2021-12-24  5:49   ` Masami Hiramatsu
  2021-12-19  7:06 ` [RFC PATCH v2 4/8] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:06 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Define a new function fwu_plat_get_alt_num using logic
  suggested by Patrick for returning the alt_num for the
  partition
* Define a new function plat_fill_gpt_partition_guids to
  fill the guid array with Partition Type guids

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

diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 84592677e4..28402fd127 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,160 @@ 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>
+
+int fwu_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;
+}
+
+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 e6bc3e6b73..1e7a1eabff 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -25,4 +25,9 @@ int fwu_revert_boot_index(void);
 int fwu_accept_image(efi_guid_t *img_type_id);
 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(int dev_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 2dcac0c3d4..6a2fa176f9 100644
--- a/lib/fwu_updates/fwu_mdata_gpt_blk.c
+++ b/lib/fwu_updates/fwu_mdata_gpt_blk.c
@@ -53,6 +53,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;
@@ -340,7 +341,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) {
@@ -371,7 +372,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;
@@ -443,7 +444,7 @@ int fwu_gpt_update_active_index(u32 active_idx)
 {
 	int ret;
 	void *buf;
-	struct fwu_mdata *mdata;
+	struct fwu_mdata *mdata = NULL;
 
 	if (active_idx > CONFIG_FWU_NUM_BANKS) {
 		printf("Active index value to be updated is incorrect\n");
@@ -523,7 +524,7 @@ int fwu_gpt_revert_boot_index(void)
 	int ret;
 	void *buf;
 	u32 cur_active_index;
-	struct fwu_mdata *mdata;
+	struct fwu_mdata *mdata = NULL;
 
 	ret = gpt_get_mdata(&mdata);
 	if (ret < 0) {
@@ -569,7 +570,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] 38+ messages in thread

* [RFC PATCH v2 4/8] FWU: STM32MP1: Add support to read boot index from backup register
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (2 preceding siblings ...)
  2021-12-19  7:06 ` [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2021-12-19  7:06 ` Sughosh Ganu
  2021-12-19  7:06 ` [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:06 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Use the TAMP_BOOTCOUNT register as suggested by Yann
  Gautier instead of the earlier unused register 10

 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 28402fd127..a8543c6410 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -1090,6 +1090,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 1e7a1eabff..5ba437798d 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -29,5 +29,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(int dev_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] 38+ messages in thread

* [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (3 preceding siblings ...)
  2021-12-19  7:06 ` [RFC PATCH v2 4/8] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
@ 2021-12-19  7:06 ` Sughosh Ganu
  2021-12-21  4:53   ` AKASHI Takahiro
  2021-12-19  7:06 ` [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:06 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Define a new function fwu_plat_get_alt_num for filling up
  all the dfu partitions with a preset ImageTypeId guid
* Remove the distinction made in the earlier version for
  setting image_type_id as suggested by Heinrich

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

* [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (4 preceding siblings ...)
  2021-12-19  7:06 ` [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
@ 2021-12-19  7:06 ` Sughosh Ganu
  2021-12-20  6:09   ` AKASHI Takahiro
  2021-12-19  7:06 ` [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2021-12-19  7:06 ` [RFC PATCH v2 8/8] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
  7 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:06 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Define a funtion fwu_update_checks_pass to do the checks
  before initiating the update
* Log the status of the boottime checks using boottime_check
  variable and allow system to boot instead of hanging the
  platform(fwu_boottime_checks)

 common/board_r.c      |   6 ++
 include/fwu.h         |   3 +
 lib/fwu_updates/fwu.c | 163 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 172 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 5ba437798d..2d2e674d6a 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -16,6 +16,9 @@
 	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_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,
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
new file mode 100644
index 0000000000..e964f9b0b1
--- /dev/null
+++ b/lib/fwu_updates/fwu.c
@@ -0,0 +1,163 @@
+// 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;
+			}
+		}
+	}
+
+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] 38+ messages in thread

* [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (5 preceding siblings ...)
  2021-12-19  7:06 ` [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2021-12-19  7:06 ` Sughosh Ganu
  2021-12-20  6:14   ` AKASHI Takahiro
  2021-12-23  0:53   ` Masami Hiramatsu
  2021-12-19  7:06 ` [RFC PATCH v2 8/8] FWU: cmd: Add a command to read FWU metadata Sughosh Ganu
  7 siblings, 2 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:06 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* Call function fwu_update_checks_pass to check if the
  update can be initiated
* Do not allow firmware update from efi_init_obj_list as the
  fwu boot-time checks need to be run

 include/fwu.h                |  18 +++-
 lib/Kconfig                  |  32 ++++++
 lib/Makefile                 |   1 +
 lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
 lib/efi_loader/efi_setup.c   |   3 +-
 lib/fwu_updates/Makefile     |  11 ++
 lib/fwu_updates/fwu.c        |  27 +++++
 7 files changed, 284 insertions(+), 6 deletions(-)
 create mode 100644 lib/fwu_updates/Makefile

diff --git a/include/fwu.h b/include/fwu.h
index 2d2e674d6a..bf50fe9277 100644
--- a/include/fwu.h
+++ b/include/fwu.h
@@ -10,14 +10,28 @@
 
 #include <linux/types.h>
 
-#define FWU_MDATA_VERSION	0x1
+#define FWU_MDATA_GUID \
+	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
+		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
+
+#define FWU_OS_REQUEST_FW_REVERT_GUID \
+	EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
+		 0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
+
+#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
+	EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
+		 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
 
 #define FWU_MDATA_GUID \
 	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
 		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
 
-int fwu_boottime_checks(void);
+#define FWU_MDATA_VERSION	0x1
+#define FWU_IMAGE_ACCEPTED	0x1
+
 u8 fwu_update_checks_pass(void);
+int fwu_boottime_checks(void);
+int fwu_trial_state_ctr_start(void);
 
 int fwu_get_active_index(u32 *active_idx);
 int fwu_update_active_index(u32 active_idx);
diff --git a/lib/Kconfig b/lib/Kconfig
index 807a4c6ade..7cb306317c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -835,3 +835,35 @@ 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.
+
+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/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..6dfe56bb0f 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,13 @@ 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;
+
+__maybe_unused static u32 update_index;
+__maybe_unused static bool capsule_update;
 
 #ifdef CONFIG_EFI_CAPSULE_ON_DISK
 /* for file system access */
@@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
 			efi_free_pool(abort_reason);
 			goto out;
 		}
+
+		if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
+			status = fwu_clear_accept_image(&image_type_id,
+							update_index);
+			if (status < 0) {
+				log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
+		}
+
 	}
 
 out:
@@ -527,6 +584,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 +598,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 +622,64 @@ 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;
+				}
+			}
+
 			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 to %u. Recommend rebooting the system\n",
+						active_idx);
+				}
+			} 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_accept_image(image_guid);
+				if (status < 0) {
+					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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -298,7 +298,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/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 e964f9b0b1..bb0e1961be 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -107,6 +107,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] 38+ messages in thread

* [RFC PATCH v2 8/8] FWU: cmd: Add a command to read FWU metadata
  2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
                   ` (6 preceding siblings ...)
  2021-12-19  7:06 ` [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2021-12-19  7:06 ` Sughosh Ganu
  7 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-19  7:06 UTC (permalink / raw)
  To: u-boot
  Cc: Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, AKASHI Takahiro, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	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 V1:
* None

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

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 5b30b13e43..ee8a976b46 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 891819ae0f..32958cba43 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..4049fb186d
--- /dev/null
+++ b/cmd/fwu_mdata.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2021, Linaro Limited
+ */
+
+#include <command.h>
+#include <fwu_mdata.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] 38+ messages in thread

* Re: [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification
  2021-12-19  7:06 ` [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
@ 2021-12-20  6:09   ` AKASHI Takahiro
  2021-12-20 10:06     ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: AKASHI Takahiro @ 2021-12-20  6:09 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Jason Liu, Tom Rini,
	Etienne Carriere

Sughosh,

On Sun, Dec 19, 2021 at 12:36:03PM +0530, Sughosh Ganu wrote:
> The FWU Multi Bank Update specification requires the Update Agent to
> carry out certain checks at the time of platform boot. The Update
> Agent is the component which is responsible for updating the firmware
> components and maintaining and keeping the metadata in sync.
> 
> The spec requires that the Update Agent perform the following checks
> at the time of boot
> * Sanity check of both the metadata copies maintained by the platform.
> * Get the boot index passed to U-Boot by the prior stage bootloader
>   and use this value for metadata bookkeeping.
> * Check if the system is booting in Trial State. If the system boots
>   in the Trial State for more than a specified number of boot counts,
>   change the Active Bank to be booting the platform from.
> 
> Add these checks in the board initialisation sequence, invoked after
> relocation.
> 
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> ---
> Changes since V1:
> * Define a funtion fwu_update_checks_pass to do the checks
>   before initiating the update
> * Log the status of the boottime checks using boottime_check
>   variable and allow system to boot instead of hanging the
>   platform(fwu_boottime_checks)
> 
>  common/board_r.c      |   6 ++
>  include/fwu.h         |   3 +
>  lib/fwu_updates/fwu.c | 163 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 172 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

Maybe I don't understand your code well.
Why do you want to call fwu_boottime_checks() here?
Why not in CONFIG_EFI_CAPSULE_UPDATE_EARLY (i.e. efi_launch_capsules()
in main_loop())?

-Takahiro Akashi

>  	run_main_loop,
>  };
> diff --git a/include/fwu.h b/include/fwu.h
> index 5ba437798d..2d2e674d6a 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -16,6 +16,9 @@
>  	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_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,
> diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> new file mode 100644
> index 0000000000..e964f9b0b1
> --- /dev/null
> +++ b/lib/fwu_updates/fwu.c
> @@ -0,0 +1,163 @@
> +// 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;
> +			}
> +		}
> +	}
> +
> +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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-19  7:06 ` [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
@ 2021-12-20  6:14   ` AKASHI Takahiro
  2021-12-20  9:48     ` Sughosh Ganu
  2021-12-23  0:53   ` Masami Hiramatsu
  1 sibling, 1 reply; 38+ messages in thread
From: AKASHI Takahiro @ 2021-12-20  6:14 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Jason Liu, Tom Rini,
	Etienne Carriere, masami.hiramatsu

On Sun, Dec 19, 2021 at 12:36:04PM +0530, Sughosh Ganu wrote:
> 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 V1:
> * Call function fwu_update_checks_pass to check if the
>   update can be initiated
> * Do not allow firmware update from efi_init_obj_list as the
>   fwu boot-time checks need to be run
> 
>  include/fwu.h                |  18 +++-
>  lib/Kconfig                  |  32 ++++++
>  lib/Makefile                 |   1 +
>  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
>  lib/efi_loader/efi_setup.c   |   3 +-
>  lib/fwu_updates/Makefile     |  11 ++
>  lib/fwu_updates/fwu.c        |  27 +++++
>  7 files changed, 284 insertions(+), 6 deletions(-)
>  create mode 100644 lib/fwu_updates/Makefile
> 
> diff --git a/include/fwu.h b/include/fwu.h
> index 2d2e674d6a..bf50fe9277 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -10,14 +10,28 @@
>  
>  #include <linux/types.h>
>  
> -#define FWU_MDATA_VERSION	0x1
> +#define FWU_MDATA_GUID \
> +	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> +		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> +
> +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> +	EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> +		 0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> +
> +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> +	EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> +		 0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
>  
>  #define FWU_MDATA_GUID \
>  	EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
>  		 0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
>  
> -int fwu_boottime_checks(void);
> +#define FWU_MDATA_VERSION	0x1
> +#define FWU_IMAGE_ACCEPTED	0x1
> +
>  u8 fwu_update_checks_pass(void);
> +int fwu_boottime_checks(void);
> +int fwu_trial_state_ctr_start(void);
>  
>  int fwu_get_active_index(u32 *active_idx);
>  int fwu_update_active_index(u32 active_idx);
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 807a4c6ade..7cb306317c 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -835,3 +835,35 @@ 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.
> +
> +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/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..6dfe56bb0f 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,13 @@ 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;
> +
> +__maybe_unused static u32 update_index;
> +__maybe_unused static bool capsule_update;
>  
>  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
>  /* for file system access */
> @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
>  			efi_free_pool(abort_reason);
>  			goto out;
>  		}
> +
> +		if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> +			status = fwu_clear_accept_image(&image_type_id,
> +							update_index);
> +			if (status < 0) {
> +				log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
> +		}
> +
>  	}
>  
>  out:
> @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> +				}
> +			}
> +
>  			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 to %u. Recommend rebooting the system\n",
> +						active_idx);
> +				}
> +			} 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_accept_image(image_guid);
> +				if (status < 0) {
> +					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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> --- a/lib/efi_loader/efi_setup.c
> +++ b/lib/efi_loader/efi_setup.c
> @@ -298,7 +298,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/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

If I understand correctly, any platform may have its own
fwu_mdata_ops. So we should not unconditionally compile in
fwu_mdata_gpt_blk.o even if CONFIG_EFI_PARTITION is enabled.

Masami must have something to say here :)

-Takahiro Akashi

> diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> index e964f9b0b1..bb0e1961be 100644
> --- a/lib/fwu_updates/fwu.c
> +++ b/lib/fwu_updates/fwu.c
> @@ -107,6 +107,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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-20  6:14   ` AKASHI Takahiro
@ 2021-12-20  9:48     ` Sughosh Ganu
  2021-12-20 13:13       ` Masami Hiramatsu
  0 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-20  9:48 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Tom Rini, Etienne Carriere,
	masami.hiramatsu

On Mon, 20 Dec 2021 at 11:44, AKASHI Takahiro <takahiro.akashi@linaro.org>
wrote:

> On Sun, Dec 19, 2021 at 12:36:04PM +0530, Sughosh Ganu wrote:
> > 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 V1:
> > * Call function fwu_update_checks_pass to check if the
> >   update can be initiated
> > * Do not allow firmware update from efi_init_obj_list as the
> >   fwu boot-time checks need to be run
> >
> >  include/fwu.h                |  18 +++-
> >  lib/Kconfig                  |  32 ++++++
> >  lib/Makefile                 |   1 +
> >  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
> >  lib/efi_loader/efi_setup.c   |   3 +-
> >  lib/fwu_updates/Makefile     |  11 ++
> >  lib/fwu_updates/fwu.c        |  27 +++++
> >  7 files changed, 284 insertions(+), 6 deletions(-)
> >  create mode 100644 lib/fwu_updates/Makefile
> >
> > diff --git a/include/fwu.h b/include/fwu.h
> > index 2d2e674d6a..bf50fe9277 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -10,14 +10,28 @@
> >
> >  #include <linux/types.h>
> >
> > -#define FWU_MDATA_VERSION    0x1
> > +#define FWU_MDATA_GUID \
> > +     EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > +              0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> > +
> > +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> > +     EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> > +              0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> > +
> > +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> > +     EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> > +              0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
> >
> >  #define FWU_MDATA_GUID \
> >       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> >                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> >
> > -int fwu_boottime_checks(void);
> > +#define FWU_MDATA_VERSION    0x1
> > +#define FWU_IMAGE_ACCEPTED   0x1
> > +
> >  u8 fwu_update_checks_pass(void);
> > +int fwu_boottime_checks(void);
> > +int fwu_trial_state_ctr_start(void);
> >
> >  int fwu_get_active_index(u32 *active_idx);
> >  int fwu_update_active_index(u32 active_idx);
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 807a4c6ade..7cb306317c 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -835,3 +835,35 @@ 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.
> > +
> > +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/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..6dfe56bb0f 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,13 @@ 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;
> > +
> > +__maybe_unused static u32 update_index;
> > +__maybe_unused static bool capsule_update;
> >
> >  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
> >  /* for file system access */
> > @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
> >                       efi_free_pool(abort_reason);
> >                       goto out;
> >               }
> > +
> > +             if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > +                     status = fwu_clear_accept_image(&image_type_id,
> > +                                                     update_index);
> > +                     if (status < 0) {
> > +                             log_err("Unable to clear the accept bit
> for the image %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("Cleared out accepted bit for Image
> %pUl\n", &image_type_id);
> > +             }
> > +
> >       }
> >
> >  out:
> > @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> > +                             }
> > +                     }
> > +
> >                       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 to %u. Recommend rebooting the system\n",
> > +                                             active_idx);
> > +                             }
> > +                     } 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_accept_image(image_guid);
> > +                             if (status < 0) {
> > +                                     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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> > --- a/lib/efi_loader/efi_setup.c
> > +++ b/lib/efi_loader/efi_setup.c
> > @@ -298,7 +298,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/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
>
> If I understand correctly, any platform may have its own
> fwu_mdata_ops. So we should not unconditionally compile in
> fwu_mdata_gpt_blk.o even if CONFIG_EFI_PARTITION is enabled.
>

I can put in an additional guard of CONFIG_BLK for building the file. Not
sure if there would be a requirement to have a platform specific set of
operations for a GPT partitioned block device. Will wait for Masami to
explain.

-sughosh



>
> Masami must have something to say here :)
>
> -Takahiro Akashi
>
> > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> > index e964f9b0b1..bb0e1961be 100644
> > --- a/lib/fwu_updates/fwu.c
> > +++ b/lib/fwu_updates/fwu.c
> > @@ -107,6 +107,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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification
  2021-12-20  6:09   ` AKASHI Takahiro
@ 2021-12-20 10:06     ` Sughosh Ganu
  2021-12-20 10:25       ` AKASHI Takahiro
  0 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-20 10:06 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Tom Rini, Etienne Carriere

hi Takahiro,

On Mon, 20 Dec 2021 at 11:39, AKASHI Takahiro <takahiro.akashi@linaro.org>
wrote:

> Sughosh,
>
> On Sun, Dec 19, 2021 at 12:36:03PM +0530, Sughosh Ganu wrote:
> > The FWU Multi Bank Update specification requires the Update Agent to
> > carry out certain checks at the time of platform boot. The Update
> > Agent is the component which is responsible for updating the firmware
> > components and maintaining and keeping the metadata in sync.
> >
> > The spec requires that the Update Agent perform the following checks
> > at the time of boot
> > * Sanity check of both the metadata copies maintained by the platform.
> > * Get the boot index passed to U-Boot by the prior stage bootloader
> >   and use this value for metadata bookkeeping.
> > * Check if the system is booting in Trial State. If the system boots
> >   in the Trial State for more than a specified number of boot counts,
> >   change the Active Bank to be booting the platform from.
> >
> > Add these checks in the board initialisation sequence, invoked after
> > relocation.
> >
> > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > ---
> > Changes since V1:
> > * Define a funtion fwu_update_checks_pass to do the checks
> >   before initiating the update
> > * Log the status of the boottime checks using boottime_check
> >   variable and allow system to boot instead of hanging the
> >   platform(fwu_boottime_checks)
> >
> >  common/board_r.c      |   6 ++
> >  include/fwu.h         |   3 +
> >  lib/fwu_updates/fwu.c | 163 ++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 172 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
>
> Maybe I don't understand your code well.
> Why do you want to call fwu_boottime_checks() here?
> Why not in CONFIG_EFI_CAPSULE_UPDATE_EARLY (i.e. efi_launch_capsules()
> in main_loop())?
>

These are boot time checks which are to be carried out during platform
boot. Do you see any issue if we place the call to fwu_boottime_checks in
the init_sequence. I would like to avoid having the fwu boot time checks
tied up with CONFIG_EFI_CAPSULE_ON_DISK_EARLY.

-sughosh


>
> -Takahiro Akashi
>
> >       run_main_loop,
> >  };
> > diff --git a/include/fwu.h b/include/fwu.h
> > index 5ba437798d..2d2e674d6a 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -16,6 +16,9 @@
> >       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_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,
> > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> > new file mode 100644
> > index 0000000000..e964f9b0b1
> > --- /dev/null
> > +++ b/lib/fwu_updates/fwu.c
> > @@ -0,0 +1,163 @@
> > +// 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;
> > +                     }
> > +             }
> > +     }
> > +
> > +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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification
  2021-12-20 10:06     ` Sughosh Ganu
@ 2021-12-20 10:25       ` AKASHI Takahiro
  2021-12-23 10:45         ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: AKASHI Takahiro @ 2021-12-20 10:25 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Jason Liu, Tom Rini,
	Etienne Carriere

Hi Sughosh,

On Mon, Dec 20, 2021 at 03:36:37PM +0530, Sughosh Ganu wrote:
> hi Takahiro,
> 
> On Mon, 20 Dec 2021 at 11:39, AKASHI Takahiro <takahiro.akashi@linaro.org>
> wrote:
> 
> > Sughosh,
> >
> > On Sun, Dec 19, 2021 at 12:36:03PM +0530, Sughosh Ganu wrote:
> > > The FWU Multi Bank Update specification requires the Update Agent to
> > > carry out certain checks at the time of platform boot. The Update
> > > Agent is the component which is responsible for updating the firmware
> > > components and maintaining and keeping the metadata in sync.
> > >
> > > The spec requires that the Update Agent perform the following checks
> > > at the time of boot
> > > * Sanity check of both the metadata copies maintained by the platform.
> > > * Get the boot index passed to U-Boot by the prior stage bootloader
> > >   and use this value for metadata bookkeeping.
> > > * Check if the system is booting in Trial State. If the system boots
> > >   in the Trial State for more than a specified number of boot counts,
> > >   change the Active Bank to be booting the platform from.
> > >
> > > Add these checks in the board initialisation sequence, invoked after
> > > relocation.
> > >
> > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > ---
> > > Changes since V1:
> > > * Define a funtion fwu_update_checks_pass to do the checks
> > >   before initiating the update
> > > * Log the status of the boottime checks using boottime_check
> > >   variable and allow system to boot instead of hanging the
> > >   platform(fwu_boottime_checks)
> > >
> > >  common/board_r.c      |   6 ++
> > >  include/fwu.h         |   3 +
> > >  lib/fwu_updates/fwu.c | 163 ++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 172 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
> >
> > Maybe I don't understand your code well.
> > Why do you want to call fwu_boottime_checks() here?
> > Why not in CONFIG_EFI_CAPSULE_UPDATE_EARLY (i.e. efi_launch_capsules()
> > in main_loop())?
> >
> 
> These are boot time checks which are to be carried out during platform
> boot. Do you see any issue if we place the call to fwu_boottime_checks in
> the init_sequence.

No, I don't see any specific issue right now.

> I would like to avoid having the fwu boot time checks
> tied up with CONFIG_EFI_CAPSULE_ON_DISK_EARLY.

My question was why you want to avoid that.
In main_loop(), update_tftp(), as well as efi capsule code, is put there.
It would be a good practice to have similar functionality called in one place.

-Takahiro Akashi


> -sughosh
> 
> 
> >
> > -Takahiro Akashi
> >
> > >       run_main_loop,
> > >  };
> > > diff --git a/include/fwu.h b/include/fwu.h
> > > index 5ba437798d..2d2e674d6a 100644
> > > --- a/include/fwu.h
> > > +++ b/include/fwu.h
> > > @@ -16,6 +16,9 @@
> > >       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_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,
> > > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> > > new file mode 100644
> > > index 0000000000..e964f9b0b1
> > > --- /dev/null
> > > +++ b/lib/fwu_updates/fwu.c
> > > @@ -0,0 +1,163 @@
> > > +// 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;
> > > +                     }
> > > +             }
> > > +     }
> > > +
> > > +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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-20  9:48     ` Sughosh Ganu
@ 2021-12-20 13:13       ` Masami Hiramatsu
  2021-12-20 16:36         ` Tom Rini
  0 siblings, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-20 13:13 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: AKASHI Takahiro, u-boot, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,

2021年12月20日(月) 18:48 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
>
> On Mon, 20 Dec 2021 at 11:44, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
>>
>> On Sun, Dec 19, 2021 at 12:36:04PM +0530, Sughosh Ganu wrote:
>> > 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 V1:
>> > * Call function fwu_update_checks_pass to check if the
>> >   update can be initiated
>> > * Do not allow firmware update from efi_init_obj_list as the
>> >   fwu boot-time checks need to be run
>> >
>> >  include/fwu.h                |  18 +++-
>> >  lib/Kconfig                  |  32 ++++++
>> >  lib/Makefile                 |   1 +
>> >  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
>> >  lib/efi_loader/efi_setup.c   |   3 +-
>> >  lib/fwu_updates/Makefile     |  11 ++
>> >  lib/fwu_updates/fwu.c        |  27 +++++
>> >  7 files changed, 284 insertions(+), 6 deletions(-)
>> >  create mode 100644 lib/fwu_updates/Makefile
>> >
>> > diff --git a/include/fwu.h b/include/fwu.h
>> > index 2d2e674d6a..bf50fe9277 100644
>> > --- a/include/fwu.h
>> > +++ b/include/fwu.h
>> > @@ -10,14 +10,28 @@
>> >
>> >  #include <linux/types.h>
>> >
>> > -#define FWU_MDATA_VERSION    0x1
>> > +#define FWU_MDATA_GUID \
>> > +     EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
>> > +              0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
>> > +
>> > +#define FWU_OS_REQUEST_FW_REVERT_GUID \
>> > +     EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
>> > +              0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
>> > +
>> > +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
>> > +     EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
>> > +              0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
>> >
>> >  #define FWU_MDATA_GUID \
>> >       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
>> >                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
>> >
>> > -int fwu_boottime_checks(void);
>> > +#define FWU_MDATA_VERSION    0x1
>> > +#define FWU_IMAGE_ACCEPTED   0x1
>> > +
>> >  u8 fwu_update_checks_pass(void);
>> > +int fwu_boottime_checks(void);
>> > +int fwu_trial_state_ctr_start(void);
>> >
>> >  int fwu_get_active_index(u32 *active_idx);
>> >  int fwu_update_active_index(u32 active_idx);
>> > diff --git a/lib/Kconfig b/lib/Kconfig
>> > index 807a4c6ade..7cb306317c 100644
>> > --- a/lib/Kconfig
>> > +++ b/lib/Kconfig
>> > @@ -835,3 +835,35 @@ 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.
>> > +
>> > +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/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..6dfe56bb0f 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,13 @@ 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;
>> > +
>> > +__maybe_unused static u32 update_index;
>> > +__maybe_unused static bool capsule_update;
>> >
>> >  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
>> >  /* for file system access */
>> > @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
>> >                       efi_free_pool(abort_reason);
>> >                       goto out;
>> >               }
>> > +
>> > +             if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
>> > +                     status = fwu_clear_accept_image(&image_type_id,
>> > +                                                     update_index);
>> > +                     if (status < 0) {
>> > +                             log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
>> > +             }
>> > +
>> >       }
>> >
>> >  out:
>> > @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
>> > +                             }
>> > +                     }
>> > +
>> >                       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 to %u. Recommend rebooting the system\n",
>> > +                                             active_idx);
>> > +                             }
>> > +                     } 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_accept_image(image_guid);
>> > +                             if (status < 0) {
>> > +                                     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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
>> > --- a/lib/efi_loader/efi_setup.c
>> > +++ b/lib/efi_loader/efi_setup.c
>> > @@ -298,7 +298,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/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
>>
>> If I understand correctly, any platform may have its own
>> fwu_mdata_ops. So we should not unconditionally compile in
>> fwu_mdata_gpt_blk.o even if CONFIG_EFI_PARTITION is enabled.
>
>
> I can put in an additional guard of CONFIG_BLK for building the file. Not sure if there would be a requirement to have a platform specific set of operations for a GPT partitioned block device. Will wait for Masami to explain.


OK, I'm trying to implement the AB update on the developerbox
platform, which doesn't have GPT, nor BLK since the firmware will be
stored on the SPI NOR flash. So I will introduce a new fwu_mdata_sf.c.
For this purpose, I introduced CONFIG_FWU_MULTI_BANK_UPDATE_SF, which
depends on CONFIG_FWU_MULTI_BANK_UPDATE and CONFIG_DM_SPI_FLASH. Thus,
I also recommend you to introduce CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK
and it should depends on CONFIG_BLK and selects CONFIG_EFI_PARTITION.

BTW, there are some code pieces which can shared with the
fwu_mdata_gpt_blk.c, for example, comparing primary and seconday
metadata and calculate the crc32.

Thank you,


>
> -sughosh
>
>
>>
>>
>> Masami must have something to say here :)
>>
>> -Takahiro Akashi
>>
>> > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
>> > index e964f9b0b1..bb0e1961be 100644
>> > --- a/lib/fwu_updates/fwu.c
>> > +++ b/lib/fwu_updates/fwu.c
>> > @@ -107,6 +107,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
>> >



-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-20 13:13       ` Masami Hiramatsu
@ 2021-12-20 16:36         ` Tom Rini
  2021-12-20 23:30           ` Masami Hiramatsu
  0 siblings, 1 reply; 38+ messages in thread
From: Tom Rini @ 2021-12-20 16:36 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Sughosh Ganu, AKASHI Takahiro, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Etienne Carriere

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

On Mon, Dec 20, 2021 at 10:13:35PM +0900, Masami Hiramatsu wrote:
> Hi Sughosh,
> 
> 2021年12月20日(月) 18:48 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> >
> > On Mon, 20 Dec 2021 at 11:44, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
> >>
> >> On Sun, Dec 19, 2021 at 12:36:04PM +0530, Sughosh Ganu wrote:
> >> > 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 V1:
> >> > * Call function fwu_update_checks_pass to check if the
> >> >   update can be initiated
> >> > * Do not allow firmware update from efi_init_obj_list as the
> >> >   fwu boot-time checks need to be run
> >> >
> >> >  include/fwu.h                |  18 +++-
> >> >  lib/Kconfig                  |  32 ++++++
> >> >  lib/Makefile                 |   1 +
> >> >  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
> >> >  lib/efi_loader/efi_setup.c   |   3 +-
> >> >  lib/fwu_updates/Makefile     |  11 ++
> >> >  lib/fwu_updates/fwu.c        |  27 +++++
> >> >  7 files changed, 284 insertions(+), 6 deletions(-)
> >> >  create mode 100644 lib/fwu_updates/Makefile
> >> >
> >> > diff --git a/include/fwu.h b/include/fwu.h
> >> > index 2d2e674d6a..bf50fe9277 100644
> >> > --- a/include/fwu.h
> >> > +++ b/include/fwu.h
> >> > @@ -10,14 +10,28 @@
> >> >
> >> >  #include <linux/types.h>
> >> >
> >> > -#define FWU_MDATA_VERSION    0x1
> >> > +#define FWU_MDATA_GUID \
> >> > +     EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> >> > +              0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> >> > +
> >> > +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> >> > +     EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> >> > +              0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> >> > +
> >> > +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> >> > +     EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> >> > +              0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
> >> >
> >> >  #define FWU_MDATA_GUID \
> >> >       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> >> >                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> >> >
> >> > -int fwu_boottime_checks(void);
> >> > +#define FWU_MDATA_VERSION    0x1
> >> > +#define FWU_IMAGE_ACCEPTED   0x1
> >> > +
> >> >  u8 fwu_update_checks_pass(void);
> >> > +int fwu_boottime_checks(void);
> >> > +int fwu_trial_state_ctr_start(void);
> >> >
> >> >  int fwu_get_active_index(u32 *active_idx);
> >> >  int fwu_update_active_index(u32 active_idx);
> >> > diff --git a/lib/Kconfig b/lib/Kconfig
> >> > index 807a4c6ade..7cb306317c 100644
> >> > --- a/lib/Kconfig
> >> > +++ b/lib/Kconfig
> >> > @@ -835,3 +835,35 @@ 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.
> >> > +
> >> > +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/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..6dfe56bb0f 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,13 @@ 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;
> >> > +
> >> > +__maybe_unused static u32 update_index;
> >> > +__maybe_unused static bool capsule_update;
> >> >
> >> >  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
> >> >  /* for file system access */
> >> > @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
> >> >                       efi_free_pool(abort_reason);
> >> >                       goto out;
> >> >               }
> >> > +
> >> > +             if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> >> > +                     status = fwu_clear_accept_image(&image_type_id,
> >> > +                                                     update_index);
> >> > +                     if (status < 0) {
> >> > +                             log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
> >> > +             }
> >> > +
> >> >       }
> >> >
> >> >  out:
> >> > @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> >> > +                             }
> >> > +                     }
> >> > +
> >> >                       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 to %u. Recommend rebooting the system\n",
> >> > +                                             active_idx);
> >> > +                             }
> >> > +                     } 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_accept_image(image_guid);
> >> > +                             if (status < 0) {
> >> > +                                     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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> >> > --- a/lib/efi_loader/efi_setup.c
> >> > +++ b/lib/efi_loader/efi_setup.c
> >> > @@ -298,7 +298,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/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
> >>
> >> If I understand correctly, any platform may have its own
> >> fwu_mdata_ops. So we should not unconditionally compile in
> >> fwu_mdata_gpt_blk.o even if CONFIG_EFI_PARTITION is enabled.
> >
> >
> > I can put in an additional guard of CONFIG_BLK for building the file. Not sure if there would be a requirement to have a platform specific set of operations for a GPT partitioned block device. Will wait for Masami to explain.
> 
> 
> OK, I'm trying to implement the AB update on the developerbox
> platform, which doesn't have GPT, nor BLK since the firmware will be
> stored on the SPI NOR flash. So I will introduce a new fwu_mdata_sf.c.
> For this purpose, I introduced CONFIG_FWU_MULTI_BANK_UPDATE_SF, which
> depends on CONFIG_FWU_MULTI_BANK_UPDATE and CONFIG_DM_SPI_FLASH. Thus,
> I also recommend you to introduce CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK
> and it should depends on CONFIG_BLK and selects CONFIG_EFI_PARTITION.
> 
> BTW, there are some code pieces which can shared with the
> fwu_mdata_gpt_blk.c, for example, comparing primary and seconday
> metadata and calculate the crc32.

Here's my concern / question.  At what level is this abstraction being
used?  I want to be sure that other SoCs, such as say a Rockchip
platform (I have a SystemReady IR certified one on the way) can re-use
this code as well but I'm sure it will need things written to different
offsets within the SPI/eMMC.  Thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-20 16:36         ` Tom Rini
@ 2021-12-20 23:30           ` Masami Hiramatsu
  2021-12-20 23:57             ` Tom Rini
  0 siblings, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-20 23:30 UTC (permalink / raw)
  To: Tom Rini
  Cc: Sughosh Ganu, AKASHI Takahiro, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Etienne Carriere

Hi Tom,

2021年12月21日(火) 1:36 Tom Rini <trini@konsulko.com>:
>
> On Mon, Dec 20, 2021 at 10:13:35PM +0900, Masami Hiramatsu wrote:
> > Hi Sughosh,
> >
> > 2021年12月20日(月) 18:48 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > >
> > >
> > > On Mon, 20 Dec 2021 at 11:44, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
> > >>
> > >> On Sun, Dec 19, 2021 at 12:36:04PM +0530, Sughosh Ganu wrote:
> > >> > 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 V1:
> > >> > * Call function fwu_update_checks_pass to check if the
> > >> >   update can be initiated
> > >> > * Do not allow firmware update from efi_init_obj_list as the
> > >> >   fwu boot-time checks need to be run
> > >> >
> > >> >  include/fwu.h                |  18 +++-
> > >> >  lib/Kconfig                  |  32 ++++++
> > >> >  lib/Makefile                 |   1 +
> > >> >  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
> > >> >  lib/efi_loader/efi_setup.c   |   3 +-
> > >> >  lib/fwu_updates/Makefile     |  11 ++
> > >> >  lib/fwu_updates/fwu.c        |  27 +++++
> > >> >  7 files changed, 284 insertions(+), 6 deletions(-)
> > >> >  create mode 100644 lib/fwu_updates/Makefile
> > >> >
> > >> > diff --git a/include/fwu.h b/include/fwu.h
> > >> > index 2d2e674d6a..bf50fe9277 100644
> > >> > --- a/include/fwu.h
> > >> > +++ b/include/fwu.h
> > >> > @@ -10,14 +10,28 @@
> > >> >
> > >> >  #include <linux/types.h>
> > >> >
> > >> > -#define FWU_MDATA_VERSION    0x1
> > >> > +#define FWU_MDATA_GUID \
> > >> > +     EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > >> > +              0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> > >> > +
> > >> > +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> > >> > +     EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> > >> > +              0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> > >> > +
> > >> > +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> > >> > +     EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> > >> > +              0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
> > >> >
> > >> >  #define FWU_MDATA_GUID \
> > >> >       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > >> >                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> > >> >
> > >> > -int fwu_boottime_checks(void);
> > >> > +#define FWU_MDATA_VERSION    0x1
> > >> > +#define FWU_IMAGE_ACCEPTED   0x1
> > >> > +
> > >> >  u8 fwu_update_checks_pass(void);
> > >> > +int fwu_boottime_checks(void);
> > >> > +int fwu_trial_state_ctr_start(void);
> > >> >
> > >> >  int fwu_get_active_index(u32 *active_idx);
> > >> >  int fwu_update_active_index(u32 active_idx);
> > >> > diff --git a/lib/Kconfig b/lib/Kconfig
> > >> > index 807a4c6ade..7cb306317c 100644
> > >> > --- a/lib/Kconfig
> > >> > +++ b/lib/Kconfig
> > >> > @@ -835,3 +835,35 @@ 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.
> > >> > +
> > >> > +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/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..6dfe56bb0f 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,13 @@ 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;
> > >> > +
> > >> > +__maybe_unused static u32 update_index;
> > >> > +__maybe_unused static bool capsule_update;
> > >> >
> > >> >  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
> > >> >  /* for file system access */
> > >> > @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
> > >> >                       efi_free_pool(abort_reason);
> > >> >                       goto out;
> > >> >               }
> > >> > +
> > >> > +             if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > >> > +                     status = fwu_clear_accept_image(&image_type_id,
> > >> > +                                                     update_index);
> > >> > +                     if (status < 0) {
> > >> > +                             log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
> > >> > +             }
> > >> > +
> > >> >       }
> > >> >
> > >> >  out:
> > >> > @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> > >> > +                             }
> > >> > +                     }
> > >> > +
> > >> >                       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 to %u. Recommend rebooting the system\n",
> > >> > +                                             active_idx);
> > >> > +                             }
> > >> > +                     } 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_accept_image(image_guid);
> > >> > +                             if (status < 0) {
> > >> > +                                     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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> > >> > --- a/lib/efi_loader/efi_setup.c
> > >> > +++ b/lib/efi_loader/efi_setup.c
> > >> > @@ -298,7 +298,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/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
> > >>
> > >> If I understand correctly, any platform may have its own
> > >> fwu_mdata_ops. So we should not unconditionally compile in
> > >> fwu_mdata_gpt_blk.o even if CONFIG_EFI_PARTITION is enabled.
> > >
> > >
> > > I can put in an additional guard of CONFIG_BLK for building the file. Not sure if there would be a requirement to have a platform specific set of operations for a GPT partitioned block device. Will wait for Masami to explain.
> >
> >
> > OK, I'm trying to implement the AB update on the developerbox
> > platform, which doesn't have GPT, nor BLK since the firmware will be
> > stored on the SPI NOR flash. So I will introduce a new fwu_mdata_sf.c.
> > For this purpose, I introduced CONFIG_FWU_MULTI_BANK_UPDATE_SF, which
> > depends on CONFIG_FWU_MULTI_BANK_UPDATE and CONFIG_DM_SPI_FLASH. Thus,
> > I also recommend you to introduce CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK
> > and it should depends on CONFIG_BLK and selects CONFIG_EFI_PARTITION.
> >
> > BTW, there are some code pieces which can shared with the
> > fwu_mdata_gpt_blk.c, for example, comparing primary and seconday
> > metadata and calculate the crc32.
>
> Here's my concern / question.  At what level is this abstraction being
> used?  I want to be sure that other SoCs, such as say a Rockchip
> platform (I have a SystemReady IR certified one on the way) can re-use
> this code as well but I'm sure it will need things written to different
> offsets within the SPI/eMMC.  Thanks!

For the metadata, I introduced CONFIG_FWU_SF_PRIMARY_METADATA_OFFSET
and CONFIG_FWU_SF_PRIMARY_METADATA_OFFSET for configuring offset of
the metadata on SPI Flash for my prototype code.
I think it might be better to introduce accessors for the metadata,
e.g. fwu_load_pri_mdata()/fwu_save_sec_mdata() etc. so that the
platform can choose the media which stores metadata independent from
the firmware storage.

For the firmware offset, it is defined in the dfu_alt_info, so you can
use (or even mix) any storage media like SPI nor or MTD or eMMC.

Thank you,


>
> --
> Tom



-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-20 23:30           ` Masami Hiramatsu
@ 2021-12-20 23:57             ` Tom Rini
  0 siblings, 0 replies; 38+ messages in thread
From: Tom Rini @ 2021-12-20 23:57 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Sughosh Ganu, AKASHI Takahiro, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Etienne Carriere

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

On Tue, Dec 21, 2021 at 08:30:02AM +0900, Masami Hiramatsu wrote:
> Hi Tom,
> 
> 2021年12月21日(火) 1:36 Tom Rini <trini@konsulko.com>:
> >
> > On Mon, Dec 20, 2021 at 10:13:35PM +0900, Masami Hiramatsu wrote:
> > > Hi Sughosh,
> > >
> > > 2021年12月20日(月) 18:48 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > > >
> > > >
> > > > On Mon, 20 Dec 2021 at 11:44, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
> > > >>
> > > >> On Sun, Dec 19, 2021 at 12:36:04PM +0530, Sughosh Ganu wrote:
> > > >> > 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 V1:
> > > >> > * Call function fwu_update_checks_pass to check if the
> > > >> >   update can be initiated
> > > >> > * Do not allow firmware update from efi_init_obj_list as the
> > > >> >   fwu boot-time checks need to be run
> > > >> >
> > > >> >  include/fwu.h                |  18 +++-
> > > >> >  lib/Kconfig                  |  32 ++++++
> > > >> >  lib/Makefile                 |   1 +
> > > >> >  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
> > > >> >  lib/efi_loader/efi_setup.c   |   3 +-
> > > >> >  lib/fwu_updates/Makefile     |  11 ++
> > > >> >  lib/fwu_updates/fwu.c        |  27 +++++
> > > >> >  7 files changed, 284 insertions(+), 6 deletions(-)
> > > >> >  create mode 100644 lib/fwu_updates/Makefile
> > > >> >
> > > >> > diff --git a/include/fwu.h b/include/fwu.h
> > > >> > index 2d2e674d6a..bf50fe9277 100644
> > > >> > --- a/include/fwu.h
> > > >> > +++ b/include/fwu.h
> > > >> > @@ -10,14 +10,28 @@
> > > >> >
> > > >> >  #include <linux/types.h>
> > > >> >
> > > >> > -#define FWU_MDATA_VERSION    0x1
> > > >> > +#define FWU_MDATA_GUID \
> > > >> > +     EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > > >> > +              0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> > > >> > +
> > > >> > +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> > > >> > +     EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> > > >> > +              0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> > > >> > +
> > > >> > +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> > > >> > +     EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> > > >> > +              0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
> > > >> >
> > > >> >  #define FWU_MDATA_GUID \
> > > >> >       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > > >> >                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> > > >> >
> > > >> > -int fwu_boottime_checks(void);
> > > >> > +#define FWU_MDATA_VERSION    0x1
> > > >> > +#define FWU_IMAGE_ACCEPTED   0x1
> > > >> > +
> > > >> >  u8 fwu_update_checks_pass(void);
> > > >> > +int fwu_boottime_checks(void);
> > > >> > +int fwu_trial_state_ctr_start(void);
> > > >> >
> > > >> >  int fwu_get_active_index(u32 *active_idx);
> > > >> >  int fwu_update_active_index(u32 active_idx);
> > > >> > diff --git a/lib/Kconfig b/lib/Kconfig
> > > >> > index 807a4c6ade..7cb306317c 100644
> > > >> > --- a/lib/Kconfig
> > > >> > +++ b/lib/Kconfig
> > > >> > @@ -835,3 +835,35 @@ 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.
> > > >> > +
> > > >> > +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/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..6dfe56bb0f 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,13 @@ 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;
> > > >> > +
> > > >> > +__maybe_unused static u32 update_index;
> > > >> > +__maybe_unused static bool capsule_update;
> > > >> >
> > > >> >  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
> > > >> >  /* for file system access */
> > > >> > @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
> > > >> >                       efi_free_pool(abort_reason);
> > > >> >                       goto out;
> > > >> >               }
> > > >> > +
> > > >> > +             if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > > >> > +                     status = fwu_clear_accept_image(&image_type_id,
> > > >> > +                                                     update_index);
> > > >> > +                     if (status < 0) {
> > > >> > +                             log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
> > > >> > +             }
> > > >> > +
> > > >> >       }
> > > >> >
> > > >> >  out:
> > > >> > @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> > > >> > +                             }
> > > >> > +                     }
> > > >> > +
> > > >> >                       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 to %u. Recommend rebooting the system\n",
> > > >> > +                                             active_idx);
> > > >> > +                             }
> > > >> > +                     } 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_accept_image(image_guid);
> > > >> > +                             if (status < 0) {
> > > >> > +                                     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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> > > >> > --- a/lib/efi_loader/efi_setup.c
> > > >> > +++ b/lib/efi_loader/efi_setup.c
> > > >> > @@ -298,7 +298,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/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
> > > >>
> > > >> If I understand correctly, any platform may have its own
> > > >> fwu_mdata_ops. So we should not unconditionally compile in
> > > >> fwu_mdata_gpt_blk.o even if CONFIG_EFI_PARTITION is enabled.
> > > >
> > > >
> > > > I can put in an additional guard of CONFIG_BLK for building the file. Not sure if there would be a requirement to have a platform specific set of operations for a GPT partitioned block device. Will wait for Masami to explain.
> > >
> > >
> > > OK, I'm trying to implement the AB update on the developerbox
> > > platform, which doesn't have GPT, nor BLK since the firmware will be
> > > stored on the SPI NOR flash. So I will introduce a new fwu_mdata_sf.c.
> > > For this purpose, I introduced CONFIG_FWU_MULTI_BANK_UPDATE_SF, which
> > > depends on CONFIG_FWU_MULTI_BANK_UPDATE and CONFIG_DM_SPI_FLASH. Thus,
> > > I also recommend you to introduce CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK
> > > and it should depends on CONFIG_BLK and selects CONFIG_EFI_PARTITION.
> > >
> > > BTW, there are some code pieces which can shared with the
> > > fwu_mdata_gpt_blk.c, for example, comparing primary and seconday
> > > metadata and calculate the crc32.
> >
> > Here's my concern / question.  At what level is this abstraction being
> > used?  I want to be sure that other SoCs, such as say a Rockchip
> > platform (I have a SystemReady IR certified one on the way) can re-use
> > this code as well but I'm sure it will need things written to different
> > offsets within the SPI/eMMC.  Thanks!
> 
> For the metadata, I introduced CONFIG_FWU_SF_PRIMARY_METADATA_OFFSET
> and CONFIG_FWU_SF_PRIMARY_METADATA_OFFSET for configuring offset of
> the metadata on SPI Flash for my prototype code.
> I think it might be better to introduce accessors for the metadata,
> e.g. fwu_load_pri_mdata()/fwu_save_sec_mdata() etc. so that the
> platform can choose the media which stores metadata independent from
> the firmware storage.
> 
> For the firmware offset, it is defined in the dfu_alt_info, so you can
> use (or even mix) any storage media like SPI nor or MTD or eMMC.

OK, good so you're keeping it in mind.  Is there any chance we can get a
second platform supported as part of the series itself, to confirm it's
sufficient?  I always worry a bit about things that are supposed to be
abstract enough to support anything but only implemented once.  Thanks!

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-19  7:05 ` [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
@ 2021-12-21  0:10   ` Masami Hiramatsu
  2021-12-21  4:35     ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-21  0:10 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, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,

2021年12月19日(日) 16:06 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 V1:
> * Move all function declarations to a separate header fwu.h
> * Rename metadata with mdata for all symbols
> * Drop the parameter in the function fwu_revert_boot_index
>   as suggested by Etienne
>
>  include/fwu.h               |  28 +++++
>  include/fwu_mdata.h         | 102 ++++++++++++++++
>  lib/fwu_updates/fwu_mdata.c | 236 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 366 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..e6bc3e6b73
> --- /dev/null
> +++ b/include/fwu.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#if !defined _FWU_H_
> +#define _FWU_H_
> +
> +#include <efi.h>
> +
> +#include <linux/types.h>
> +
> +#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_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);
> +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..11eb570012
> --- /dev/null
> +++ b/include/fwu_mdata.h
> @@ -0,0 +1,102 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#if !defined _FWU_MDATA_H_
> +#define _FWU_MDATA_H_
> +
> +#include <efi.h>
> +#include <uuid.h>
> +
> +#include <linux/types.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;
> +       u32 accepted;
> +       u32 reserved;
> +};

Could you explicitly pack these metadata data structures?
Since these metadata will be shared among bootloaders (TF-A, SCP-firmware),
it is better to ensure that those are packed and fixed offset for each field.

> +
> +/**
> + * 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];
> +};
> +
> +/**
> + * 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 {
> +       u32 crc32;
> +       u32 version;
> +       u32 active_index;
> +       u32 previous_active_index;
> +
> +       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> +};
> +
> +/**
> + * @get_active_index: get the current active_index value
> + * @update_active_index: update the 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
> + * @revert_boot_index: set the active_index to previous_active_index
> + * @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
> + */
> +struct fwu_mdata_ops {
> +       int (*get_active_index)(u32 *active_idx);
> +
> +       int (*update_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 (*revert_boot_index)(void);
> +
> +       int (*set_accept_image)(efi_guid_t *img_type_id);
> +
> +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> +
> +       int (*get_mdata)(struct fwu_mdata **mdata);
> +};
> +
> +int fwu_get_mdata(struct fwu_mdata **mdata);
> +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);

Also, could you also move these function prototypes and operators to
fwu? I would like to copy this header file to the boot loaders as is.
In that case, I just need the definition of the metadata data structure,
but no function prototypes.

Thank you,

> +
> +#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..348e9c85f7
> --- /dev/null
> +++ b/lib/fwu_updates/fwu_mdata.c
> @@ -0,0 +1,236 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2021, Linaro Limited
> + */
> +
> +#include <fwu_mdata.h>
> +
> +#include <linux/errno.h>
> +#include <linux/types.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)
> +{
> +       struct fwu_mdata_ops *ops;
> +
> +       ops = get_fwu_mdata_ops();
> +       if (!ops)
> +               return -EPROTONOSUPPORT;
> +
> +       if (!ops->update_active_index) {
> +               log_err("update_active_index() method not defined for the platform\n");
> +               return -ENOSYS;
> +       }
> +
> +       return ops->update_active_index(active_idx);
> +}
> +
> +/**
> + * 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)
> +{
> +       struct fwu_mdata_ops *ops;
> +
> +       ops = get_fwu_mdata_ops();
> +       if (!ops)
> +               return -EPROTONOSUPPORT;
> +
> +       if (!ops->revert_boot_index) {
> +               log_err("revert_boot_index() method not defined for the platform\n");
> +               return -ENOSYS;
> +       }
> +
> +       return ops->revert_boot_index();
> +}
> +
> +/**
> + * 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
> + *
> + * 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)
> +{
> +       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);
> +}
> +
> +/**
> + * 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
> + *
> + * 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);
> +}
> --
> 2.17.1
>


-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  0:10   ` Masami Hiramatsu
@ 2021-12-21  4:35     ` Sughosh Ganu
  2021-12-21  5:03       ` AKASHI Takahiro
  0 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-21  4:35 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, Jason Liu,
	Tom Rini, Etienne Carriere

hi Masami,

On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <masami.hiramatsu@linaro.org>
wrote:

> Hi Sughosh,
>
> 2021年12月19日(日) 16:06 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 V1:
> > * Move all function declarations to a separate header fwu.h
> > * Rename metadata with mdata for all symbols
> > * Drop the parameter in the function fwu_revert_boot_index
> >   as suggested by Etienne
> >
> >  include/fwu.h               |  28 +++++
> >  include/fwu_mdata.h         | 102 ++++++++++++++++
> >  lib/fwu_updates/fwu_mdata.c | 236 ++++++++++++++++++++++++++++++++++++
> >  3 files changed, 366 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..e6bc3e6b73
> > --- /dev/null
> > +++ b/include/fwu.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2021, Linaro Limited
> > + */
> > +
> > +#if !defined _FWU_H_
> > +#define _FWU_H_
> > +
> > +#include <efi.h>
> > +
> > +#include <linux/types.h>
> > +
> > +#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_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);
> > +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..11eb570012
> > --- /dev/null
> > +++ b/include/fwu_mdata.h
> > @@ -0,0 +1,102 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +/*
> > + * Copyright (c) 2021, Linaro Limited
> > + */
> > +
> > +#if !defined _FWU_MDATA_H_
> > +#define _FWU_MDATA_H_
> > +
> > +#include <efi.h>
> > +#include <uuid.h>
> > +
> > +#include <linux/types.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;
> > +       u32 accepted;
> > +       u32 reserved;
> > +};
>
> Could you explicitly pack these metadata data structures?
> Since these metadata will be shared among bootloaders (TF-A, SCP-firmware),
> it is better to ensure that those are packed and fixed offset for each
> field.
>

Okay. WIll do it.


>
> > +
> > +/**
> > + * 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];
> > +};
> > +
> > +/**
> > + * 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 {
> > +       u32 crc32;
> > +       u32 version;
> > +       u32 active_index;
> > +       u32 previous_active_index;
> > +
> > +       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> > +};
> > +
> > +/**
> > + * @get_active_index: get the current active_index value
> > + * @update_active_index: update the 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
> > + * @revert_boot_index: set the active_index to previous_active_index
> > + * @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
> > + */
> > +struct fwu_mdata_ops {
> > +       int (*get_active_index)(u32 *active_idx);
> > +
> > +       int (*update_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 (*revert_boot_index)(void);
> > +
> > +       int (*set_accept_image)(efi_guid_t *img_type_id);
> > +
> > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> > +
> > +       int (*get_mdata)(struct fwu_mdata **mdata);
> > +};
> > +
> > +int fwu_get_mdata(struct fwu_mdata **mdata);
> > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
>
> Also, could you also move these function prototypes and operators to
> fwu? I would like to copy this header file to the boot loaders as is.
> In that case, I just need the definition of the metadata data structure,
> but no function prototypes.
>

I have moved the function declarations to fwu.h. The one function prototype
that I have in fwu_mdata.h is the one which has the metadata structure as
one of it's parameters. Same for the ops as well. The get_mdata function
has the metadata structure as its parameter. Are you facing any issues with
the current structure of the files.

-sughosh


> Thank you,
>
> > +
> > +#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..348e9c85f7
> > --- /dev/null
> > +++ b/lib/fwu_updates/fwu_mdata.c
> > @@ -0,0 +1,236 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (c) 2021, Linaro Limited
> > + */
> > +
> > +#include <fwu_mdata.h>
> > +
> > +#include <linux/errno.h>
> > +#include <linux/types.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)
> > +{
> > +       struct fwu_mdata_ops *ops;
> > +
> > +       ops = get_fwu_mdata_ops();
> > +       if (!ops)
> > +               return -EPROTONOSUPPORT;
> > +
> > +       if (!ops->update_active_index) {
> > +               log_err("update_active_index() method not defined for
> the platform\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       return ops->update_active_index(active_idx);
> > +}
> > +
> > +/**
> > + * 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)
> > +{
> > +       struct fwu_mdata_ops *ops;
> > +
> > +       ops = get_fwu_mdata_ops();
> > +       if (!ops)
> > +               return -EPROTONOSUPPORT;
> > +
> > +       if (!ops->revert_boot_index) {
> > +               log_err("revert_boot_index() method not defined for the
> platform\n");
> > +               return -ENOSYS;
> > +       }
> > +
> > +       return ops->revert_boot_index();
> > +}
> > +
> > +/**
> > + * 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
> > + *
> > + * 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)
> > +{
> > +       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);
> > +}
> > +
> > +/**
> > + * 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
> > + *
> > + * 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);
> > +}
> > --
> > 2.17.1
> >
>
>
> --
> Masami Hiramatsu
>

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

* Re: [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2021-12-19  7:06 ` [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
@ 2021-12-21  4:53   ` AKASHI Takahiro
  2021-12-21  5:34     ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: AKASHI Takahiro @ 2021-12-21  4:53 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: u-boot, Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Jason Liu, Tom Rini,
	Etienne Carriere

Sughosh,

On Sun, Dec 19, 2021 at 12:36:02PM +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 V1:
> * Define a new function fwu_plat_get_alt_num for filling up
>   all the dfu partitions with a preset ImageTypeId guid
> * Remove the distinction made in the earlier version for
>   setting image_type_id as suggested by Heinrich
> 
>  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

If I understand your code correctly, a guid in descriptor for any image
(I mean any part defined by dfu_alto_info) will have the same value
even with this change.
If so, why do we have to take an array of GUIDs as a parameter?

On your previous version, Heinrich made a comment like:

! The sequence of GUIDs in a capsule should not influence the update. The
! design lacks a configuration defining which GUID maps to which DFU part.
! 
! Please, get rid of all DFU environment variables and describe the update
! in a configuration file that you add to the capsule.

Have you addressed this issue in this series?
(To do that, we may have to introduce a new format of capsule file.)

-Takahiro Akashi



>   *
>   * 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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  4:35     ` Sughosh Ganu
@ 2021-12-21  5:03       ` AKASHI Takahiro
  2021-12-21  5:47         ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: AKASHI Takahiro @ 2021-12-21  5:03 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, Jason Liu,
	Tom Rini, Etienne Carriere

On Tue, Dec 21, 2021 at 10:05:57AM +0530, Sughosh Ganu wrote:
> hi Masami,
> 
> On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <masami.hiramatsu@linaro.org>
> wrote:
> 
> > Hi Sughosh,
> >
> > 2021年12月19日(日) 16:06 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 V1:
> > > * Move all function declarations to a separate header fwu.h
> > > * Rename metadata with mdata for all symbols
> > > * Drop the parameter in the function fwu_revert_boot_index
> > >   as suggested by Etienne
> > >
> > >  include/fwu.h               |  28 +++++
> > >  include/fwu_mdata.h         | 102 ++++++++++++++++
> > >  lib/fwu_updates/fwu_mdata.c | 236 ++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 366 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..e6bc3e6b73
> > > --- /dev/null
> > > +++ b/include/fwu.h
> > > @@ -0,0 +1,28 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +/*
> > > + * Copyright (c) 2021, Linaro Limited
> > > + */
> > > +
> > > +#if !defined _FWU_H_
> > > +#define _FWU_H_
> > > +
> > > +#include <efi.h>
> > > +
> > > +#include <linux/types.h>
> > > +
> > > +#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_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);
> > > +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..11eb570012
> > > --- /dev/null
> > > +++ b/include/fwu_mdata.h
> > > @@ -0,0 +1,102 @@
> > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > +/*
> > > + * Copyright (c) 2021, Linaro Limited
> > > + */
> > > +
> > > +#if !defined _FWU_MDATA_H_
> > > +#define _FWU_MDATA_H_
> > > +
> > > +#include <efi.h>
> > > +#include <uuid.h>
> > > +
> > > +#include <linux/types.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;
> > > +       u32 accepted;
> > > +       u32 reserved;
> > > +};
> >
> > Could you explicitly pack these metadata data structures?
> > Since these metadata will be shared among bootloaders (TF-A, SCP-firmware),
> > it is better to ensure that those are packed and fixed offset for each
> > field.
> >
> 
> Okay. WIll do it.
> 
> 
> >
> > > +
> > > +/**
> > > + * 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];
> > > +};
> > > +
> > > +/**
> > > + * 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 {
> > > +       u32 crc32;
> > > +       u32 version;
> > > +       u32 active_index;
> > > +       u32 previous_active_index;
> > > +
> > > +       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> > > +};
> > > +
> > > +/**
> > > + * @get_active_index: get the current active_index value
> > > + * @update_active_index: update the 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
> > > + * @revert_boot_index: set the active_index to previous_active_index
> > > + * @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
> > > + */
> > > +struct fwu_mdata_ops {
> > > +       int (*get_active_index)(u32 *active_idx);
> > > +
> > > +       int (*update_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 (*revert_boot_index)(void);
> > > +
> > > +       int (*set_accept_image)(efi_guid_t *img_type_id);
> > > +
> > > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> > > +
> > > +       int (*get_mdata)(struct fwu_mdata **mdata);
> > > +};
> > > +
> > > +int fwu_get_mdata(struct fwu_mdata **mdata);
> > > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
> >
> > Also, could you also move these function prototypes and operators to
> > fwu? I would like to copy this header file to the boot loaders as is.
> > In that case, I just need the definition of the metadata data structure,
> > but no function prototypes.
> >
> 
> I have moved the function declarations to fwu.h. The one function prototype
> that I have in fwu_mdata.h is the one which has the metadata structure as
> one of it's parameters. Same for the ops as well. The get_mdata function
> has the metadata structure as its parameter. Are you facing any issues with
> the current structure of the files.

struct fwu_mdata;
int fwu_get_mdata(struct fwu_**mdata);

would be good enough?

I'm not sure whether it is a good idea that we re-use the *same* file
in other software, but I would suggest you to use standard POSIX types
like 'uint32_t' instead of 'u32' anyway.

-Takahiro Akashi


> -sughosh
> 
> 
> > Thank you,
> >
> > > +
> > > +#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..348e9c85f7
> > > --- /dev/null
> > > +++ b/lib/fwu_updates/fwu_mdata.c
> > > @@ -0,0 +1,236 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/*
> > > + * Copyright (c) 2021, Linaro Limited
> > > + */
> > > +
> > > +#include <fwu_mdata.h>
> > > +
> > > +#include <linux/errno.h>
> > > +#include <linux/types.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)
> > > +{
> > > +       struct fwu_mdata_ops *ops;
> > > +
> > > +       ops = get_fwu_mdata_ops();
> > > +       if (!ops)
> > > +               return -EPROTONOSUPPORT;
> > > +
> > > +       if (!ops->update_active_index) {
> > > +               log_err("update_active_index() method not defined for
> > the platform\n");
> > > +               return -ENOSYS;
> > > +       }
> > > +
> > > +       return ops->update_active_index(active_idx);
> > > +}
> > > +
> > > +/**
> > > + * 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)
> > > +{
> > > +       struct fwu_mdata_ops *ops;
> > > +
> > > +       ops = get_fwu_mdata_ops();
> > > +       if (!ops)
> > > +               return -EPROTONOSUPPORT;
> > > +
> > > +       if (!ops->revert_boot_index) {
> > > +               log_err("revert_boot_index() method not defined for the
> > platform\n");
> > > +               return -ENOSYS;
> > > +       }
> > > +
> > > +       return ops->revert_boot_index();
> > > +}
> > > +
> > > +/**
> > > + * 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
> > > + *
> > > + * 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)
> > > +{
> > > +       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);
> > > +}
> > > +
> > > +/**
> > > + * 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
> > > + *
> > > + * 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);
> > > +}
> > > --
> > > 2.17.1
> > >
> >
> >
> > --
> > Masami Hiramatsu
> >

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

* Re: [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor
  2021-12-21  4:53   ` AKASHI Takahiro
@ 2021-12-21  5:34     ` Sughosh Ganu
  0 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-21  5:34 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Tom Rini, Etienne Carriere

hi Takahiro,

On Tue, 21 Dec 2021 at 10:23, AKASHI Takahiro <takahiro.akashi@linaro.org>
wrote:

> Sughosh,
>
> On Sun, Dec 19, 2021 at 12:36:02PM +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 V1:
> > * Define a new function fwu_plat_get_alt_num for filling up
> >   all the dfu partitions with a preset ImageTypeId guid
> > * Remove the distinction made in the earlier version for
> >   setting image_type_id as suggested by Heinrich
> >
> >  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
>
> If I understand your code correctly, a guid in descriptor for any image
> (I mean any part defined by dfu_alto_info) will have the same value
> even with this change.
> If so, why do we have to take an array of GUIDs as a parameter?
>

One of Heinrich's comments in my previous version was not to distinguish
between the FWU case and the normal case when setting the image_type_id.
The existing code sets the same GUID value(image_type) for all images. I
have kept this consistent. With the FWU feature enabled,
fwu_plat_fill_partition_guids is called and this function fills in the
array with the relevant values of partition GUIDs.
fwu_plat_fill_partition_guids has been defined for the ST board in patch
3/8.


> On your previous version, Heinrich made a comment like:
>
> ! The sequence of GUIDs in a capsule should not influence the update. The
> ! design lacks a configuration defining which GUID maps to which DFU part.
> !
> ! Please, get rid of all DFU environment variables and describe the update
> ! in a configuration file that you add to the capsule.
>
> Have you addressed this issue in this series?
> (To do that, we may have to introduce a new format of capsule file.)
>

No, Ilias and I had replied back that detaching capsule update from DFU is
a separate effort, not related to the addition of the FWU functionality and
should be taken up as a separate activity.

-sughosh


>
> -Takahiro Akashi
>
>
>
> >   *
> >   * 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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  5:03       ` AKASHI Takahiro
@ 2021-12-21  5:47         ` Sughosh Ganu
  2021-12-21  6:01           ` Masami Hiramatsu
  2021-12-21  6:16           ` AKASHI Takahiro
  0 siblings, 2 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-21  5:47 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, Masami Hiramatsu, u-boot,
	Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Jason Liu, Tom Rini,
	Etienne Carriere

On Tue, 21 Dec 2021 at 10:33, AKASHI Takahiro <takahiro.akashi@linaro.org>
wrote:

> On Tue, Dec 21, 2021 at 10:05:57AM +0530, Sughosh Ganu wrote:
> > hi Masami,
> >
> > On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <
> masami.hiramatsu@linaro.org>
> > wrote:
> >
> > > Hi Sughosh,
> > >
> > > 2021年12月19日(日) 16:06 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 V1:
> > > > * Move all function declarations to a separate header fwu.h
> > > > * Rename metadata with mdata for all symbols
> > > > * Drop the parameter in the function fwu_revert_boot_index
> > > >   as suggested by Etienne
> > > >
> > > >  include/fwu.h               |  28 +++++
> > > >  include/fwu_mdata.h         | 102 ++++++++++++++++
> > > >  lib/fwu_updates/fwu_mdata.c | 236
> ++++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 366 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..e6bc3e6b73
> > > > --- /dev/null
> > > > +++ b/include/fwu.h
> > > > @@ -0,0 +1,28 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > +/*
> > > > + * Copyright (c) 2021, Linaro Limited
> > > > + */
> > > > +
> > > > +#if !defined _FWU_H_
> > > > +#define _FWU_H_
> > > > +
> > > > +#include <efi.h>
> > > > +
> > > > +#include <linux/types.h>
> > > > +
> > > > +#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_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);
> > > > +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..11eb570012
> > > > --- /dev/null
> > > > +++ b/include/fwu_mdata.h
> > > > @@ -0,0 +1,102 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > +/*
> > > > + * Copyright (c) 2021, Linaro Limited
> > > > + */
> > > > +
> > > > +#if !defined _FWU_MDATA_H_
> > > > +#define _FWU_MDATA_H_
> > > > +
> > > > +#include <efi.h>
> > > > +#include <uuid.h>
> > > > +
> > > > +#include <linux/types.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;
> > > > +       u32 accepted;
> > > > +       u32 reserved;
> > > > +};
> > >
> > > Could you explicitly pack these metadata data structures?
> > > Since these metadata will be shared among bootloaders (TF-A,
> SCP-firmware),
> > > it is better to ensure that those are packed and fixed offset for each
> > > field.
> > >
> >
> > Okay. WIll do it.
> >
> >
> > >
> > > > +
> > > > +/**
> > > > + * 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];
> > > > +};
> > > > +
> > > > +/**
> > > > + * 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 {
> > > > +       u32 crc32;
> > > > +       u32 version;
> > > > +       u32 active_index;
> > > > +       u32 previous_active_index;
> > > > +
> > > > +       struct fwu_image_entry
> img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> > > > +};
> > > > +
> > > > +/**
> > > > + * @get_active_index: get the current active_index value
> > > > + * @update_active_index: update the 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
> > > > + * @revert_boot_index: set the active_index to previous_active_index
> > > > + * @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
> > > > + */
> > > > +struct fwu_mdata_ops {
> > > > +       int (*get_active_index)(u32 *active_idx);
> > > > +
> > > > +       int (*update_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 (*revert_boot_index)(void);
> > > > +
> > > > +       int (*set_accept_image)(efi_guid_t *img_type_id);
> > > > +
> > > > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> > > > +
> > > > +       int (*get_mdata)(struct fwu_mdata **mdata);
> > > > +};
> > > > +
> > > > +int fwu_get_mdata(struct fwu_mdata **mdata);
> > > > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
> > >
> > > Also, could you also move these function prototypes and operators to
> > > fwu? I would like to copy this header file to the boot loaders as is.
> > > In that case, I just need the definition of the metadata data
> structure,
> > > but no function prototypes.
> > >
> >
> > I have moved the function declarations to fwu.h. The one function
> prototype
> > that I have in fwu_mdata.h is the one which has the metadata structure as
> > one of it's parameters. Same for the ops as well. The get_mdata function
> > has the metadata structure as its parameter. Are you facing any issues
> with
> > the current structure of the files.
>
> struct fwu_mdata;
> int fwu_get_mdata(struct fwu_**mdata);
>
> would be good enough?
>

Yes, I had considered putting this kind of declaration in fwu.h. But I
decided against it thinking that any function declaration that involved the
fwu metadata structure can be put in one file. But I just want to
understand if there is some issue in putting these declarations in the
fwu_mdata.h. The rest of the function declarations and symbols are put in
the fwu.h header. If you see, I only include the fwu.h in the
efi_firmware.c and efi_capsule.c.


>
> I'm not sure whether it is a good idea that we re-use the *same* file
> in other software, but I would suggest you to use standard POSIX types
> like 'uint32_t' instead of 'u32' anyway.
>

Hmm, this is on the same lines to the types used in the capsule code. That
was the primary reason that I stuck with u<size> types. Any issue with
using the short type? The Linux kernel seems to be using it.

-sughosh


>
> -Takahiro Akashi
>
>
> > -sughosh
> >
> >
> > > Thank you,
> > >
> > > > +
> > > > +#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..348e9c85f7
> > > > --- /dev/null
> > > > +++ b/lib/fwu_updates/fwu_mdata.c
> > > > @@ -0,0 +1,236 @@
> > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > +/*
> > > > + * Copyright (c) 2021, Linaro Limited
> > > > + */
> > > > +
> > > > +#include <fwu_mdata.h>
> > > > +
> > > > +#include <linux/errno.h>
> > > > +#include <linux/types.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)
> > > > +{
> > > > +       struct fwu_mdata_ops *ops;
> > > > +
> > > > +       ops = get_fwu_mdata_ops();
> > > > +       if (!ops)
> > > > +               return -EPROTONOSUPPORT;
> > > > +
> > > > +       if (!ops->update_active_index) {
> > > > +               log_err("update_active_index() method not defined for
> > > the platform\n");
> > > > +               return -ENOSYS;
> > > > +       }
> > > > +
> > > > +       return ops->update_active_index(active_idx);
> > > > +}
> > > > +
> > > > +/**
> > > > + * 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)
> > > > +{
> > > > +       struct fwu_mdata_ops *ops;
> > > > +
> > > > +       ops = get_fwu_mdata_ops();
> > > > +       if (!ops)
> > > > +               return -EPROTONOSUPPORT;
> > > > +
> > > > +       if (!ops->revert_boot_index) {
> > > > +               log_err("revert_boot_index() method not defined for
> the
> > > platform\n");
> > > > +               return -ENOSYS;
> > > > +       }
> > > > +
> > > > +       return ops->revert_boot_index();
> > > > +}
> > > > +
> > > > +/**
> > > > + * 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
> > > > + *
> > > > + * 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)
> > > > +{
> > > > +       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);
> > > > +}
> > > > +
> > > > +/**
> > > > + * 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
> > > > + *
> > > > + * 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);
> > > > +}
> > > > --
> > > > 2.17.1
> > > >
> > >
> > >
> > > --
> > > Masami Hiramatsu
> > >
>

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

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  5:47         ` Sughosh Ganu
@ 2021-12-21  6:01           ` Masami Hiramatsu
  2021-12-21  6:08             ` Sughosh Ganu
  2021-12-21  6:16           ` AKASHI Takahiro
  1 sibling, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-21  6:01 UTC (permalink / raw)
  To: Sughosh Ganu
  Cc: AKASHI Takahiro, u-boot, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,


2021年12月21日(火) 14:47 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
>
> On Tue, 21 Dec 2021 at 10:33, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
>>
>> On Tue, Dec 21, 2021 at 10:05:57AM +0530, Sughosh Ganu wrote:
>> > hi Masami,
>> >
>> > On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <masami.hiramatsu@linaro.org>
>> > wrote:
>> >
>> > > Hi Sughosh,
>> > >
>> > > 2021年12月19日(日) 16:06 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 V1:
>> > > > * Move all function declarations to a separate header fwu.h
>> > > > * Rename metadata with mdata for all symbols
>> > > > * Drop the parameter in the function fwu_revert_boot_index
>> > > >   as suggested by Etienne
>> > > >
>> > > >  include/fwu.h               |  28 +++++
>> > > >  include/fwu_mdata.h         | 102 ++++++++++++++++
>> > > >  lib/fwu_updates/fwu_mdata.c | 236 ++++++++++++++++++++++++++++++++++++
>> > > >  3 files changed, 366 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..e6bc3e6b73
>> > > > --- /dev/null
>> > > > +++ b/include/fwu.h
>> > > > @@ -0,0 +1,28 @@
>> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
>> > > > +/*
>> > > > + * Copyright (c) 2021, Linaro Limited
>> > > > + */
>> > > > +
>> > > > +#if !defined _FWU_H_
>> > > > +#define _FWU_H_
>> > > > +
>> > > > +#include <efi.h>
>> > > > +
>> > > > +#include <linux/types.h>
>> > > > +
>> > > > +#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_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);
>> > > > +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..11eb570012
>> > > > --- /dev/null
>> > > > +++ b/include/fwu_mdata.h
>> > > > @@ -0,0 +1,102 @@
>> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
>> > > > +/*
>> > > > + * Copyright (c) 2021, Linaro Limited
>> > > > + */
>> > > > +
>> > > > +#if !defined _FWU_MDATA_H_
>> > > > +#define _FWU_MDATA_H_
>> > > > +
>> > > > +#include <efi.h>
>> > > > +#include <uuid.h>
>> > > > +
>> > > > +#include <linux/types.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;
>> > > > +       u32 accepted;
>> > > > +       u32 reserved;
>> > > > +};
>> > >
>> > > Could you explicitly pack these metadata data structures?
>> > > Since these metadata will be shared among bootloaders (TF-A, SCP-firmware),
>> > > it is better to ensure that those are packed and fixed offset for each
>> > > field.
>> > >
>> >
>> > Okay. WIll do it.
>> >
>> >
>> > >
>> > > > +
>> > > > +/**
>> > > > + * 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];
>> > > > +};
>> > > > +
>> > > > +/**
>> > > > + * 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 {
>> > > > +       u32 crc32;
>> > > > +       u32 version;
>> > > > +       u32 active_index;
>> > > > +       u32 previous_active_index;
>> > > > +
>> > > > +       struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
>> > > > +};
>> > > > +
>> > > > +/**
>> > > > + * @get_active_index: get the current active_index value
>> > > > + * @update_active_index: update the 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
>> > > > + * @revert_boot_index: set the active_index to previous_active_index
>> > > > + * @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
>> > > > + */
>> > > > +struct fwu_mdata_ops {
>> > > > +       int (*get_active_index)(u32 *active_idx);
>> > > > +
>> > > > +       int (*update_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 (*revert_boot_index)(void);
>> > > > +
>> > > > +       int (*set_accept_image)(efi_guid_t *img_type_id);
>> > > > +
>> > > > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
>> > > > +
>> > > > +       int (*get_mdata)(struct fwu_mdata **mdata);
>> > > > +};
>> > > > +
>> > > > +int fwu_get_mdata(struct fwu_mdata **mdata);
>> > > > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
>> > >
>> > > Also, could you also move these function prototypes and operators to
>> > > fwu? I would like to copy this header file to the boot loaders as is.
>> > > In that case, I just need the definition of the metadata data structure,
>> > > but no function prototypes.
>> > >
>> >
>> > I have moved the function declarations to fwu.h. The one function prototype
>> > that I have in fwu_mdata.h is the one which has the metadata structure as
>> > one of it's parameters. Same for the ops as well. The get_mdata function
>> > has the metadata structure as its parameter. Are you facing any issues with
>> > the current structure of the files.

The structure is OK (if it is packed). But the prototypes, interfaces
are no needed
because the metadata access method is not needed for the bootloader, like
TF-A and SCP-firmware.
Of course I can write it again for those firmwares, as far as it's
coding style suits
to the project, I would like to reuse it. If any update applied, I can apply the
change to the other firmware too.

>>
>> struct fwu_mdata;
>> int fwu_get_mdata(struct fwu_**mdata);
>>
>> would be good enough?
>
>
> Yes, I had considered putting this kind of declaration in fwu.h. But I decided against it thinking that any function declaration that involved the fwu metadata structure can be put in one file. But I just want to understand if there is some issue in putting these declarations in the fwu_mdata.h. The rest of the function declarations and symbols are put in the fwu.h header. If you see, I only include the fwu.h in the efi_firmware.c and efi_capsule.c.

I just want to share the metadata definition among firmware projects.
In that case, the metadata is on the storage media, but the operation
will be re-implemented for each firmware. I think it is better to
split it. :)

Thank you,

>
>>
>>
>> I'm not sure whether it is a good idea that we re-use the *same* file
>> in other software, but I would suggest you to use standard POSIX types
>> like 'uint32_t' instead of 'u32' anyway.
>
>
> Hmm, this is on the same lines to the types used in the capsule code. That was the primary reason that I stuck with u<size> types. Any issue with using the short type? The Linux kernel seems to be using it.
>
> -sughosh
>
>>
>>
>> -Takahiro Akashi
>>
>>
>> > -sughosh
>> >
>> >
>> > > Thank you,
>> > >
>> > > > +
>> > > > +#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..348e9c85f7
>> > > > --- /dev/null
>> > > > +++ b/lib/fwu_updates/fwu_mdata.c
>> > > > @@ -0,0 +1,236 @@
>> > > > +// SPDX-License-Identifier: GPL-2.0+
>> > > > +/*
>> > > > + * Copyright (c) 2021, Linaro Limited
>> > > > + */
>> > > > +
>> > > > +#include <fwu_mdata.h>
>> > > > +
>> > > > +#include <linux/errno.h>
>> > > > +#include <linux/types.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)
>> > > > +{
>> > > > +       struct fwu_mdata_ops *ops;
>> > > > +
>> > > > +       ops = get_fwu_mdata_ops();
>> > > > +       if (!ops)
>> > > > +               return -EPROTONOSUPPORT;
>> > > > +
>> > > > +       if (!ops->update_active_index) {
>> > > > +               log_err("update_active_index() method not defined for
>> > > the platform\n");
>> > > > +               return -ENOSYS;
>> > > > +       }
>> > > > +
>> > > > +       return ops->update_active_index(active_idx);
>> > > > +}
>> > > > +
>> > > > +/**
>> > > > + * 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)
>> > > > +{
>> > > > +       struct fwu_mdata_ops *ops;
>> > > > +
>> > > > +       ops = get_fwu_mdata_ops();
>> > > > +       if (!ops)
>> > > > +               return -EPROTONOSUPPORT;
>> > > > +
>> > > > +       if (!ops->revert_boot_index) {
>> > > > +               log_err("revert_boot_index() method not defined for the
>> > > platform\n");
>> > > > +               return -ENOSYS;
>> > > > +       }
>> > > > +
>> > > > +       return ops->revert_boot_index();
>> > > > +}
>> > > > +
>> > > > +/**
>> > > > + * 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
>> > > > + *
>> > > > + * 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)
>> > > > +{
>> > > > +       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);
>> > > > +}
>> > > > +
>> > > > +/**
>> > > > + * 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
>> > > > + *
>> > > > + * 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);
>> > > > +}
>> > > > --
>> > > > 2.17.1
>> > > >
>> > >
>> > >
>> > > --
>> > > Masami Hiramatsu
>> > >



-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  6:01           ` Masami Hiramatsu
@ 2021-12-21  6:08             ` Sughosh Ganu
  0 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-21  6:08 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: AKASHI Takahiro, u-boot, Patrick Delaunay, Patrice Chotard,
	Heinrich Schuchardt, Alexander Graf, Simon Glass, Bin Meng,
	Ilias Apalodimas, Jose Marinho, Grant Likely, Jason Liu,
	Tom Rini, Etienne Carriere

hi Masami,

On Tue, 21 Dec 2021 at 11:31, Masami Hiramatsu <masami.hiramatsu@linaro.org>
wrote:

> Hi Sughosh,
>
>
> 2021年12月21日(火) 14:47 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> >
> > On Tue, 21 Dec 2021 at 10:33, AKASHI Takahiro <
> takahiro.akashi@linaro.org> wrote:
> >>
> >> On Tue, Dec 21, 2021 at 10:05:57AM +0530, Sughosh Ganu wrote:
> >> > hi Masami,
> >> >
> >> > On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <
> masami.hiramatsu@linaro.org>
> >> > wrote:
> >> >
> >> > > Hi Sughosh,
> >> > >
> >> > > 2021年12月19日(日) 16:06 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 V1:
> >> > > > * Move all function declarations to a separate header fwu.h
> >> > > > * Rename metadata with mdata for all symbols
> >> > > > * Drop the parameter in the function fwu_revert_boot_index
> >> > > >   as suggested by Etienne
> >> > > >
> >> > > >  include/fwu.h               |  28 +++++
> >> > > >  include/fwu_mdata.h         | 102 ++++++++++++++++
> >> > > >  lib/fwu_updates/fwu_mdata.c | 236
> ++++++++++++++++++++++++++++++++++++
> >> > > >  3 files changed, 366 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..e6bc3e6b73
> >> > > > --- /dev/null
> >> > > > +++ b/include/fwu.h
> >> > > > @@ -0,0 +1,28 @@
> >> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> >> > > > +/*
> >> > > > + * Copyright (c) 2021, Linaro Limited
> >> > > > + */
> >> > > > +
> >> > > > +#if !defined _FWU_H_
> >> > > > +#define _FWU_H_
> >> > > > +
> >> > > > +#include <efi.h>
> >> > > > +
> >> > > > +#include <linux/types.h>
> >> > > > +
> >> > > > +#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_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);
> >> > > > +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..11eb570012
> >> > > > --- /dev/null
> >> > > > +++ b/include/fwu_mdata.h
> >> > > > @@ -0,0 +1,102 @@
> >> > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> >> > > > +/*
> >> > > > + * Copyright (c) 2021, Linaro Limited
> >> > > > + */
> >> > > > +
> >> > > > +#if !defined _FWU_MDATA_H_
> >> > > > +#define _FWU_MDATA_H_
> >> > > > +
> >> > > > +#include <efi.h>
> >> > > > +#include <uuid.h>
> >> > > > +
> >> > > > +#include <linux/types.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;
> >> > > > +       u32 accepted;
> >> > > > +       u32 reserved;
> >> > > > +};
> >> > >
> >> > > Could you explicitly pack these metadata data structures?
> >> > > Since these metadata will be shared among bootloaders (TF-A,
> SCP-firmware),
> >> > > it is better to ensure that those are packed and fixed offset for
> each
> >> > > field.
> >> > >
> >> >
> >> > Okay. WIll do it.
> >> >
> >> >
> >> > >
> >> > > > +
> >> > > > +/**
> >> > > > + * 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];
> >> > > > +};
> >> > > > +
> >> > > > +/**
> >> > > > + * 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 {
> >> > > > +       u32 crc32;
> >> > > > +       u32 version;
> >> > > > +       u32 active_index;
> >> > > > +       u32 previous_active_index;
> >> > > > +
> >> > > > +       struct fwu_image_entry
> img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> >> > > > +};
> >> > > > +
> >> > > > +/**
> >> > > > + * @get_active_index: get the current active_index value
> >> > > > + * @update_active_index: update the 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
> >> > > > + * @revert_boot_index: set the active_index to
> previous_active_index
> >> > > > + * @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
> >> > > > + */
> >> > > > +struct fwu_mdata_ops {
> >> > > > +       int (*get_active_index)(u32 *active_idx);
> >> > > > +
> >> > > > +       int (*update_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 (*revert_boot_index)(void);
> >> > > > +
> >> > > > +       int (*set_accept_image)(efi_guid_t *img_type_id);
> >> > > > +
> >> > > > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32
> bank);
> >> > > > +
> >> > > > +       int (*get_mdata)(struct fwu_mdata **mdata);
> >> > > > +};
> >> > > > +
> >> > > > +int fwu_get_mdata(struct fwu_mdata **mdata);
> >> > > > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
> >> > >
> >> > > Also, could you also move these function prototypes and operators to
> >> > > fwu? I would like to copy this header file to the boot loaders as
> is.
> >> > > In that case, I just need the definition of the metadata data
> structure,
> >> > > but no function prototypes.
> >> > >
> >> >
> >> > I have moved the function declarations to fwu.h. The one function
> prototype
> >> > that I have in fwu_mdata.h is the one which has the metadata
> structure as
> >> > one of it's parameters. Same for the ops as well. The get_mdata
> function
> >> > has the metadata structure as its parameter. Are you facing any
> issues with
> >> > the current structure of the files.
>
> The structure is OK (if it is packed). But the prototypes, interfaces
> are no needed
> because the metadata access method is not needed for the bootloader, like
> TF-A and SCP-firmware.
> Of course I can write it again for those firmwares, as far as it's
> coding style suits
> to the project, I would like to reuse it. If any update applied, I can
> apply the
> change to the other firmware too.
>

Okay, I now get why you want the metadata structure in a separate file :).
That makes sense. I will remove all other stuff apart from the structure
definitions in my next version. Thanks for your explanation.

-sughosh


>
> >>
> >> struct fwu_mdata;
> >> int fwu_get_mdata(struct fwu_**mdata);
> >>
> >> would be good enough?
> >
> >
> > Yes, I had considered putting this kind of declaration in fwu.h. But I
> decided against it thinking that any function declaration that involved the
> fwu metadata structure can be put in one file. But I just want to
> understand if there is some issue in putting these declarations in the
> fwu_mdata.h. The rest of the function declarations and symbols are put in
> the fwu.h header. If you see, I only include the fwu.h in the
> efi_firmware.c and efi_capsule.c.
>
> I just want to share the metadata definition among firmware projects.
> In that case, the metadata is on the storage media, but the operation
> will be re-implemented for each firmware. I think it is better to
> split it. :)
>
> Thank you,
>
> >
> >>
> >>
> >> I'm not sure whether it is a good idea that we re-use the *same* file
> >> in other software, but I would suggest you to use standard POSIX types
> >> like 'uint32_t' instead of 'u32' anyway.
> >
> >
> > Hmm, this is on the same lines to the types used in the capsule code.
> That was the primary reason that I stuck with u<size> types. Any issue with
> using the short type? The Linux kernel seems to be using it.
> >
> > -sughosh
> >
> >>
> >>
> >> -Takahiro Akashi
> >>
> >>
> >> > -sughosh
> >> >
> >> >
> >> > > Thank you,
> >> > >
> >> > > > +
> >> > > > +#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..348e9c85f7
> >> > > > --- /dev/null
> >> > > > +++ b/lib/fwu_updates/fwu_mdata.c
> >> > > > @@ -0,0 +1,236 @@
> >> > > > +// SPDX-License-Identifier: GPL-2.0+
> >> > > > +/*
> >> > > > + * Copyright (c) 2021, Linaro Limited
> >> > > > + */
> >> > > > +
> >> > > > +#include <fwu_mdata.h>
> >> > > > +
> >> > > > +#include <linux/errno.h>
> >> > > > +#include <linux/types.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)
> >> > > > +{
> >> > > > +       struct fwu_mdata_ops *ops;
> >> > > > +
> >> > > > +       ops = get_fwu_mdata_ops();
> >> > > > +       if (!ops)
> >> > > > +               return -EPROTONOSUPPORT;
> >> > > > +
> >> > > > +       if (!ops->update_active_index) {
> >> > > > +               log_err("update_active_index() method not defined
> for
> >> > > the platform\n");
> >> > > > +               return -ENOSYS;
> >> > > > +       }
> >> > > > +
> >> > > > +       return ops->update_active_index(active_idx);
> >> > > > +}
> >> > > > +
> >> > > > +/**
> >> > > > + * 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)
> >> > > > +{
> >> > > > +       struct fwu_mdata_ops *ops;
> >> > > > +
> >> > > > +       ops = get_fwu_mdata_ops();
> >> > > > +       if (!ops)
> >> > > > +               return -EPROTONOSUPPORT;
> >> > > > +
> >> > > > +       if (!ops->revert_boot_index) {
> >> > > > +               log_err("revert_boot_index() method not defined
> for the
> >> > > platform\n");
> >> > > > +               return -ENOSYS;
> >> > > > +       }
> >> > > > +
> >> > > > +       return ops->revert_boot_index();
> >> > > > +}
> >> > > > +
> >> > > > +/**
> >> > > > + * 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
> >> > > > + *
> >> > > > + * 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)
> >> > > > +{
> >> > > > +       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);
> >> > > > +}
> >> > > > +
> >> > > > +/**
> >> > > > + * 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
> >> > > > + *
> >> > > > + * 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);
> >> > > > +}
> >> > > > --
> >> > > > 2.17.1
> >> > > >
> >> > >
> >> > >
> >> > > --
> >> > > Masami Hiramatsu
> >> > >
>
>
>
> --
> Masami Hiramatsu
>

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

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  5:47         ` Sughosh Ganu
  2021-12-21  6:01           ` Masami Hiramatsu
@ 2021-12-21  6:16           ` AKASHI Takahiro
  2021-12-21  6:24             ` Sughosh Ganu
  1 sibling, 1 reply; 38+ messages in thread
From: AKASHI Takahiro @ 2021-12-21  6:16 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, Jason Liu,
	Tom Rini, Etienne Carriere

On Tue, Dec 21, 2021 at 11:17:47AM +0530, Sughosh Ganu wrote:
> On Tue, 21 Dec 2021 at 10:33, AKASHI Takahiro <takahiro.akashi@linaro.org>
> wrote:
> 
> > On Tue, Dec 21, 2021 at 10:05:57AM +0530, Sughosh Ganu wrote:
> > > hi Masami,
> > >
> > > On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <
> > masami.hiramatsu@linaro.org>
> > > wrote:
> > >
> > > > Hi Sughosh,
> > > >
> > > > 2021年12月19日(日) 16:06 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 V1:
> > > > > * Move all function declarations to a separate header fwu.h
> > > > > * Rename metadata with mdata for all symbols
> > > > > * Drop the parameter in the function fwu_revert_boot_index
> > > > >   as suggested by Etienne
> > > > >
> > > > >  include/fwu.h               |  28 +++++
> > > > >  include/fwu_mdata.h         | 102 ++++++++++++++++
> > > > >  lib/fwu_updates/fwu_mdata.c | 236
> > ++++++++++++++++++++++++++++++++++++
> > > > >  3 files changed, 366 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..e6bc3e6b73
> > > > > --- /dev/null
> > > > > +++ b/include/fwu.h
> > > > > @@ -0,0 +1,28 @@
> > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > +/*
> > > > > + * Copyright (c) 2021, Linaro Limited
> > > > > + */
> > > > > +
> > > > > +#if !defined _FWU_H_
> > > > > +#define _FWU_H_
> > > > > +
> > > > > +#include <efi.h>
> > > > > +
> > > > > +#include <linux/types.h>
> > > > > +
> > > > > +#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_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);
> > > > > +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..11eb570012
> > > > > --- /dev/null
> > > > > +++ b/include/fwu_mdata.h
> > > > > @@ -0,0 +1,102 @@
> > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > +/*
> > > > > + * Copyright (c) 2021, Linaro Limited
> > > > > + */
> > > > > +
> > > > > +#if !defined _FWU_MDATA_H_
> > > > > +#define _FWU_MDATA_H_
> > > > > +
> > > > > +#include <efi.h>
> > > > > +#include <uuid.h>
> > > > > +
> > > > > +#include <linux/types.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;
> > > > > +       u32 accepted;
> > > > > +       u32 reserved;
> > > > > +};
> > > >
> > > > Could you explicitly pack these metadata data structures?
> > > > Since these metadata will be shared among bootloaders (TF-A,
> > SCP-firmware),
> > > > it is better to ensure that those are packed and fixed offset for each
> > > > field.
> > > >
> > >
> > > Okay. WIll do it.
> > >
> > >
> > > >
> > > > > +
> > > > > +/**
> > > > > + * 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];
> > > > > +};
> > > > > +
> > > > > +/**
> > > > > + * 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 {
> > > > > +       u32 crc32;
> > > > > +       u32 version;
> > > > > +       u32 active_index;
> > > > > +       u32 previous_active_index;
> > > > > +
> > > > > +       struct fwu_image_entry
> > img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> > > > > +};
> > > > > +
> > > > > +/**
> > > > > + * @get_active_index: get the current active_index value
> > > > > + * @update_active_index: update the 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
> > > > > + * @revert_boot_index: set the active_index to previous_active_index
> > > > > + * @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
> > > > > + */
> > > > > +struct fwu_mdata_ops {
> > > > > +       int (*get_active_index)(u32 *active_idx);
> > > > > +
> > > > > +       int (*update_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 (*revert_boot_index)(void);
> > > > > +
> > > > > +       int (*set_accept_image)(efi_guid_t *img_type_id);
> > > > > +
> > > > > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32 bank);
> > > > > +
> > > > > +       int (*get_mdata)(struct fwu_mdata **mdata);
> > > > > +};
> > > > > +
> > > > > +int fwu_get_mdata(struct fwu_mdata **mdata);
> > > > > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
> > > >
> > > > Also, could you also move these function prototypes and operators to
> > > > fwu? I would like to copy this header file to the boot loaders as is.
> > > > In that case, I just need the definition of the metadata data
> > structure,
> > > > but no function prototypes.
> > > >
> > >
> > > I have moved the function declarations to fwu.h. The one function
> > prototype
> > > that I have in fwu_mdata.h is the one which has the metadata structure as
> > > one of it's parameters. Same for the ops as well. The get_mdata function
> > > has the metadata structure as its parameter. Are you facing any issues
> > with
> > > the current structure of the files.
> >
> > struct fwu_mdata;
> > int fwu_get_mdata(struct fwu_**mdata);
> >
> > would be good enough?
> >
> 
> Yes, I had considered putting this kind of declaration in fwu.h. But I
> decided against it thinking that any function declaration that involved the
> fwu metadata structure can be put in one file. But I just want to
> understand if there is some issue in putting these declarations in the
> fwu_mdata.h. The rest of the function declarations and symbols are put in
> the fwu.h header. If you see, I only include the fwu.h in the
> efi_firmware.c and efi_capsule.c.
> 
> 
> >
> > I'm not sure whether it is a good idea that we re-use the *same* file
> > in other software, but I would suggest you to use standard POSIX types
> > like 'uint32_t' instead of 'u32' anyway.
> >
> 
> Hmm, this is on the same lines to the types used in the capsule code. That
> was the primary reason that I stuck with u<size> types. Any issue with
> using the short type? The Linux kernel seems to be using it.

That is my point. Why should we use linux-specific types in
other software, especially when we want to import a generic
header, which is essentially platform agnostic?

-Takahiro Akashi

> -sughosh
> 
> 
> >
> > -Takahiro Akashi
> >
> >
> > > -sughosh
> > >
> > >
> > > > Thank you,
> > > >
> > > > > +
> > > > > +#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..348e9c85f7
> > > > > --- /dev/null
> > > > > +++ b/lib/fwu_updates/fwu_mdata.c
> > > > > @@ -0,0 +1,236 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > > +/*
> > > > > + * Copyright (c) 2021, Linaro Limited
> > > > > + */
> > > > > +
> > > > > +#include <fwu_mdata.h>
> > > > > +
> > > > > +#include <linux/errno.h>
> > > > > +#include <linux/types.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)
> > > > > +{
> > > > > +       struct fwu_mdata_ops *ops;
> > > > > +
> > > > > +       ops = get_fwu_mdata_ops();
> > > > > +       if (!ops)
> > > > > +               return -EPROTONOSUPPORT;
> > > > > +
> > > > > +       if (!ops->update_active_index) {
> > > > > +               log_err("update_active_index() method not defined for
> > > > the platform\n");
> > > > > +               return -ENOSYS;
> > > > > +       }
> > > > > +
> > > > > +       return ops->update_active_index(active_idx);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + * 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)
> > > > > +{
> > > > > +       struct fwu_mdata_ops *ops;
> > > > > +
> > > > > +       ops = get_fwu_mdata_ops();
> > > > > +       if (!ops)
> > > > > +               return -EPROTONOSUPPORT;
> > > > > +
> > > > > +       if (!ops->revert_boot_index) {
> > > > > +               log_err("revert_boot_index() method not defined for
> > the
> > > > platform\n");
> > > > > +               return -ENOSYS;
> > > > > +       }
> > > > > +
> > > > > +       return ops->revert_boot_index();
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + * 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
> > > > > + *
> > > > > + * 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)
> > > > > +{
> > > > > +       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);
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > + * 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
> > > > > + *
> > > > > + * 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);
> > > > > +}
> > > > > --
> > > > > 2.17.1
> > > > >
> > > >
> > > >
> > > > --
> > > > Masami Hiramatsu
> > > >
> >

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

* Re: [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata
  2021-12-21  6:16           ` AKASHI Takahiro
@ 2021-12-21  6:24             ` Sughosh Ganu
  0 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-21  6:24 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, Masami Hiramatsu, u-boot,
	Patrick Delaunay, Patrice Chotard, Heinrich Schuchardt,
	Alexander Graf, Simon Glass, Bin Meng, Ilias Apalodimas,
	Jose Marinho, Grant Likely, Jason Liu, Tom Rini,
	Etienne Carriere

On Tue, 21 Dec 2021 at 11:46, AKASHI Takahiro <takahiro.akashi@linaro.org>
wrote:

> On Tue, Dec 21, 2021 at 11:17:47AM +0530, Sughosh Ganu wrote:
> > On Tue, 21 Dec 2021 at 10:33, AKASHI Takahiro <
> takahiro.akashi@linaro.org>
> > wrote:
> >
> > > On Tue, Dec 21, 2021 at 10:05:57AM +0530, Sughosh Ganu wrote:
> > > > hi Masami,
> > > >
> > > > On Tue, 21 Dec 2021 at 05:40, Masami Hiramatsu <
> > > masami.hiramatsu@linaro.org>
> > > > wrote:
> > > >
> > > > > Hi Sughosh,
> > > > >
> > > > > 2021年12月19日(日) 16:06 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 V1:
> > > > > > * Move all function declarations to a separate header fwu.h
> > > > > > * Rename metadata with mdata for all symbols
> > > > > > * Drop the parameter in the function fwu_revert_boot_index
> > > > > >   as suggested by Etienne
> > > > > >
> > > > > >  include/fwu.h               |  28 +++++
> > > > > >  include/fwu_mdata.h         | 102 ++++++++++++++++
> > > > > >  lib/fwu_updates/fwu_mdata.c | 236
> > > ++++++++++++++++++++++++++++++++++++
> > > > > >  3 files changed, 366 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..e6bc3e6b73
> > > > > > --- /dev/null
> > > > > > +++ b/include/fwu.h
> > > > > > @@ -0,0 +1,28 @@
> > > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > > +/*
> > > > > > + * Copyright (c) 2021, Linaro Limited
> > > > > > + */
> > > > > > +
> > > > > > +#if !defined _FWU_H_
> > > > > > +#define _FWU_H_
> > > > > > +
> > > > > > +#include <efi.h>
> > > > > > +
> > > > > > +#include <linux/types.h>
> > > > > > +
> > > > > > +#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_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);
> > > > > > +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..11eb570012
> > > > > > --- /dev/null
> > > > > > +++ b/include/fwu_mdata.h
> > > > > > @@ -0,0 +1,102 @@
> > > > > > +/* SPDX-License-Identifier: GPL-2.0+ */
> > > > > > +/*
> > > > > > + * Copyright (c) 2021, Linaro Limited
> > > > > > + */
> > > > > > +
> > > > > > +#if !defined _FWU_MDATA_H_
> > > > > > +#define _FWU_MDATA_H_
> > > > > > +
> > > > > > +#include <efi.h>
> > > > > > +#include <uuid.h>
> > > > > > +
> > > > > > +#include <linux/types.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;
> > > > > > +       u32 accepted;
> > > > > > +       u32 reserved;
> > > > > > +};
> > > > >
> > > > > Could you explicitly pack these metadata data structures?
> > > > > Since these metadata will be shared among bootloaders (TF-A,
> > > SCP-firmware),
> > > > > it is better to ensure that those are packed and fixed offset for
> each
> > > > > field.
> > > > >
> > > >
> > > > Okay. WIll do it.
> > > >
> > > >
> > > > >
> > > > > > +
> > > > > > +/**
> > > > > > + * 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];
> > > > > > +};
> > > > > > +
> > > > > > +/**
> > > > > > + * 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 {
> > > > > > +       u32 crc32;
> > > > > > +       u32 version;
> > > > > > +       u32 active_index;
> > > > > > +       u32 previous_active_index;
> > > > > > +
> > > > > > +       struct fwu_image_entry
> > > img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
> > > > > > +};
> > > > > > +
> > > > > > +/**
> > > > > > + * @get_active_index: get the current active_index value
> > > > > > + * @update_active_index: update the 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
> > > > > > + * @revert_boot_index: set the active_index to
> previous_active_index
> > > > > > + * @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
> > > > > > + */
> > > > > > +struct fwu_mdata_ops {
> > > > > > +       int (*get_active_index)(u32 *active_idx);
> > > > > > +
> > > > > > +       int (*update_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 (*revert_boot_index)(void);
> > > > > > +
> > > > > > +       int (*set_accept_image)(efi_guid_t *img_type_id);
> > > > > > +
> > > > > > +       int (*clear_accept_image)(efi_guid_t *img_type_id, u32
> bank);
> > > > > > +
> > > > > > +       int (*get_mdata)(struct fwu_mdata **mdata);
> > > > > > +};
> > > > > > +
> > > > > > +int fwu_get_mdata(struct fwu_mdata **mdata);
> > > > > > +struct fwu_mdata_ops *get_plat_fwu_mdata_ops(void);
> > > > >
> > > > > Also, could you also move these function prototypes and operators
> to
> > > > > fwu? I would like to copy this header file to the boot loaders as
> is.
> > > > > In that case, I just need the definition of the metadata data
> > > structure,
> > > > > but no function prototypes.
> > > > >
> > > >
> > > > I have moved the function declarations to fwu.h. The one function
> > > prototype
> > > > that I have in fwu_mdata.h is the one which has the metadata
> structure as
> > > > one of it's parameters. Same for the ops as well. The get_mdata
> function
> > > > has the metadata structure as its parameter. Are you facing any
> issues
> > > with
> > > > the current structure of the files.
> > >
> > > struct fwu_mdata;
> > > int fwu_get_mdata(struct fwu_**mdata);
> > >
> > > would be good enough?
> > >
> >
> > Yes, I had considered putting this kind of declaration in fwu.h. But I
> > decided against it thinking that any function declaration that involved
> the
> > fwu metadata structure can be put in one file. But I just want to
> > understand if there is some issue in putting these declarations in the
> > fwu_mdata.h. The rest of the function declarations and symbols are put in
> > the fwu.h header. If you see, I only include the fwu.h in the
> > efi_firmware.c and efi_capsule.c.
> >
> >
> > >
> > > I'm not sure whether it is a good idea that we re-use the *same* file
> > > in other software, but I would suggest you to use standard POSIX types
> > > like 'uint32_t' instead of 'u32' anyway.
> > >
> >
> > Hmm, this is on the same lines to the types used in the capsule code.
> That
> > was the primary reason that I stuck with u<size> types. Any issue with
> > using the short type? The Linux kernel seems to be using it.
>
> That is my point. Why should we use linux-specific types in
> other software, especially when we want to import a generic
> header, which is essentially platform agnostic?
>

Well, I was not aware that the header was to be imported in other software,
till Masami explained. I will change the types in the fwu_mdata.h header.

-sughosh


>
> -Takahiro Akashi
>
> > -sughosh
> >
> >
> > >
> > > -Takahiro Akashi
> > >
> > >
> > > > -sughosh
> > > >
> > > >
> > > > > Thank you,
> > > > >
> > > > > > +
> > > > > > +#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..348e9c85f7
> > > > > > --- /dev/null
> > > > > > +++ b/lib/fwu_updates/fwu_mdata.c
> > > > > > @@ -0,0 +1,236 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0+
> > > > > > +/*
> > > > > > + * Copyright (c) 2021, Linaro Limited
> > > > > > + */
> > > > > > +
> > > > > > +#include <fwu_mdata.h>
> > > > > > +
> > > > > > +#include <linux/errno.h>
> > > > > > +#include <linux/types.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)
> > > > > > +{
> > > > > > +       struct fwu_mdata_ops *ops;
> > > > > > +
> > > > > > +       ops = get_fwu_mdata_ops();
> > > > > > +       if (!ops)
> > > > > > +               return -EPROTONOSUPPORT;
> > > > > > +
> > > > > > +       if (!ops->update_active_index) {
> > > > > > +               log_err("update_active_index() method not
> defined for
> > > > > the platform\n");
> > > > > > +               return -ENOSYS;
> > > > > > +       }
> > > > > > +
> > > > > > +       return ops->update_active_index(active_idx);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + * 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)
> > > > > > +{
> > > > > > +       struct fwu_mdata_ops *ops;
> > > > > > +
> > > > > > +       ops = get_fwu_mdata_ops();
> > > > > > +       if (!ops)
> > > > > > +               return -EPROTONOSUPPORT;
> > > > > > +
> > > > > > +       if (!ops->revert_boot_index) {
> > > > > > +               log_err("revert_boot_index() method not defined
> for
> > > the
> > > > > platform\n");
> > > > > > +               return -ENOSYS;
> > > > > > +       }
> > > > > > +
> > > > > > +       return ops->revert_boot_index();
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + * 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
> > > > > > + *
> > > > > > + * 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)
> > > > > > +{
> > > > > > +       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);
> > > > > > +}
> > > > > > +
> > > > > > +/**
> > > > > > + * 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
> > > > > > + *
> > > > > > + * 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);
> > > > > > +}
> > > > > > --
> > > > > > 2.17.1
> > > > > >
> > > > >
> > > > >
> > > > > --
> > > > > Masami Hiramatsu
> > > > >
> > >
>

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

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-19  7:06 ` [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
  2021-12-20  6:14   ` AKASHI Takahiro
@ 2021-12-23  0:53   ` Masami Hiramatsu
  2021-12-23 10:39     ` Sughosh Ganu
  1 sibling, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-23  0: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, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,

Can you move the FWU related configs to lib/fwu_updates/Kconfig ?
FWU multi bank update is an independent feature, thus I think it is
better to have its own Kconfig file and the lib/Kconfig only includes
it.
(I did it on my development series)

Thank you,

2021年12月19日(日) 16:07 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> 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 V1:
> * Call function fwu_update_checks_pass to check if the
>   update can be initiated
> * Do not allow firmware update from efi_init_obj_list as the
>   fwu boot-time checks need to be run
>
>  include/fwu.h                |  18 +++-
>  lib/Kconfig                  |  32 ++++++
>  lib/Makefile                 |   1 +
>  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
>  lib/efi_loader/efi_setup.c   |   3 +-
>  lib/fwu_updates/Makefile     |  11 ++
>  lib/fwu_updates/fwu.c        |  27 +++++
>  7 files changed, 284 insertions(+), 6 deletions(-)
>  create mode 100644 lib/fwu_updates/Makefile
>
> diff --git a/include/fwu.h b/include/fwu.h
> index 2d2e674d6a..bf50fe9277 100644
> --- a/include/fwu.h
> +++ b/include/fwu.h
> @@ -10,14 +10,28 @@
>
>  #include <linux/types.h>
>
> -#define FWU_MDATA_VERSION      0x1
> +#define FWU_MDATA_GUID \
> +       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> +                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> +
> +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> +       EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> +                0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> +
> +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> +       EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> +                0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
>
>  #define FWU_MDATA_GUID \
>         EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
>                  0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
>
> -int fwu_boottime_checks(void);
> +#define FWU_MDATA_VERSION      0x1
> +#define FWU_IMAGE_ACCEPTED     0x1
> +
>  u8 fwu_update_checks_pass(void);
> +int fwu_boottime_checks(void);
> +int fwu_trial_state_ctr_start(void);
>
>  int fwu_get_active_index(u32 *active_idx);
>  int fwu_update_active_index(u32 active_idx);
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 807a4c6ade..7cb306317c 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -835,3 +835,35 @@ 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.
> +
> +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/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..6dfe56bb0f 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,13 @@ 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;
> +
> +__maybe_unused static u32 update_index;
> +__maybe_unused static bool capsule_update;
>
>  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
>  /* for file system access */
> @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
>                         efi_free_pool(abort_reason);
>                         goto out;
>                 }
> +
> +               if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> +                       status = fwu_clear_accept_image(&image_type_id,
> +                                                       update_index);
> +                       if (status < 0) {
> +                               log_err("Unable to clear the accept bit for the image %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("Cleared out accepted bit for Image %pUl\n", &image_type_id);
> +               }
> +
>         }
>
>  out:
> @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> +                               }
> +                       }
> +
>                         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 to %u. Recommend rebooting the system\n",
> +                                               active_idx);
> +                               }
> +                       } 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_accept_image(image_guid);
> +                               if (status < 0) {
> +                                       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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> --- a/lib/efi_loader/efi_setup.c
> +++ b/lib/efi_loader/efi_setup.c
> @@ -298,7 +298,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/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 e964f9b0b1..bb0e1961be 100644
> --- a/lib/fwu_updates/fwu.c
> +++ b/lib/fwu_updates/fwu.c
> @@ -107,6 +107,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
>


-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature
  2021-12-23  0:53   ` Masami Hiramatsu
@ 2021-12-23 10:39     ` Sughosh Ganu
  0 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-23 10:39 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, Jason Liu,
	Tom Rini, Etienne Carriere

hi Masami,

On Thu, 23 Dec 2021 at 06:23, Masami Hiramatsu <masami.hiramatsu@linaro.org>
wrote:

> Hi Sughosh,
>
> Can you move the FWU related configs to lib/fwu_updates/Kconfig ?
> FWU multi bank update is an independent feature, thus I think it is
> better to have its own Kconfig file and the lib/Kconfig only includes
> it.
> (I did it on my development series)
>

Okay, I have moved the FWU config options in a Kconfig file under
lib/fwu_updates/. This gets sourced from lib/Kconfig.

-sughosh


>
> Thank you,
>
> 2021年12月19日(日) 16:07 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > 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 V1:
> > * Call function fwu_update_checks_pass to check if the
> >   update can be initiated
> > * Do not allow firmware update from efi_init_obj_list as the
> >   fwu boot-time checks need to be run
> >
> >  include/fwu.h                |  18 +++-
> >  lib/Kconfig                  |  32 ++++++
> >  lib/Makefile                 |   1 +
> >  lib/efi_loader/efi_capsule.c | 198 ++++++++++++++++++++++++++++++++++-
> >  lib/efi_loader/efi_setup.c   |   3 +-
> >  lib/fwu_updates/Makefile     |  11 ++
> >  lib/fwu_updates/fwu.c        |  27 +++++
> >  7 files changed, 284 insertions(+), 6 deletions(-)
> >  create mode 100644 lib/fwu_updates/Makefile
> >
> > diff --git a/include/fwu.h b/include/fwu.h
> > index 2d2e674d6a..bf50fe9277 100644
> > --- a/include/fwu.h
> > +++ b/include/fwu.h
> > @@ -10,14 +10,28 @@
> >
> >  #include <linux/types.h>
> >
> > -#define FWU_MDATA_VERSION      0x1
> > +#define FWU_MDATA_GUID \
> > +       EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> > +                0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> > +
> > +#define FWU_OS_REQUEST_FW_REVERT_GUID \
> > +       EFI_GUID(0xacd58b4b, 0xc0e8, 0x475f, 0x99, 0xb5, \
> > +                0x6b, 0x3f, 0x7e, 0x07, 0xaa, 0xf0)
> > +
> > +#define FWU_OS_REQUEST_FW_ACCEPT_GUID \
> > +       EFI_GUID(0x0c996046, 0xbcc0, 0x4d04, 0x85, 0xec, \
> > +                0xe1, 0xfc, 0xed, 0xf1, 0xc6, 0xf8)
> >
> >  #define FWU_MDATA_GUID \
> >         EFI_GUID(0x8a7a84a0, 0x8387, 0x40f6, 0xab, 0x41, \
> >                  0xa8, 0xb9, 0xa5, 0xa6, 0x0d, 0x23)
> >
> > -int fwu_boottime_checks(void);
> > +#define FWU_MDATA_VERSION      0x1
> > +#define FWU_IMAGE_ACCEPTED     0x1
> > +
> >  u8 fwu_update_checks_pass(void);
> > +int fwu_boottime_checks(void);
> > +int fwu_trial_state_ctr_start(void);
> >
> >  int fwu_get_active_index(u32 *active_idx);
> >  int fwu_update_active_index(u32 active_idx);
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 807a4c6ade..7cb306317c 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -835,3 +835,35 @@ 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.
> > +
> > +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/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..6dfe56bb0f 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,13 @@ 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;
> > +
> > +__maybe_unused static u32 update_index;
> > +__maybe_unused static bool capsule_update;
> >
> >  #ifdef CONFIG_EFI_CAPSULE_ON_DISK
> >  /* for file system access */
> > @@ -403,10 +411,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 +492,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 +532,24 @@ static efi_status_t efi_capsule_update_firmware(
> >                         efi_free_pool(abort_reason);
> >                         goto out;
> >                 }
> > +
> > +               if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) {
> > +                       status = fwu_clear_accept_image(&image_type_id,
> > +                                                       update_index);
> > +                       if (status < 0) {
> > +                               log_err("Unable to clear the accept bit
> for the image %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("Cleared out accepted bit for Image
> %pUl\n", &image_type_id);
> > +               }
> > +
> >         }
> >
> >  out:
> > @@ -527,6 +584,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 +598,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 +622,64 @@ 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;
> > +                               }
> > +                       }
> > +
> >                         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 to %u. Recommend rebooting the system\n",
> > +                                               active_idx);
> > +                               }
> > +                       } 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_accept_image(image_guid);
> > +                               if (status < 0) {
> > +                                       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 +690,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 +1247,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 +1278,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 +1290,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 +1298,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 1aba71cd96..6601176a2d 100644
> > --- a/lib/efi_loader/efi_setup.c
> > +++ b/lib/efi_loader/efi_setup.c
> > @@ -298,7 +298,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/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 e964f9b0b1..bb0e1961be 100644
> > --- a/lib/fwu_updates/fwu.c
> > +++ b/lib/fwu_updates/fwu.c
> > @@ -107,6 +107,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
> >
>
>
> --
> Masami Hiramatsu
>

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

* Re: [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification
  2021-12-20 10:25       ` AKASHI Takahiro
@ 2021-12-23 10:45         ` Sughosh Ganu
  0 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-23 10:45 UTC (permalink / raw)
  To: AKASHI Takahiro, Sughosh Ganu, u-boot, Patrick Delaunay,
	Patrice Chotard, Heinrich Schuchardt, Alexander Graf,
	Simon Glass, Bin Meng, Ilias Apalodimas, Jose Marinho,
	Grant Likely, Jason Liu, Tom Rini, Etienne Carriere

hi Takahiro,

On Mon, 20 Dec 2021 at 15:55, AKASHI Takahiro <takahiro.akashi@linaro.org>
wrote:

> Hi Sughosh,
>
> On Mon, Dec 20, 2021 at 03:36:37PM +0530, Sughosh Ganu wrote:
> > hi Takahiro,
> >
> > On Mon, 20 Dec 2021 at 11:39, AKASHI Takahiro <
> takahiro.akashi@linaro.org>
> > wrote:
> >
> > > Sughosh,
> > >
> > > On Sun, Dec 19, 2021 at 12:36:03PM +0530, Sughosh Ganu wrote:
> > > > The FWU Multi Bank Update specification requires the Update Agent to
> > > > carry out certain checks at the time of platform boot. The Update
> > > > Agent is the component which is responsible for updating the firmware
> > > > components and maintaining and keeping the metadata in sync.
> > > >
> > > > The spec requires that the Update Agent perform the following checks
> > > > at the time of boot
> > > > * Sanity check of both the metadata copies maintained by the
> platform.
> > > > * Get the boot index passed to U-Boot by the prior stage bootloader
> > > >   and use this value for metadata bookkeeping.
> > > > * Check if the system is booting in Trial State. If the system boots
> > > >   in the Trial State for more than a specified number of boot counts,
> > > >   change the Active Bank to be booting the platform from.
> > > >
> > > > Add these checks in the board initialisation sequence, invoked after
> > > > relocation.
> > > >
> > > > Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
> > > > ---
> > > > Changes since V1:
> > > > * Define a funtion fwu_update_checks_pass to do the checks
> > > >   before initiating the update
> > > > * Log the status of the boottime checks using boottime_check
> > > >   variable and allow system to boot instead of hanging the
> > > >   platform(fwu_boottime_checks)
> > > >
> > > >  common/board_r.c      |   6 ++
> > > >  include/fwu.h         |   3 +
> > > >  lib/fwu_updates/fwu.c | 163
> ++++++++++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 172 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
> > >
> > > Maybe I don't understand your code well.
> > > Why do you want to call fwu_boottime_checks() here?
> > > Why not in CONFIG_EFI_CAPSULE_UPDATE_EARLY (i.e. efi_launch_capsules()
> > > in main_loop())?
> > >
> >
> > These are boot time checks which are to be carried out during platform
> > boot. Do you see any issue if we place the call to fwu_boottime_checks in
> > the init_sequence.
>
> No, I don't see any specific issue right now.
>
> > I would like to avoid having the fwu boot time checks
> > tied up with CONFIG_EFI_CAPSULE_ON_DISK_EARLY.
>
> My question was why you want to avoid that.
> In main_loop(), update_tftp(), as well as efi capsule code, is put there.
> It would be a good practice to have similar functionality called in one
> place.
>

Keeping the call to fwu_boottime_checks separate allows one to try it out
separately from the u-boot shell, by not
enabling CONFIG_EFI_CAPSULE_ON_DISK_EARLY. Also, currently, the FWU code is
closely tied up with the capsule update code. But in the future, if someone
wants to use the fwu metadata without using the capsule format for the
update, that would be possible with the call being separate. But I agree
that this is a hypothetical case which may or may not happen. If you don't
have a strong opinion on this, I would prefer it be kept separate. Let me
know.

-sughosh


> -Takahiro Akashi
>
>
> > -sughosh
> >
> >
> > >
> > > -Takahiro Akashi
> > >
> > > >       run_main_loop,
> > > >  };
> > > > diff --git a/include/fwu.h b/include/fwu.h
> > > > index 5ba437798d..2d2e674d6a 100644
> > > > --- a/include/fwu.h
> > > > +++ b/include/fwu.h
> > > > @@ -16,6 +16,9 @@
> > > >       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_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,
> > > > diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
> > > > new file mode 100644
> > > > index 0000000000..e964f9b0b1
> > > > --- /dev/null
> > > > +++ b/lib/fwu_updates/fwu.c
> > > > @@ -0,0 +1,163 @@
> > > > +// 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;
> > > > +                     }
> > > > +             }
> > > > +     }
> > > > +
> > > > +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	[flat|nested] 38+ messages in thread

* Re: [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2021-12-19  7:06 ` [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
@ 2021-12-24  5:49   ` Masami Hiramatsu
  2021-12-24 10:07     ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-24  5:49 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, Jason Liu,
	Tom Rini, Etienne Carriere

() should Hi Sughosh and Ilias,

I would like to confirm that what the plat_fill_gpt_partition_guids()
should return.

2021年12月19日(日) 16:07 Sughosh Ganu <sughosh.ganu@linaro.org>:

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

So on this platform which uses GPT partition for each bank, it stores
the GUID for each partition.
I think this information will be shown in the ESRT, but not used for
specifying capsule image_type_uuid.

This is strange.
Without this FWU multi-bank update, the array will only have the
image_type UUID.
Thus,  user can use ESRT to confirm what UUID should be specified for
the capsule file. (it has image-type UUID)
(of course that is fixed value on one platform anyway)

And when FWU multi-bank update is enabled, that changes to the
partition GUIDs. But those GUIDs are NOT used when making the capsule
file nor doing the update process, because we should not specify the
bank index directly, right?

We will set a unique image-type UUID on each image entry, and use it
for making a capsule file, but the capsule file itself doesn't specify
the banks. And acceptance/revert capsule file also doesn't specify it.
Acceptance file will also uses image_type UUID, but not the partition
UUID for the bank.

Maybe I'm wrong, but I'm confusing. And this is important for the
platform which doesn't use GPT.

Thank you,


-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2021-12-19  7:05 ` [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
@ 2021-12-24  9:59   ` Masami Hiramatsu
  2021-12-24 17:08     ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-24  9:59 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, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,

2021年12月19日(日) 16:06 Sughosh Ganu <sughosh.ganu@linaro.org>:

> +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(desc->devnum, &part);

This is still GPT depending interface. In my use case (no GPT but raw SPI flash)
I don't have devnum. Moreover, this one is used only from the
fwu_mdata_gpt_blk.c.
Please ensure (and comment) that this is only for GPT user.

> +                       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_update_active_index(u32 active_idx)
> +{
> +       int ret;
> +       void *buf;
> +       struct fwu_mdata *mdata;
> +
> +       if (active_idx > CONFIG_FWU_NUM_BANKS) {
> +               printf("Active index value to be updated is incorrect\n");
> +               return -1;
> +       }
> +
> +       ret = gpt_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 = gpt_update_mdata(mdata);
> +       if (ret < 0) {
> +               log_err("Failed to update FWU metadata partitions\n");
> +               ret = -EIO;
> +       }
> +
> +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);
> +}
> +
> +int fwu_gpt_revert_boot_index(void)
> +{
> +       int ret;
> +       void *buf;
> +       u32 cur_active_index;
> +       struct fwu_mdata *mdata;
> +
> +       ret = gpt_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 = gpt_update_mdata(mdata);

If we have the fwu_update_mdata(), you can make this fwu_gpt_revert_boot_index()
and above fwu_gpt_update_boot_index() platform agnostic. (in that case
"gpt" must
be removed), because there is no dependency to GPT.

> +       if (ret < 0) {
> +               log_err("Failed to update FWU metadata partitions\n");
> +               ret = -EIO;
> +       }
> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +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;
> +       }
> +
> +       if (action == IMAGE_ACCEPT_SET)
> +               bank = mdata->active_index;
> +
> +       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 = gpt_update_mdata(mdata);

This function is also doing the generic things. Only gpt_update_mdata() is
the barrier. I would like to suggest you to add ".update_mdata" member
to the fwu_mdata_ops.


Thank you,

> +                       goto out;
> +               }
> +       }
> +
> +       /* Image not found */
> +       ret = -EINVAL;
> +
> +out:
> +       free(mdata);
> +
> +       return ret;
> +}
> +
> +int fwu_gpt_accept_image(efi_guid_t *img_type_id)
> +{
> +       return fwu_gpt_set_clear_image_accept(img_type_id, 0,
> +                                             IMAGE_ACCEPT_SET);
> +}
> +
> +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,
> +       .update_active_index = fwu_gpt_update_active_index,
> +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> +       .mdata_check = fwu_gpt_mdata_check,
> +       .revert_boot_index = fwu_gpt_revert_boot_index,
> +       .set_accept_image = fwu_gpt_accept_image,
> +       .clear_accept_image = fwu_gpt_clear_accept_image,
> +       .get_mdata = fwu_gpt_get_mdata,
> +};
> --
> 2.17.1
>


-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2021-12-24  5:49   ` Masami Hiramatsu
@ 2021-12-24 10:07     ` Sughosh Ganu
  2021-12-24 10:18       ` Masami Hiramatsu
  0 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-24 10: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, Jason Liu,
	Tom Rini, Etienne Carriere

hi Masami,

On Fri, 24 Dec 2021 at 11:19, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> () should Hi Sughosh and Ilias,
>
> I would like to confirm that what the plat_fill_gpt_partition_guids()
> should return.
>
> 2021年12月19日(日) 16:07 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> > +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;
> > +}
>
> So on this platform which uses GPT partition for each bank, it stores
> the GUID for each partition.
> I think this information will be shown in the ESRT, but not used for
> specifying capsule image_type_uuid.
>
> This is strange.
> Without this FWU multi-bank update, the array will only have the
> image_type UUID.
> Thus,  user can use ESRT to confirm what UUID should be specified for
> the capsule file. (it has image-type UUID)
> (of course that is fixed value on one platform anyway)
>
> And when FWU multi-bank update is enabled, that changes to the
> partition GUIDs. But those GUIDs are NOT used when making the capsule
> file nor doing the update process, because we should not specify the
> bank index directly, right?

The partition GUIDs are the same as ImageTypeId field in the
EFI_FIRMWARE_IMAGE_DESCRIPTOR and the UpdateImageTypeId field in the
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER. This value is the same
as the PartitionTypeGUID field in the GPT partition entry.

ImageTypeId  = UpdateImageTypeId = PartitionTypeGUID

This is the GUID value that is used when generating the capsule.

>
> We will set a unique image-type UUID on each image entry, and use it
> for making a capsule file,

Even with the FWU feature enabled, the PartitionTypeGUID/ImageTypeId
is used for making the capsule. What changes for the FWU feature is
that the value of UpdateImageIndex/ImageIndex that is passed to the
capsule generation tool becomes irrelevant. When the FWU feature is
not enabled, the ImageIndex value that is passed to the capsule
generation tool is important, since this is supposed to correspond to
the DFU alt number -- this ImageIndex value is then used to identify
the partition/address to which the capsule payload is to be written.
With the FWU feature enabled, this value is not obtained from the
capsule, since the partition/address to write the image to is
identified at runtime based on the value of the update bank.

> but the capsule file itself doesn't specify
> the banks. And acceptance/revert capsule file also doesn't specify it.
> Acceptance file will also uses image_type UUID, but not the partition
> UUID for the bank.

The image acceptance capsule will also contain the ImageTypeId. The
Accept bit will be set for the active bank image of the image type
specified in the acceptance capsule.

-sughosh

>
> Maybe I'm wrong, but I'm confusing. And this is important for the
> platform which doesn't use GPT.
>
> Thank you,
>
>
> --
> Masami Hiramatsu

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

* Re: [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2021-12-24 10:07     ` Sughosh Ganu
@ 2021-12-24 10:18       ` Masami Hiramatsu
  2021-12-24 16:59         ` Sughosh Ganu
  0 siblings, 1 reply; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-24 10:18 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, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,

2021年12月24日(金) 19:08 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> hi Masami,
>
> On Fri, 24 Dec 2021 at 11:19, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > () should Hi Sughosh and Ilias,
> >
> > I would like to confirm that what the plat_fill_gpt_partition_guids()
> > should return.
> >
> > 2021年12月19日(日) 16:07 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > > +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;
> > > +}
> >
> > So on this platform which uses GPT partition for each bank, it stores
> > the GUID for each partition.
> > I think this information will be shown in the ESRT, but not used for
> > specifying capsule image_type_uuid.
> >
> > This is strange.
> > Without this FWU multi-bank update, the array will only have the
> > image_type UUID.
> > Thus,  user can use ESRT to confirm what UUID should be specified for
> > the capsule file. (it has image-type UUID)
> > (of course that is fixed value on one platform anyway)
> >
> > And when FWU multi-bank update is enabled, that changes to the
> > partition GUIDs. But those GUIDs are NOT used when making the capsule
> > file nor doing the update process, because we should not specify the
> > bank index directly, right?
>
> The partition GUIDs are the same as ImageTypeId field in the
> EFI_FIRMWARE_IMAGE_DESCRIPTOR and the UpdateImageTypeId field in the
> EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER. This value is the same
> as the PartitionTypeGUID field in the GPT partition entry.
>
> ImageTypeId  = UpdateImageTypeId = PartitionTypeGUID
>
> This is the GUID value that is used when generating the capsule.

So you meant the above "plat_fill_gpt_partition_guids()" fills the
array with ImageTypeId?
Thus, if we have a single image type, the array will be filled with
that single GUID?


> > We will set a unique image-type UUID on each image entry, and use it
> > for making a capsule file,
>
> Even with the FWU feature enabled, the PartitionTypeGUID/ImageTypeId
> is used for making the capsule. What changes for the FWU feature is
> that the value of UpdateImageIndex/ImageIndex that is passed to the
> capsule generation tool becomes irrelevant. When the FWU feature is
> not enabled, the ImageIndex value that is passed to the capsule
> generation tool is important, since this is supposed to correspond to
> the DFU alt number -- this ImageIndex value is then used to identify
> the partition/address to which the capsule payload is to be written.
> With the FWU feature enabled, this value is not obtained from the
> capsule, since the partition/address to write the image to is
> identified at runtime based on the value of the update bank.

OK.

>
> > but the capsule file itself doesn't specify
> > the banks. And acceptance/revert capsule file also doesn't specify it.
> > Acceptance file will also uses image_type UUID, but not the partition
> > UUID for the bank.
>
> The image acceptance capsule will also contain the ImageTypeId. The
> Accept bit will be set for the active bank image of the image type
> specified in the acceptance capsule.

OK, so the Image UUID(image slot for the banks) will not be used in
the process, is that correct?
I would like to confirm this, because this is important for the system
which doesn't use GPT.

Thank you,

>
> -sughosh
>
> >
> > Maybe I'm wrong, but I'm confusing. And this is important for the
> > platform which doesn't use GPT.
> >
> > Thank you,
> >
> >
> > --
> > Masami Hiramatsu



-- 
Masami Hiramatsu

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

* Re: [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata
  2021-12-24 10:18       ` Masami Hiramatsu
@ 2021-12-24 16:59         ` Sughosh Ganu
  0 siblings, 0 replies; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-24 16: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, Jason Liu,
	Tom Rini, Etienne Carriere

hi Masami,

On Fri, 24 Dec 2021 at 15:49, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> 2021年12月24日(金) 19:08 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > hi Masami,
> >
> > On Fri, 24 Dec 2021 at 11:19, Masami Hiramatsu
> > <masami.hiramatsu@linaro.org> wrote:
> > >
> > > () should Hi Sughosh and Ilias,
> > >
> > > I would like to confirm that what the plat_fill_gpt_partition_guids()
> > > should return.
> > >
> > > 2021年12月19日(日) 16:07 Sughosh Ganu <sughosh.ganu@linaro.org>:
> > >
> > > > +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;
> > > > +}
> > >
> > > So on this platform which uses GPT partition for each bank, it stores
> > > the GUID for each partition.
> > > I think this information will be shown in the ESRT, but not used for
> > > specifying capsule image_type_uuid.
> > >
> > > This is strange.
> > > Without this FWU multi-bank update, the array will only have the
> > > image_type UUID.
> > > Thus,  user can use ESRT to confirm what UUID should be specified for
> > > the capsule file. (it has image-type UUID)
> > > (of course that is fixed value on one platform anyway)
> > >
> > > And when FWU multi-bank update is enabled, that changes to the
> > > partition GUIDs. But those GUIDs are NOT used when making the capsule
> > > file nor doing the update process, because we should not specify the
> > > bank index directly, right?
> >
> > The partition GUIDs are the same as ImageTypeId field in the
> > EFI_FIRMWARE_IMAGE_DESCRIPTOR and the UpdateImageTypeId field in the
> > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER. This value is the same
> > as the PartitionTypeGUID field in the GPT partition entry.
> >
> > ImageTypeId  = UpdateImageTypeId = PartitionTypeGUID
> >
> > This is the GUID value that is used when generating the capsule.
>
> So you meant the above "plat_fill_gpt_partition_guids()" fills the
> array with ImageTypeId?

Yes. Please note that the actual api is fwu_plat_fill_partition_guids.
For the ST board, fwu_plat_fill_partition_guids calls
plat_fill_gpt_partition_guids.

> Thus, if we have a single image type, the array will be filled with
> that single GUID?

That will depend on the dfu_alt_info setting and the platform function
fwu_plat_fill_partition_guids defined for the corresponding platform.

>
>
> > > We will set a unique image-type UUID on each image entry, and use it
> > > for making a capsule file,
> >
> > Even with the FWU feature enabled, the PartitionTypeGUID/ImageTypeId
> > is used for making the capsule. What changes for the FWU feature is
> > that the value of UpdateImageIndex/ImageIndex that is passed to the
> > capsule generation tool becomes irrelevant. When the FWU feature is
> > not enabled, the ImageIndex value that is passed to the capsule
> > generation tool is important, since this is supposed to correspond to
> > the DFU alt number -- this ImageIndex value is then used to identify
> > the partition/address to which the capsule payload is to be written.
> > With the FWU feature enabled, this value is not obtained from the
> > capsule, since the partition/address to write the image to is
> > identified at runtime based on the value of the update bank.
>
> OK.
>
> >
> > > but the capsule file itself doesn't specify
> > > the banks. And acceptance/revert capsule file also doesn't specify it.
> > > Acceptance file will also uses image_type UUID, but not the partition
> > > UUID for the bank.
> >
> > The image acceptance capsule will also contain the ImageTypeId. The
> > Accept bit will be set for the active bank image of the image type
> > specified in the acceptance capsule.
>
> OK, so the Image UUID(image slot for the banks) will not be used in
> the process, is that correct?
> I would like to confirm this, because this is important for the system
> which doesn't use GPT.

Yes, only the ImageTypeId will be used. You can check the
implementation for the GPT partitioned block devices in
fwu_gpt_set_clear_image_accept.

-sughosh

>
> Thank you,
>
> >
> > -sughosh
> >
> > >
> > > Maybe I'm wrong, but I'm confusing. And this is important for the
> > > platform which doesn't use GPT.
> > >
> > > Thank you,
> > >
> > >
> > > --
> > > Masami Hiramatsu
>
>
>
> --
> Masami Hiramatsu

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

* Re: [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2021-12-24  9:59   ` Masami Hiramatsu
@ 2021-12-24 17:08     ` Sughosh Ganu
  2021-12-25  6:57       ` Masami Hiramatsu
  0 siblings, 1 reply; 38+ messages in thread
From: Sughosh Ganu @ 2021-12-24 17:08 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, Jason Liu,
	Tom Rini, Etienne Carriere

hi Masami,

On Fri, 24 Dec 2021 at 15:29, Masami Hiramatsu
<masami.hiramatsu@linaro.org> wrote:
>
> Hi Sughosh,
>
> 2021年12月19日(日) 16:06 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> > +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(desc->devnum, &part);
>
> This is still GPT depending interface. In my use case (no GPT but raw SPI flash)
> I don't have devnum. Moreover, this one is used only from the
> fwu_mdata_gpt_blk.c.

You are right. I will change this api to not have the first parameter.
The function will then pass only the identifier which is a void *.

> Please ensure (and comment) that this is only for GPT user.
>
> > +                       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_update_active_index(u32 active_idx)
> > +{
> > +       int ret;
> > +       void *buf;
> > +       struct fwu_mdata *mdata;
> > +
> > +       if (active_idx > CONFIG_FWU_NUM_BANKS) {
> > +               printf("Active index value to be updated is incorrect\n");
> > +               return -1;
> > +       }
> > +
> > +       ret = gpt_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 = gpt_update_mdata(mdata);
> > +       if (ret < 0) {
> > +               log_err("Failed to update FWU metadata partitions\n");
> > +               ret = -EIO;
> > +       }
> > +
> > +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);
> > +}
> > +
> > +int fwu_gpt_revert_boot_index(void)
> > +{
> > +       int ret;
> > +       void *buf;
> > +       u32 cur_active_index;
> > +       struct fwu_mdata *mdata;
> > +
> > +       ret = gpt_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 = gpt_update_mdata(mdata);
>
> If we have the fwu_update_mdata(), you can make this fwu_gpt_revert_boot_index()
> and above fwu_gpt_update_boot_index() platform agnostic. (in that case
> "gpt" must
> be removed), because there is no dependency to GPT.

Okay. I believe you are suggesting having a GPT specific
implementation only for fwu_update_mdata, and move
fwu_gpt_revert_boot_index and fwu_gpt_update_active_index as common
functions with appropriate renaming. I can do that.

-sughosh

>
> > +       if (ret < 0) {
> > +               log_err("Failed to update FWU metadata partitions\n");
> > +               ret = -EIO;
> > +       }
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +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;
> > +       }
> > +
> > +       if (action == IMAGE_ACCEPT_SET)
> > +               bank = mdata->active_index;
> > +
> > +       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 = gpt_update_mdata(mdata);
>
> This function is also doing the generic things. Only gpt_update_mdata() is
> the barrier. I would like to suggest you to add ".update_mdata" member
> to the fwu_mdata_ops.
>
>
> Thank you,
>
> > +                       goto out;
> > +               }
> > +       }
> > +
> > +       /* Image not found */
> > +       ret = -EINVAL;
> > +
> > +out:
> > +       free(mdata);
> > +
> > +       return ret;
> > +}
> > +
> > +int fwu_gpt_accept_image(efi_guid_t *img_type_id)
> > +{
> > +       return fwu_gpt_set_clear_image_accept(img_type_id, 0,
> > +                                             IMAGE_ACCEPT_SET);
> > +}
> > +
> > +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,
> > +       .update_active_index = fwu_gpt_update_active_index,
> > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > +       .mdata_check = fwu_gpt_mdata_check,
> > +       .revert_boot_index = fwu_gpt_revert_boot_index,
> > +       .set_accept_image = fwu_gpt_accept_image,
> > +       .clear_accept_image = fwu_gpt_clear_accept_image,
> > +       .get_mdata = fwu_gpt_get_mdata,
> > +};
> > --
> > 2.17.1
> >
>
>
> --
> Masami Hiramatsu

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

* Re: [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices
  2021-12-24 17:08     ` Sughosh Ganu
@ 2021-12-25  6:57       ` Masami Hiramatsu
  0 siblings, 0 replies; 38+ messages in thread
From: Masami Hiramatsu @ 2021-12-25  6:57 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, Jason Liu,
	Tom Rini, Etienne Carriere

Hi Sughosh,

2021年12月25日(土) 2:08 Sughosh Ganu <sughosh.ganu@linaro.org>:
>
> hi Masami,
>
> On Fri, 24 Dec 2021 at 15:29, Masami Hiramatsu
> <masami.hiramatsu@linaro.org> wrote:
> >
> > Hi Sughosh,
> >
> > 2021年12月19日(日) 16:06 Sughosh Ganu <sughosh.ganu@linaro.org>:
> >
> > > +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(desc->devnum, &part);
> >
> > This is still GPT depending interface. In my use case (no GPT but raw SPI flash)
> > I don't have devnum. Moreover, this one is used only from the
> > fwu_mdata_gpt_blk.c.
>
> You are right. I will change this api to not have the first parameter.
> The function will then pass only the identifier which is a void *.

What about passing image index and bank index ? :-)

>
> > Please ensure (and comment) that this is only for GPT user.
> >
> > > +                       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_update_active_index(u32 active_idx)
> > > +{
> > > +       int ret;
> > > +       void *buf;
> > > +       struct fwu_mdata *mdata;
> > > +
> > > +       if (active_idx > CONFIG_FWU_NUM_BANKS) {
> > > +               printf("Active index value to be updated is incorrect\n");
> > > +               return -1;
> > > +       }
> > > +
> > > +       ret = gpt_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 = gpt_update_mdata(mdata);
> > > +       if (ret < 0) {
> > > +               log_err("Failed to update FWU metadata partitions\n");
> > > +               ret = -EIO;
> > > +       }
> > > +
> > > +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);
> > > +}
> > > +
> > > +int fwu_gpt_revert_boot_index(void)
> > > +{
> > > +       int ret;
> > > +       void *buf;
> > > +       u32 cur_active_index;
> > > +       struct fwu_mdata *mdata;
> > > +
> > > +       ret = gpt_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 = gpt_update_mdata(mdata);
> >
> > If we have the fwu_update_mdata(), you can make this fwu_gpt_revert_boot_index()
> > and above fwu_gpt_update_boot_index() platform agnostic. (in that case
> > "gpt" must
> > be removed), because there is no dependency to GPT.
>
> Okay. I believe you are suggesting having a GPT specific
> implementation only for fwu_update_mdata, and move
> fwu_gpt_revert_boot_index and fwu_gpt_update_active_index as common
> functions with appropriate renaming. I can do that.

Yes, that's right. Then I don't need to repeat the same code :-)

Thank you,

>
> -sughosh
>
> >
> > > +       if (ret < 0) {
> > > +               log_err("Failed to update FWU metadata partitions\n");
> > > +               ret = -EIO;
> > > +       }
> > > +
> > > +out:
> > > +       free(mdata);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +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;
> > > +       }
> > > +
> > > +       if (action == IMAGE_ACCEPT_SET)
> > > +               bank = mdata->active_index;
> > > +
> > > +       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 = gpt_update_mdata(mdata);
> >
> > This function is also doing the generic things. Only gpt_update_mdata() is
> > the barrier. I would like to suggest you to add ".update_mdata" member
> > to the fwu_mdata_ops.
> >
> >
> > Thank you,
> >
> > > +                       goto out;
> > > +               }
> > > +       }
> > > +
> > > +       /* Image not found */
> > > +       ret = -EINVAL;
> > > +
> > > +out:
> > > +       free(mdata);
> > > +
> > > +       return ret;
> > > +}
> > > +
> > > +int fwu_gpt_accept_image(efi_guid_t *img_type_id)
> > > +{
> > > +       return fwu_gpt_set_clear_image_accept(img_type_id, 0,
> > > +                                             IMAGE_ACCEPT_SET);
> > > +}
> > > +
> > > +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,
> > > +       .update_active_index = fwu_gpt_update_active_index,
> > > +       .get_image_alt_num = fwu_gpt_get_image_alt_num,
> > > +       .mdata_check = fwu_gpt_mdata_check,
> > > +       .revert_boot_index = fwu_gpt_revert_boot_index,
> > > +       .set_accept_image = fwu_gpt_accept_image,
> > > +       .clear_accept_image = fwu_gpt_clear_accept_image,
> > > +       .get_mdata = fwu_gpt_get_mdata,
> > > +};
> > > --
> > > 2.17.1
> > >
> >
> >
> > --
> > Masami Hiramatsu



-- 
Masami Hiramatsu

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

end of thread, other threads:[~2021-12-25  6:58 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-19  7:05 [RFC PATCH v2 0/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
2021-12-19  7:05 ` [RFC PATCH v2 1/8] FWU: Add FWU metadata structure and functions for accessing metadata Sughosh Ganu
2021-12-21  0:10   ` Masami Hiramatsu
2021-12-21  4:35     ` Sughosh Ganu
2021-12-21  5:03       ` AKASHI Takahiro
2021-12-21  5:47         ` Sughosh Ganu
2021-12-21  6:01           ` Masami Hiramatsu
2021-12-21  6:08             ` Sughosh Ganu
2021-12-21  6:16           ` AKASHI Takahiro
2021-12-21  6:24             ` Sughosh Ganu
2021-12-19  7:05 ` [RFC PATCH v2 2/8] FWU: Add FWU metadata access functions for GPT partitioned block devices Sughosh Ganu
2021-12-24  9:59   ` Masami Hiramatsu
2021-12-24 17:08     ` Sughosh Ganu
2021-12-25  6:57       ` Masami Hiramatsu
2021-12-19  7:06 ` [RFC PATCH v2 3/8] FWU: stm32mp1: Add helper functions for accessing FWU metadata Sughosh Ganu
2021-12-24  5:49   ` Masami Hiramatsu
2021-12-24 10:07     ` Sughosh Ganu
2021-12-24 10:18       ` Masami Hiramatsu
2021-12-24 16:59         ` Sughosh Ganu
2021-12-19  7:06 ` [RFC PATCH v2 4/8] FWU: STM32MP1: Add support to read boot index from backup register Sughosh Ganu
2021-12-19  7:06 ` [RFC PATCH v2 5/8] EFI: FMP: Add provision to update image's ImageTypeId in image descriptor Sughosh Ganu
2021-12-21  4:53   ` AKASHI Takahiro
2021-12-21  5:34     ` Sughosh Ganu
2021-12-19  7:06 ` [RFC PATCH v2 6/8] FWU: Add boot time checks as highlighted by the FWU specification Sughosh Ganu
2021-12-20  6:09   ` AKASHI Takahiro
2021-12-20 10:06     ` Sughosh Ganu
2021-12-20 10:25       ` AKASHI Takahiro
2021-12-23 10:45         ` Sughosh Ganu
2021-12-19  7:06 ` [RFC PATCH v2 7/8] FWU: Add support for FWU Multi Bank Update feature Sughosh Ganu
2021-12-20  6:14   ` AKASHI Takahiro
2021-12-20  9:48     ` Sughosh Ganu
2021-12-20 13:13       ` Masami Hiramatsu
2021-12-20 16:36         ` Tom Rini
2021-12-20 23:30           ` Masami Hiramatsu
2021-12-20 23:57             ` Tom Rini
2021-12-23  0:53   ` Masami Hiramatsu
2021-12-23 10:39     ` Sughosh Ganu
2021-12-19  7:06 ` [RFC PATCH v2 8/8] FWU: cmd: Add a command to read FWU metadata 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.