
From: Masami Hiramatsu masami.hiramatsu@linaro.org
The DeveloperBox platform can support the FWU Multi bank update. SCP firmware will switch the boot mode by DSW3-4 and load the Multi bank update supported TF-A BL2 from 0x600000 offset on the SPI flash. Thus it can co-exist with the legacy boot mode (legacy U-Boot or EDK2).
Signed-off-by: Masami Hiramatsu masami.hiramatsu@linaro.org --- Changes in v3: - Change devicetree to add partitions. - Update fwu_plat_get_alt_num() to find the alt number from the bank index. - Use only 2 partitions for AB update. - Clear platform-mdata's boot_count to finish platform trial boot.
Signed-off-by: Sughosh Ganu sughosh.ganu@linaro.org --- .../synquacer-sc2a11-developerbox-u-boot.dtsi | 15 +- board/socionext/developerbox/Kconfig | 13 ++ board/socionext/developerbox/Makefile | 1 + board/socionext/developerbox/fwu_plat.c | 207 ++++++++++++++++++ include/configs/synquacer.h | 8 + 5 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 board/socionext/developerbox/fwu_plat.c
diff --git a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi index 095727e03c..ab4e3d1c2b 100644 --- a/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi +++ b/arch/arm/dts/synquacer-sc2a11-developerbox-u-boot.dtsi @@ -23,7 +23,7 @@ active_clk_edges; chipselect_num = <1>;
- spi-flash@0 { + spi_flash: spi-flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; @@ -84,11 +84,15 @@ label = "UBoot-Env"; reg = <0x580000 0x80000>; }; - + /* FWU Multi bank update partitions */ partition@600000 { - label = "FIP"; + label = "FIP-Bank0"; reg = <0x600000 0x400000>; }; + partition@a00000 { + label = "FIP-Bank1"; + reg = <0xa00000 0x400000>; + }; }; }; }; @@ -114,6 +118,11 @@ optee { status = "okay"; }; + fwu-mdata { + compatible = "u-boot,fwu-mdata-mtd"; + fwu-mdata-store = <&spi_flash>; + mdata-offsets = <0x500000 0x530000>; + }; }; };
diff --git a/board/socionext/developerbox/Kconfig b/board/socionext/developerbox/Kconfig index c181d26a44..7df6750baf 100644 --- a/board/socionext/developerbox/Kconfig +++ b/board/socionext/developerbox/Kconfig @@ -32,4 +32,17 @@ config SYS_CONFIG_NAME default "synquacer"
endif + +config FWU_MULTI_BANK_UPDATE + select FWU_MDATA_MTD + select DM_SPI_FLASH + select DM_FWU_MDATA + select BOARD_LATE_INIT + +config FWU_NUM_BANKS + default 2 + +config FWU_NUM_IMAGES_PER_BANK + default 1 + endif diff --git a/board/socionext/developerbox/Makefile b/board/socionext/developerbox/Makefile index 4a46de995a..9b80ee38e7 100644 --- a/board/socionext/developerbox/Makefile +++ b/board/socionext/developerbox/Makefile @@ -7,3 +7,4 @@ #
obj-y := developerbox.o +obj-$(CONFIG_FWU_MULTI_BANK_UPDATE) += fwu_plat.o diff --git a/board/socionext/developerbox/fwu_plat.c b/board/socionext/developerbox/fwu_plat.c new file mode 100644 index 0000000000..fd6d0e3659 --- /dev/null +++ b/board/socionext/developerbox/fwu_plat.c @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021, Linaro Limited + */ + +#include <dfu.h> +#include <efi_loader.h> +#include <flash.h> +#include <fwu.h> +#include <fwu_mdata.h> +#include <malloc.h> +#include <memalign.h> +#include <spi.h> +#include <spi_flash.h> + +#include <linux/errno.h> +#include <linux/types.h> +#include <u-boot/crc.h> + +/* SPI Flash accessors */ +static struct spi_flash *plat_spi_flash; + +static int __plat_sf_get_flash(void) +{ + /* TODO: define platform spi-flash somewhere. */ + plat_spi_flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + + return 0; +} + +static int plat_sf_get_flash(struct spi_flash **flash) +{ + int ret = 0; + + if (!plat_spi_flash) + ret = __plat_sf_get_flash(); + + *flash = plat_spi_flash; + + return ret; +} + +static int sf_load_data(u32 offs, u32 size, void **data) +{ + struct spi_flash *flash; + int ret; + + ret = plat_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 = plat_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; +} + +#define PLAT_METADATA_OFFSET 0x510000 +#define PLAT_METADATA_SIZE (sizeof(struct devbox_metadata)) + +struct __packed devbox_metadata { + u32 boot_index; + u32 boot_count; +} *devbox_plat_metadata; + +int fwu_plat_get_alt_num(struct udevice __always_unused *dev, + efi_guid_t *image_id, int *alt_num) +{ + struct fwu_image_bank_info *bank; + struct fwu_mdata *mdata; + int i, ret; + + ret = fwu_get_mdata(&mdata); + if (ret < 0) + return ret; + + /* + * DeveloperBox FWU expects Bank:Image = 1:1, and the dfu_alt_info + * only has the entries for banks. Thus the alt_no should be equal + * to the bank index number. + */ + ret = -ENOENT; + for (i = 0; i < CONFIG_FWU_NUM_BANKS; i++) { + bank = &mdata->img_entry[0].img_bank_info[i]; + if (guidcmp(image_id, &bank->image_uuid) == 0) { + *alt_num = i; + ret = 0; + break; + } + } + + free(mdata); + + return ret; +} + +/* This assumes that user doesn't change system default dfu_alt_info */ +efi_status_t fill_image_type_guid_array(const efi_guid_t __always_unused + *default_guid, + efi_guid_t **part_guid_arr) +{ + int i; + + *part_guid_arr = malloc(sizeof(efi_guid_t) * DEFAULT_DFU_ALT_NUM); + if (!*part_guid_arr) + return EFI_OUT_OF_RESOURCES; + + for (i = 0; i < DEFAULT_DFU_ALT_NUM; i++) + guidcpy((*part_guid_arr + i), &devbox_fip_image_type_guid); + + return EFI_SUCCESS; +} + +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 ret; + + *update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS; + + return ret; +} + +static int devbox_load_plat_metadata(void) +{ + if (devbox_plat_metadata) + return 0; + + return sf_load_data(PLAT_METADATA_OFFSET, PLAT_METADATA_SIZE, + (void **)&devbox_plat_metadata); +} + +void fwu_plat_get_bootidx(void *boot_idx) +{ + u32 *bootidx = boot_idx; + + if (devbox_load_plat_metadata() < 0) + *bootidx = 0; + else + *bootidx = devbox_plat_metadata->boot_index; +} + +int board_late_init(void) +{ + int ret; + + ret = devbox_load_plat_metadata(); + if (ret < 0) + return ret; + + if (devbox_plat_metadata->boot_count) { + /* We are in the platform trial boot. Finish it. */ + devbox_plat_metadata->boot_count = 0; + ret = sf_save_data(PLAT_METADATA_OFFSET, PLAT_METADATA_SIZE, + (void *)devbox_plat_metadata); + if (ret < 0) + return ret; + + pr_debug("FWU: Finish platform trial boot safely.\n"); + } + + return 0; +} diff --git a/include/configs/synquacer.h b/include/configs/synquacer.h index eafcc69e12..14eeb3f57e 100644 --- a/include/configs/synquacer.h +++ b/include/configs/synquacer.h @@ -46,8 +46,16 @@
/* Since U-Boot 64bit PCIe support is limited, disable 64bit MMIO support */
+#ifdef CONFIG_FWU_MULTI_BANK_UPDATE +#define DEFAULT_DFU_ALT_NUM 2 +#define DEFAULT_DFU_ALT_INFO "dfu_alt_info=" \ + "mtd nor1=bank0 raw 600000 400000;" \ + "bank1 raw a00000 400000\0" +#else +#define DEFAULT_DFU_ALT_NUM 1 #define DEFAULT_DFU_ALT_INFO "dfu_alt_info=" \ "mtd nor1=fip.bin raw 600000 400000\0" +#endif
/* GUIDs for capsule updatable firmware images */ #define DEVELOPERBOX_FIP_IMAGE_GUID \