
On Fri, Jan 21, 2022 at 12:31:10AM +0900, Masami Hiramatsu wrote:
Signed-off-by: Masami Hiramatsu masami.hiramatsu@linaro.org
include/fwu.h | 13 ++ lib/fwu_updates/Kconfig | 34 ++++++ lib/fwu_updates/Makefile | 5 - lib/fwu_updates/fwu_mdata_sf.c | 241 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 lib/fwu_updates/fwu_mdata_sf.c
diff --git a/include/fwu.h b/include/fwu.h index 7af94988b7..a013170321 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -64,9 +64,18 @@ int fwu_accept_image(efi_guid_t *img_type_id, u32 bank); int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank);
int fwu_plat_get_update_index(u32 *update_idx); -int fwu_plat_get_blk_desc(struct blk_desc **desc); -int fwu_plat_get_alt_num(void *identifier); int fwu_plat_fill_partition_guids(efi_guid_t **part_guid_arr); void fwu_plat_get_bootidx(void *boot_idx);
+#ifdef CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK +int fwu_plat_get_blk_desc(struct blk_desc **desc); +int fwu_plat_get_alt_num(void *identifier); +#endif
We can (and should) remove "#ifdef ..." from headers.
-Takahiro Akashi
+#ifdef CONFIG_FWU_MULTI_BANK_UPDATE_SF +struct fwu_mdata_ops *fwu_sf_get_fwu_mdata_ops(void); +int fwu_plat_get_image_alt_num(efi_guid_t image_type_id, u32 update_bank,
int *alt_no);
+#endif
#endif /* _FWU_H_ */ diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig index 0940a90747..8a369b9872 100644 --- a/lib/fwu_updates/Kconfig +++ b/lib/fwu_updates/Kconfig @@ -38,3 +38,37 @@ config FWU_REBOOT_AFTER_UPDATE Reboot the machine soon after installing a new firmware and start trial boot. You can disable this option for debugging or FWU development, but recommended to enable it.
+config FWU_MULTI_BANK_UPDATE_GPT_BLK
- bool "Enable FWU Multi Bank Update for GPT on blockdev"
- depends on FWU_MULTI_BANK_UPDATE
- select EFI_PARTITION
- help
Enable FWU Multi Bank Update for GPT on a block device. This
driver depends on GPT and the block device. FWU meatadata and
firmware will be stored on a block device with GPT.
+config FWU_MULTI_BANK_UPDATE_SF
- bool "Enable FWU Multi Bank Update for SPI Flash"
- depends on FWU_MULTI_BANK_UPDATE
- help
Enable FWU Multi Bank Update for SPI flash driver. This
driver does not depend on GPT. Instead, the platform must
provide some APIs and define the offset of the primary and
the secondary metadata.
+config FWU_SF_PRIMARY_MDATA_OFFSET
- hex "The offset of the primary metadata"
- depends on FWU_MULTI_BANK_UPDATE_SF
- help
The offset of the primary metadata on SPI Flash in
hexadecimal.
+config FWU_SF_SECONDARY_MDATA_OFFSET
- hex "The offset of the secondary metadata"
- depends on FWU_MULTI_BANK_UPDATE_SF
- help
The offset of the secondary metadata on SPI Flash in
hexadecimal.
This must NOT be the same offset of the primary
metadata.
diff --git a/lib/fwu_updates/Makefile b/lib/fwu_updates/Makefile index 73099a30cb..80669344f2 100644 --- a/lib/fwu_updates/Makefile +++ b/lib/fwu_updates/Makefile @@ -6,6 +6,5 @@ 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 +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE_GPT_BLK) += fwu_mdata_gpt_blk.o +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE_SF) += fwu_mdata_sf.o diff --git a/lib/fwu_updates/fwu_mdata_sf.c b/lib/fwu_updates/fwu_mdata_sf.c new file mode 100644 index 0000000000..9e3cae7b68 --- /dev/null +++ b/lib/fwu_updates/fwu_mdata_sf.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2021, Linaro Limited
- */
+#include <efi_loader.h> +#include <fwu.h> +#include <fwu_mdata.h> +#include <malloc.h> +#include <memalign.h> +#include <spi.h> +#include <spi_flash.h> +#include <flash.h>
+#include <linux/errno.h> +#include <linux/types.h> +#include <u-boot/crc.h>
+/*
- For the FWU SPI flash driver, the platform must define below functions
- according to its dfu_alt_info.
- */
+extern int fwu_plat_get_image_alt_num(efi_guid_t image_type_id,
u32 update_bank, int *alt_no);
+static struct spi_flash *fwu_spi_flash;
+static int __fwu_sf_get_flash(void) +{
- if (IS_ENABLED(CONFIG_DM_SPI_FLASH)) {
struct udevice *new;
int ret;
ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE,
&new);
if (ret)
return ret;
fwu_spi_flash = dev_get_uclass_priv(new);
- } else {
fwu_spi_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE);
if (!fwu_spi_flash)
return -EIO;
- }
- return 0;
+}
+static int fwu_sf_get_flash(struct spi_flash **flash) +{
- int ret = 0;
- if (!fwu_spi_flash)
ret = __fwu_sf_get_flash();
- *flash = fwu_spi_flash;
- return ret;
+}
+static int sf_load_data(u32 offs, u32 size, void **data) +{
- struct spi_flash *flash;
- int ret;
- ret = fwu_sf_get_flash(&flash);
- if (ret < 0)
return ret;
- *data = memalign(ARCH_DMA_MINALIGN, size);
- if (!*data)
return -ENOMEM;
- ret = spi_flash_read(flash, offs, size, *data);
- if (ret < 0) {
free(*data);
*data = NULL;
- }
- return ret;
+}
+static int sf_save_data(u32 offs, u32 size, void *data) +{
- struct spi_flash *flash;
- u32 sect_size, nsect;
- void *buf;
- int ret;
- ret = fwu_sf_get_flash(&flash);
- if (ret < 0)
return ret;
- sect_size = flash->mtd.erasesize;
- nsect = DIV_ROUND_UP(size, sect_size);
- ret = spi_flash_erase(flash, offs, nsect * sect_size);
- if (ret < 0)
return ret;
- buf = memalign(ARCH_DMA_MINALIGN, size);
- if (!buf)
return -ENOMEM;
- memcpy(buf, data, size);
- ret = spi_flash_write(flash, offs, size, buf);
- free(buf);
- return ret;
+}
+static int fwu_sf_load_mdata(struct fwu_mdata **mdata, u32 offs) +{
- int ret;
- ret = sf_load_data(offs, sizeof(struct fwu_mdata), (void **)mdata);
- if (ret >= 0) {
ret = fwu_verify_mdata(*mdata,
offs == CONFIG_FWU_SF_PRIMARY_MDATA_OFFSET);
if (ret < 0) {
free(*mdata);
*mdata = NULL;
}
- }
- return ret;
+}
+static int fwu_sf_load_primary_mdata(struct fwu_mdata **mdata) +{
- return fwu_sf_load_mdata(mdata, CONFIG_FWU_SF_PRIMARY_MDATA_OFFSET);
+}
+static int fwu_sf_load_secondary_mdata(struct fwu_mdata **mdata) +{
- return fwu_sf_load_mdata(mdata, CONFIG_FWU_SF_SECONDARY_MDATA_OFFSET);
+}
+static int fwu_sf_save_primary_mdata(struct fwu_mdata *mdata) +{
- return sf_save_data(CONFIG_FWU_SF_PRIMARY_MDATA_OFFSET,
sizeof(struct fwu_mdata), mdata);
+}
+static int fwu_sf_save_secondary_mdata(struct fwu_mdata *mdata) +{
- return sf_save_data(CONFIG_FWU_SF_SECONDARY_MDATA_OFFSET,
sizeof(struct fwu_mdata), mdata);
+}
+static int fwu_sf_get_valid_mdata(struct fwu_mdata **mdata) +{
- if (fwu_sf_load_primary_mdata(mdata) == 0)
return 0;
- log_err("Failed to load/verify primary mdata. Try secondary.\n");
- if (fwu_sf_load_secondary_mdata(mdata) == 0)
return 0;
- log_err("Failed to load/verify secondary mdata.\n");
- return -1;
+}
+static int fwu_sf_update_mdata(struct fwu_mdata *mdata) +{
- int ret;
- /* Update mdata crc32 field */
- mdata->crc32 = crc32(0, (void *)&mdata->version,
sizeof(*mdata) - sizeof(u32));
- /* First write the primary mdata */
- ret = fwu_sf_save_primary_mdata(mdata);
- if (ret < 0) {
log_err("Failed to update the primary mdata.\n");
return ret;
- }
- /* And now the replica */
- ret = fwu_sf_save_secondary_mdata(mdata);
- if (ret < 0) {
log_err("Failed to update the secondary mdata.\n");
return ret;
- }
- return 0;
+}
+static int fwu_sf_mdata_check(void) +{
- struct fwu_mdata *primary = NULL, *secondary = NULL;
- int ret;
- ret = fwu_sf_load_primary_mdata(&primary);
- if (ret < 0)
log_err("Failed to read the primary mdata: %d\n", ret);
- ret = fwu_sf_load_secondary_mdata(&secondary);
- if (ret < 0)
log_err("Failed to read the secondary mdata: %d\n", ret);
- if (primary && secondary) {
if (memcmp(primary, secondary, sizeof(struct fwu_mdata))) {
log_err("The primary and the secondary mdata are different\n");
ret = -1;
}
- } else if (primary) {
ret = fwu_sf_save_secondary_mdata(primary);
if (ret < 0)
log_err("Restoring secondary mdata partition failed\n");
- } else if (secondary) {
ret = fwu_sf_save_primary_mdata(secondary);
if (ret < 0)
log_err("Restoring primary mdata partition failed\n");
- }
- free(primary);
- free(secondary);
- return ret;
+}
+static int fwu_sf_get_mdata(struct fwu_mdata **mdata) +{
- return fwu_sf_get_valid_mdata(mdata);
+}
+static struct fwu_mdata_ops fwu_sf_mdata_ops = {
- .get_image_alt_num = fwu_plat_get_image_alt_num,
- .mdata_check = fwu_sf_mdata_check,
- .get_mdata = fwu_sf_get_mdata,
- .update_mdata = fwu_sf_update_mdata,
+};
+struct fwu_mdata_ops *fwu_sf_get_fwu_mdata_ops(void) +{
- return &fwu_sf_mdata_ops;
+}