From: Dinesh Maniyam <[email protected]> Add the SOCFPGA_RSU_MULTIBOOT feature so the SPL selects the U-Boot proper (SSBL) image, environment and FIT that pair with the RSU sub-partition the SPL itself booted from. rsu_spl.c reads the RSU sub-partition table (SPT), locates the SSBL.<slot> partition matching the running SPL slot and exposes:
- spl_spi_get_uboot_offs() : SSBL offset for SPI boot, - rsu_spl_mmc_filename() : u-boot_<slot>.itb/.img for FAT/MMC boot, - rsu_spl_mmc_env_name() : matching environment file name, - env_sf_get_env_offset() : environment offset within the SSBL slot. The generic SPL/env code grows small, default-off hooks for this: spl_mmc.c and env/fat.c call weak filename helpers (default -ENOENT, overridden by rsu_spl.c), and env/sf.c gains a weak env_sf_get_env_offset() helper (default CONFIG_ENV_OFFSET) so the SPI environment offset can be computed at runtime instead of redefining the CONFIG symbol. SPL_SOCFPGA_RSU_SSBL_FALLBACK bounds the SSBL slot size used when the SPT lookup fails so the environment-offset math cannot underflow. Signed-off-by: Dinesh Maniyam <[email protected]> --- arch/arm/mach-socfpga/Kconfig | 21 + arch/arm/mach-socfpga/Makefile | 5 + arch/arm/mach-socfpga/include/mach/rsu_spl.h | 14 + arch/arm/mach-socfpga/rsu_spl.c | 388 +++++++++++++++++++ common/spl/spl_mmc.c | 24 +- env/fat.c | 64 ++- env/sf.c | 33 +- include/env_internal.h | 11 + 8 files changed, 541 insertions(+), 19 deletions(-) create mode 100644 arch/arm/mach-socfpga/include/mach/rsu_spl.h create mode 100644 arch/arm/mach-socfpga/rsu_spl.c diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index e9d675344f7..889dcc825b0 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -28,6 +28,27 @@ config SOCFPGA_RSU_MULTIFLASH spans the RSU sub-partition layout across all of them. Leave disabled for the common single-flash layout. +config SOCFPGA_RSU_MULTIBOOT + bool "Enable RSU SPL multiboot SSBL selection" + depends on ARCH_SOCFPGA_SOC64 && SPL && SPI_FLASH + help + Select the second-stage boot loader (SSBL, i.e. U-Boot proper) + image based on the RSU sub-partition the SPL was loaded from. + SPL reads the RSU sub-partition table (SPT) to locate the SSBL + partition that pairs with the currently running SPL image and + loads U-Boot proper, its environment and FIT from there. This + keeps a multi-image RSU layout self-consistent across updates. + +config SPL_SOCFPGA_RSU_SSBL_FALLBACK + int "RSU SPL fallback SSBL slot size (MiB)" + depends on SOCFPGA_RSU_MULTIBOOT + default 8 + range 1 64 + help + Conservative upper bound (in MiB) for the SSBL slot used when the + SPT lookup fails, so the environment-offset math in env/sf.c cannot + underflow. Override only if the board's SSBL exceeds the default. + config SOCFPGA_SECURE_VAB_AUTH bool "Enable boot image authentication with Secure Device Manager" depends on ARCH_SOCFPGA_AGILEX || ARCH_SOCFPGA_N5X || \ diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 109af31ceb8..14410cee149 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -147,6 +147,11 @@ obj-$(CONFIG_ARMV8_PSCI) += smc_rsu_s10.o endif endif +# RSU SPL multiboot selects the SSBL (U-Boot proper) image to load; the +# helpers are consumed from both SPL (spl_mmc/spl_spi) and U-Boot proper +# (env/fat, env/sf), so build for both. +obj-$(CONFIG_SOCFPGA_RSU_MULTIBOOT) += rsu_spl.o + ifdef CONFIG_ARCH_SOCFPGA_GEN5 # QTS-generated config file wrappers CFLAGS_wrap_iocsr_config.o += -I$(srctree)/board/$(BOARDDIR) diff --git a/arch/arm/mach-socfpga/include/mach/rsu_spl.h b/arch/arm/mach-socfpga/include/mach/rsu_spl.h new file mode 100644 index 00000000000..c9507b4d934 --- /dev/null +++ b/arch/arm/mach-socfpga/include/mach/rsu_spl.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022-2023 Intel Corporation <www.intel.com> + */ + +#ifndef _RSU_S10_SPL_H_ +#define _RSU_S10_SPL_H_ + +#include <asm/arch/rsu_s10.h> + +u32 rsu_spl_ssbl_address(bool is_qspi_imge_check); +u32 rsu_spl_ssbl_size(bool is_qspi_imge_check); + +#endif /* _RSU_S10_SPL_H_ */ diff --git a/arch/arm/mach-socfpga/rsu_spl.c b/arch/arm/mach-socfpga/rsu_spl.c new file mode 100644 index 00000000000..a3145cce9c3 --- /dev/null +++ b/arch/arm/mach-socfpga/rsu_spl.c @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022-2023 Intel Corporation <www.intel.com> + * Copyright (C) 2026 Altera Corporation <www.altera.com> + */ + +#include <env_internal.h> +#include <log.h> +#include <spi.h> +#include <spi_flash.h> +#include <stdio.h> +#include <dm/device.h> +#include <asm/arch/mailbox_s10.h> +#include <asm/arch/rsu.h> +#include <asm/arch/rsu_flash_if.h> +#include <asm/arch/rsu_s10.h> +#include <asm/arch/rsu_spl.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/sizes.h> +#include <linux/string.h> + +#define SSBL_PART_PREFIX "SSBL." +#define RSU_ADDR_MASK 0xFFFFFFFF +#define RSU_ADDR_SHIFT 32 +#define UBOOT_ENV_EXT ".env" +#define UBOOT_IMG_EXT ".img" +#define UBOOT_ITB_EXT ".itb" +#define UBOOT_ENV_PREFIX "u-boot_" +#define UBOOT_ENV_REDUND_PREFIX "u-boot-redund_" +#define UBOOT_PREFIX "u-boot_" +#define FACTORY_IMG_NAME "FACTORY_IM" + +#define RSU_SPL_SPT_SLOT_MAX 127 + +/* Bytes; pairs with CONFIG_SYS_SPI_U_BOOT_OFFS so env-offset math cannot underflow. */ +#define RSU_SPL_SSBL_FALLBACK_BYTES \ + (CONFIG_SPL_SOCFPGA_RSU_SSBL_FALLBACK * SZ_1M) + +static unsigned int rsu_spl_spt_nentries(const struct socfpga_rsu_s10_spt *spt) +{ + if (spt->magic_number != RSU_S10_SPT_MAGIC_NUMBER) + return 0; + if (spt->entries > RSU_SPL_SPT_SLOT_MAX) + return RSU_SPL_SPT_SLOT_MAX; + return spt->entries; +} + +static int get_spl_slot(struct socfpga_rsu_s10_spt *rsu_spt, + size_t rsu_spt_size, int *crt_spt_index) +{ + u32 rsu_spt0_offset = 0, rsu_spt1_offset = 0; + u32 spt_offset[4] = {0}; + struct rsu_status_info rsu_status = {0}; +#ifdef CONFIG_DM_SPI_FLASH + struct udevice *flash; +#else + struct spi_flash *flash; +#endif + unsigned int nentries; + int i; + int pret; + int ret = -EINVAL; + + /* get rsu status */ + if (mbox_rsu_status((u32 *)&rsu_status, sizeof(rsu_status) / 4)) { + puts("RSU: Error - mbox_rsu_status failed!\n"); + return -EOPNOTSUPP; + } + + /* get spt offsets */ + if (mbox_rsu_get_spt_offset(spt_offset, 4)) { + puts("RSU: Error - mbox_rsu_get_spt_offset failed!\n"); + return -EINVAL; + } + + rsu_spt0_offset = spt_offset[SPT0_INDEX]; + rsu_spt1_offset = spt_offset[SPT1_INDEX]; + + pret = rsu_mtd_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SOCFPGA_RSU_SF_CS, &flash); + if (pret) { + printf("RSU: Error - rsu_mtd_probe failed (%d)!\n", pret); + return pret; + } + + /* read spt0 */ + pret = rsu_mtd_read(flash, rsu_spt0_offset, rsu_spt_size, rsu_spt); + if (pret) { + printf("RSU: Error - rsu_mtd_read spt0 failed (%d)!\n", pret); + ret = pret; + goto out; + } + + /* if spt0 does not have the correct magic number */ + if (rsu_spt->magic_number != RSU_S10_SPT_MAGIC_NUMBER) { + /* read spt1 */ + pret = rsu_mtd_read(flash, rsu_spt1_offset, rsu_spt_size, rsu_spt); + if (pret) { + printf("RSU: Error - rsu_mtd_read spt1 failed (%d)!\n", + pret); + ret = pret; + goto out; + } + + /* bail out if spt1 does not have the correct magic number */ + if (rsu_spt->magic_number != RSU_S10_SPT_MAGIC_NUMBER) { + printf("RSU: Error: spt table magic number not match 0x%08x!\n", + rsu_spt->magic_number); + goto out; + } + } + + nentries = rsu_spl_spt_nentries(rsu_spt); + if (!nentries) + goto out; + + /* Flash may omit NUL in 16-byte names; cap strings for strstr/printf safety */ + for (i = 0; i < (int)nentries; i++) + rsu_spt->spt_slot[i].name[MAX_PART_NAME_LENGTH - 1] = '\0'; + + /* display status */ + debug("RSU current image: 0x%08x\n", (u32)rsu_status.current_image); + debug("RSU state: 0x%08x\n", rsu_status.state); + debug("RSU error location: 0x%08x\n", rsu_status.error_location); + debug("RSU error details: 0x%08x\n", rsu_status.error_details); + + /* display partitions */ + for (i = 0; i < (int)nentries; i++) { + debug("RSU: Partition '%s' start=0x%08x length=0x%08x\n", + rsu_spt->spt_slot[i].name, rsu_spt->spt_slot[i].offset[0], + rsu_spt->spt_slot[i].length); + } + + /* locate the SPT entry for currently loaded image */ + for (i = 0; i < (int)nentries; i++) { + if (((rsu_status.current_image & RSU_ADDR_MASK) == + rsu_spt->spt_slot[i].offset[0]) && + ((rsu_status.current_image >> RSU_ADDR_SHIFT) == + rsu_spt->spt_slot[i].offset[1])) { + *crt_spt_index = i; + ret = 0; + goto out; + } + } + + puts("RSU: Error - could not locate SPL partition in the SPT table!\n"); +out: + /* Release the probed SPI flash; no-op under DM_SPI_FLASH. */ + rsu_mtd_unclaim(flash); + return ret; +} + +static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot) +{ + struct socfpga_rsu_s10_spt rsu_spt = {0}; + int crt_spt_index = -EINVAL; + char *result; + unsigned int nentries; + int i, ret; + + rsu_ssbl_slot->offset[0] = -EINVAL; + + ret = get_spl_slot(&rsu_spt, sizeof(rsu_spt), &crt_spt_index); + if (ret) { + puts("RSU: Error - could not locate partition in the SPT table!\n"); + return ret; + } + + nentries = rsu_spl_spt_nentries(&rsu_spt); + + /* locate the u-boot proper(SSBL) partition and return its address */ + for (i = 0; i < (int)nentries; i++) { + /* get the substring ptr to the first occurrence of SSBL. prefix */ + result = strstr(rsu_spt.spt_slot[i].name, SSBL_PART_PREFIX); + + /* skip if not found the SSBL prefix */ + if (!result) + continue; + + /* check if the prefix is located at the first */ + if (result == rsu_spt.spt_slot[i].name) { + /* move to the substring after SSBL. prefix */ + result += strlen(SSBL_PART_PREFIX); + + /* compare SPL's spt name after the prefix */ + if (!strncmp(result, rsu_spt.spt_slot[crt_spt_index].name, + MAX_PART_NAME_LENGTH - strlen(SSBL_PART_PREFIX)) || + !strncmp(result, rsu_spt.spt_slot[crt_spt_index].name, + strlen(FACTORY_IMG_NAME))) { + printf("RSU: found SSBL partition %s at address 0x%08x.\n", + result, (int)rsu_spt.spt_slot[i].offset[0]); + memcpy(rsu_ssbl_slot, &rsu_spt.spt_slot[i], + sizeof(struct socfpga_rsu_s10_spt_slot)); + + return 0; + } + } + } + + /* fail to find u-boot proper(SSBL) */ + if (crt_spt_index >= 0 && crt_spt_index < (int)nentries) + printf("RSU: Error - could not find u-boot proper partition SSBL.%s!\n", + rsu_spt.spt_slot[crt_spt_index].name); + else + puts("RSU: Error - could not find u-boot proper (SSBL) partition!\n"); + + return -EINVAL; +} + +int rsu_spl_mmc_filename(char *filename, int max_size) +{ + struct socfpga_rsu_s10_spt rsu_spt = {0}; + int crt_spt_index = -EINVAL; + int ret; + + if (!filename) { + printf("RSU: filename is NULL!\n"); + return -ENOENT; + } + + /* + * max_size is `int` for ABI reasons but used as size_t below; + * reject non-positive up front so it cannot sign-extend. + */ + if (max_size <= 0) + return -EINVAL; + + if ((strlen(UBOOT_PREFIX) + MAX_PART_NAME_LENGTH + strlen(UBOOT_ITB_EXT)) + > (size_t)max_size) + return -ENAMETOOLONG; + + ret = get_spl_slot(&rsu_spt, sizeof(rsu_spt), &crt_spt_index); + if (ret) { + if (ret == -EOPNOTSUPP) { + puts("RSU: Error - mbox_rsu_status failed! Check for RSU image.\n"); + return -EOPNOTSUPP; + } + + panic("ERROR: could not find u-boot proper (SSBL) for MMC load"); + } + + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT)) + ret = snprintf(filename, (size_t)max_size, "%s%s%s", UBOOT_PREFIX, + rsu_spt.spt_slot[crt_spt_index].name, UBOOT_ITB_EXT); + else + ret = snprintf(filename, (size_t)max_size, "%s%s%s", UBOOT_PREFIX, + rsu_spt.spt_slot[crt_spt_index].name, UBOOT_IMG_EXT); + + if (ret < 0 || ret >= max_size) + return -ENAMETOOLONG; + + printf("%s, filename: %s\n", __func__, filename); + return 0; +} + +int rsu_spl_mmc_env_name(char *filename, int max_size, bool redund) +{ + struct socfpga_rsu_s10_spt rsu_spt = {0}; + int crt_spt_index = -EINVAL; + int ret; + + if (!filename) { + printf("RSU: filename is NULL!\n"); + return -ENOENT; + } + + /* Same signed/unsigned guard as rsu_spl_mmc_filename(). */ + if (max_size <= 0) + return -EINVAL; + + /* + * Only one of UBOOT_ENV_REDUND_PREFIX / UBOOT_ENV_PREFIX is used + * per call; size against the chosen one so a buffer that actually + * fits is not falsely rejected. + */ + if ((strlen(redund ? UBOOT_ENV_REDUND_PREFIX : UBOOT_ENV_PREFIX) + + MAX_PART_NAME_LENGTH + strlen(UBOOT_ENV_EXT)) > (size_t)max_size) + return -ENAMETOOLONG; + + ret = get_spl_slot(&rsu_spt, sizeof(rsu_spt), &crt_spt_index); + if (ret) { + if (ret == -EOPNOTSUPP) { + puts("RSU: Error - mbox_rsu_status failed! Check for RSU image.\n"); + return -EOPNOTSUPP; + } + + /* should throw error if cannot find u-boot proper(SSBL) in MMC */ + printf("ERROR: could not find u-boot.env!"); + return ret; + } + + if (redund) + ret = snprintf(filename, (size_t)max_size, "%s%s%s", + UBOOT_ENV_REDUND_PREFIX, + rsu_spt.spt_slot[crt_spt_index].name, + UBOOT_ENV_EXT); + else + ret = snprintf(filename, (size_t)max_size, "%s%s%s", + UBOOT_ENV_PREFIX, + rsu_spt.spt_slot[crt_spt_index].name, + UBOOT_ENV_EXT); + + if (ret < 0 || ret >= max_size) + return -ENAMETOOLONG; + + printf("%s, filename: %s\n", __func__, filename); + return 0; +} + +u32 rsu_spl_ssbl_address(bool is_qspi_imge_check) +{ + int ret; + struct socfpga_rsu_s10_spt_slot rsu_ssbl_slot = {0}; + + ret = get_ssbl_slot(&rsu_ssbl_slot); + if (ret) { + if (ret == -EOPNOTSUPP) { + puts("RSU: Error - mbox_rsu_status failed! Check for RSU image.\n"); + return CONFIG_SYS_SPI_U_BOOT_OFFS; + } + + /* should throw error if cannot find u-boot proper(SSBL) address */ + if (is_qspi_imge_check) { + panic("ERROR: could not find u-boot proper(SSBL) address!"); + } else { + printf("ERROR: could not find u-boot env address!"); + return CONFIG_SYS_SPI_U_BOOT_OFFS; + } + } + + if (!rsu_ssbl_slot.length) { + if (is_qspi_imge_check) + panic("ERROR: could not find u-boot proper(SSBL) size!"); + /* No log here; the size() variant reports it. */ + return CONFIG_SYS_SPI_U_BOOT_OFFS; + } + + printf("RSU: Success found SSBL at offset: %08x.\n", + rsu_ssbl_slot.offset[0]); + return rsu_ssbl_slot.offset[0]; +} + +u32 rsu_spl_ssbl_size(bool is_qspi_imge_check) +{ + int ret; + struct socfpga_rsu_s10_spt_slot rsu_ssbl_slot = {0}; + + /* check for valid u-boot proper(SSBL) address for the size */ + ret = get_ssbl_slot(&rsu_ssbl_slot); + if (ret) { + if (ret == -EOPNOTSUPP) { + printf("ERROR: Invalid address, could not retrieve SSBL size!"); + return RSU_SPL_SSBL_FALLBACK_BYTES; + } + + /* should throw error if cannot find u-boot proper(SSBL) address */ + if (is_qspi_imge_check) { + panic("ERROR: could not find u-boot proper(SSBL) address!"); + } else { + printf("ERROR: could not find u-boot env address!"); + return RSU_SPL_SSBL_FALLBACK_BYTES; + } + } + + if (!rsu_ssbl_slot.length) { + /* throw error if cannot find u-boot proper(SSBL) size */ + printf("ERROR: could not retrieve u-boot proper(SSBL) size!"); + if (is_qspi_imge_check) + panic("ERROR: could not find u-boot proper(SSBL) size!"); + return RSU_SPL_SSBL_FALLBACK_BYTES; + } + + printf("RSU: Success found SSBL with length: %08x.\n", + rsu_ssbl_slot.length); + return rsu_ssbl_slot.length; +} + +unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash) +{ + return rsu_spl_ssbl_address(true); +} + +u32 env_sf_get_env_offset(void) +{ + /* Place the environment at the tail of the selected SSBL slot. */ + return rsu_spl_ssbl_address(false) + rsu_spl_ssbl_size(false) - + CONFIG_ENV_SIZE; +} diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index cc16709dc9b..e4002591605 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -11,6 +11,7 @@ #include <spl.h> #include <spl_load.h> #include <linux/compiler.h> +#include <linux/sizes.h> #include <errno.h> #include <mmc.h> #include <image.h> @@ -456,11 +457,32 @@ int spl_mmc_load(struct spl_image_info *spl_image, return ret; } +#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT) +__weak int rsu_spl_mmc_filename(char *filename, int max_size) +{ + return -ENOENT; +} +#endif + int spl_mmc_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { +#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT) + char filename[SZ_256] = {0}; + int ret; + + ret = rsu_spl_mmc_filename(filename, SZ_256); + if (ret) { + printf("RSU: multiboot filename not found\n"); + return ret; + } + + printf("%s: boot from filename: %s\n", __func__, filename); +#endif return spl_mmc_load(spl_image, bootdev, -#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME +#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT) + filename, +#elif defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, #else NULL, diff --git a/env/fat.c b/env/fat.c index 7e164822383..9490be7d6f9 100644 --- a/env/fat.c +++ b/env/fat.c @@ -22,6 +22,7 @@ #include <virtio.h> #include <asm/cache.h> #include <asm/global_data.h> +#include <linux/sizes.h> #include <linux/stddef.h> #ifdef CONFIG_XPL_BUILD @@ -35,6 +36,37 @@ DECLARE_GLOBAL_DATA_PTR; +#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT) +__weak int rsu_spl_mmc_env_name(char *filename, int max_size, bool redund) +{ + return -ENOENT; +} +#endif + +/* + * Resolve the FAT filename that holds the environment. With RSU multiboot + * the name is derived at runtime from the booted SSBL slot (written into + * @buf); otherwise it is the static CONFIG_ENV_FAT_FILE[_REDUND]. Returns + * NULL on failure. + */ +static const char *env_fat_filename(char *buf, int size, bool redund) +{ +#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT) + if (rsu_spl_mmc_env_name(buf, size, redund)) { + printf("RSU: multiboot env filename not found\n"); + return NULL; + } + + return buf; +#else +#ifdef CONFIG_ENV_REDUNDANT + if (redund) + return CONFIG_ENV_FAT_FILE_REDUND; +#endif + return CONFIG_ENV_FAT_FILE; +#endif +} + __weak const char *env_fat_get_intf(void) { return (const char *)CONFIG_ENV_FAT_INTERFACE; @@ -62,13 +94,18 @@ static int env_fat_save(void) env_t __aligned(ARCH_DMA_MINALIGN) env_new; struct blk_desc *dev_desc = NULL; struct disk_partition info; - const char *file = CONFIG_ENV_FAT_FILE; + char env_file[SZ_256] = {0}; + const char *file; int dev, part; int err; loff_t size; const char *ifname = env_fat_get_intf(); const char *dev_and_part = env_fat_get_dev_part(); + file = env_fat_filename(env_file, sizeof(env_file), false); + if (!file) + return 1; + err = env_export(&env_new); if (err) return err; @@ -89,8 +126,11 @@ static int env_fat_save(void) } #ifdef CONFIG_ENV_REDUNDANT - if (gd->env_valid == ENV_VALID) - file = CONFIG_ENV_FAT_FILE_REDUND; + if (gd->env_valid == ENV_VALID) { + file = env_fat_filename(env_file, sizeof(env_file), true); + if (!file) + return 1; + } #endif err = file_fat_write(file, (void *)&env_new, 0, sizeof(env_t), &size); @@ -120,6 +160,8 @@ static int env_fat_load(void) #endif struct blk_desc *dev_desc = NULL; struct disk_partition info; + char env_file[SZ_256] = {0}; + const char *file; int dev, part; int err1; const char *ifname = env_fat_get_intf(); @@ -162,9 +204,17 @@ static int env_fat_load(void) goto err_env_relocate; } - err1 = file_fat_read(CONFIG_ENV_FAT_FILE, buf1, CONFIG_ENV_SIZE); + file = env_fat_filename(env_file, sizeof(env_file), false); + if (!file) + goto err_env_relocate; + + err1 = file_fat_read(file, buf1, CONFIG_ENV_SIZE); #ifdef CONFIG_ENV_REDUNDANT - err2 = file_fat_read(CONFIG_ENV_FAT_FILE_REDUND, buf2, CONFIG_ENV_SIZE); + file = env_fat_filename(env_file, sizeof(env_file), true); + if (!file) + goto err_env_relocate; + + err2 = file_fat_read(file, buf2, CONFIG_ENV_SIZE); err1 = (err1 >= 0) ? 0 : -1; err2 = (err2 >= 0) ? 0 : -1; @@ -175,8 +225,8 @@ static int env_fat_load(void) * This printf is embedded in the messages from env_save that * will calling it. The missing \n is intentional. */ - printf("Unable to read \"%s\" from %s%d:%d... \n", - CONFIG_ENV_FAT_FILE, ifname, dev, part); + printf("Unable to read \"%s\" from %s%d:%d...\n", + file, ifname, dev, part); goto err_env_relocate; } diff --git a/env/sf.c b/env/sf.c index 14c35324e64..6cdb0e4a632 100644 --- a/env/sf.c +++ b/env/sf.c @@ -38,6 +38,17 @@ static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND; DECLARE_GLOBAL_DATA_PTR; +/* + * Offset of the primary environment within the SPI flash. Defaults to the + * static CONFIG_ENV_OFFSET, but boards may override this weak helper to + * compute the offset at runtime (e.g. RSU multiboot derives it from the + * SSBL slot the SPL booted from). + */ +__weak u32 env_sf_get_env_offset(void) +{ + return CONFIG_ENV_OFFSET; +} + __weak int spi_get_env_dev(void) { #ifdef CONFIG_ENV_SPI_BUS @@ -98,9 +109,9 @@ static int env_sf_save(void) if (gd->env_valid == ENV_VALID) { env_new_offset = CONFIG_ENV_OFFSET_REDUND; - env_offset = CONFIG_ENV_OFFSET; + env_offset = env_sf_get_env_offset(); } else { - env_new_offset = CONFIG_ENV_OFFSET; + env_new_offset = env_sf_get_env_offset(); env_offset = CONFIG_ENV_OFFSET_REDUND; } @@ -182,7 +193,7 @@ static int env_sf_load(void) if (ret) goto out; - read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, + read1_fail = spi_flash_read(env_flash, env_sf_get_env_offset(), CONFIG_ENV_SIZE, tmp_env1); read2_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND, CONFIG_ENV_SIZE, tmp_env2); @@ -217,7 +228,7 @@ static int env_sf_save(void) /* Is the sector larger than the env (i.e. embedded) */ if (sect_size > CONFIG_ENV_SIZE) { saved_size = sect_size - CONFIG_ENV_SIZE; - saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE; + saved_offset = env_sf_get_env_offset() + CONFIG_ENV_SIZE; saved_buffer = malloc(saved_size); if (!saved_buffer) { ret = -ENOMEM; @@ -237,14 +248,14 @@ static int env_sf_save(void) sector = DIV_ROUND_UP(CONFIG_ENV_SIZE, sect_size); puts("Erasing SPI flash..."); - ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, - sector * sect_size); + ret = spi_flash_erase(env_flash, env_sf_get_env_offset(), + sector * sect_size); if (ret) goto done; puts("Writing to SPI flash..."); - ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, - CONFIG_ENV_SIZE, &env_new); + ret = spi_flash_write(env_flash, env_sf_get_env_offset(), + CONFIG_ENV_SIZE, &env_new); if (ret) goto done; @@ -284,7 +295,7 @@ static int env_sf_load(void) goto out; ret = spi_flash_read(env_flash, - CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf); + env_sf_get_env_offset(), CONFIG_ENV_SIZE, buf); if (ret) { env_set_default("spi_flash_read() failed", 0); goto err_read; @@ -314,7 +325,7 @@ static int env_sf_erase(void) return ret; memset(&env, 0, sizeof(env_t)); - ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, &env); + ret = spi_flash_write(env_flash, env_sf_get_env_offset(), CONFIG_ENV_SIZE, &env); if (ret) goto done; @@ -391,7 +402,7 @@ static int env_sf_init_early(void) if (ret) goto out; - read1_fail = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, + read1_fail = spi_flash_read(env_flash, env_sf_get_env_offset(), CONFIG_ENV_SIZE, tmp_env1); if (IS_ENABLED(CONFIG_ENV_REDUNDANT)) { diff --git a/include/env_internal.h b/include/env_internal.h index 0589c435e84..8ce200fd6f1 100644 --- a/include/env_internal.h +++ b/include/env_internal.h @@ -273,6 +273,17 @@ const char *env_fat_get_intf(void); * Return: string of device and partition */ char *env_fat_get_dev_part(void); + +/** + * env_sf_get_env_offset() - Provide the offset of the env in SPI flash + * + * It is a weak function allowing boards to override the default offset of + * the U-Boot environment in SPI flash (CONFIG_ENV_OFFSET) with a value + * computed at runtime, e.g. derived from the RSU multiboot SSBL slot. + * + * Return: byte offset of the primary environment within the SPI flash + */ +u32 env_sf_get_env_offset(void); #endif /* DO_DEPS_ONLY */ #endif /* _ENV_INTERNAL_H_ */ -- 2.43.7

