summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKah Jing Lee <kah.jing.lee@intel.com>2022-12-12 15:38:56 +0800
committerLokanathan, Raaj <raaj.lokanathan@intel.com>2023-01-06 15:51:40 +0800
commit7b0c13622eaaa7680a489a35e71f1cc1d38b47e0 (patch)
tree41ebbe1dce4aee7bf0637fa4d50524814e6e2e47
parent8204e3e6f3f9104739547ba127f2120846e9e9d3 (diff)
downloadu-boot-socfpga-7b0c13622eaaa7680a489a35e71f1cc1d38b47e0.tar.gz
arch: arm: rsu: Multiboot selection Uboot SSBL for RSU (MMC)
Use different Uboot in MMC for each RSU bitstream based on the SPL. Selection is based on the current partition of the running SPL. Based on the SPL partition, multiboot will search for uboot-proper name in MMC to load. E.g: P1 SPL will select u-boot_P1.itb from MMC to load Signed-off-by: Kah Jing Lee <kah.jing.lee@intel.com> --- v2: - Rework based on review - Add the check for FACTORY_IMAGE to only check 15 chars limit for a match (SSBL.FACTORY_IM), since this is the limitation in SPT partition name of 2 bytes --- v3: - Rework based on review - Add a flag to avoid panic triggered when env file is not found in both MMC & QSPI, since current flow allow the env file to find from MMC, QSPI, and NAND --- v4: - Rework based on review ---
-rw-r--r--arch/arm/mach-socfpga/include/mach/rsu_spl.h4
-rw-r--r--arch/arm/mach-socfpga/rsu_spl.c199
-rw-r--r--common/spl/spl_mmc.c23
-rw-r--r--env/fat.c80
-rw-r--r--env/sf.c4
5 files changed, 268 insertions, 42 deletions
diff --git a/arch/arm/mach-socfpga/include/mach/rsu_spl.h b/arch/arm/mach-socfpga/include/mach/rsu_spl.h
index f9cc49034e..d0d8b664b4 100644
--- a/arch/arm/mach-socfpga/include/mach/rsu_spl.h
+++ b/arch/arm/mach-socfpga/include/mach/rsu_spl.h
@@ -8,7 +8,7 @@
#define _RSU_S10_SPL_H_
#include <asm/arch/rsu_s10.h>
-u32 rsu_spl_ssbl_address(void);
-u32 rsu_spl_ssbl_size(void);
+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
index 92d12682c3..8bbda4979d 100644
--- a/arch/arm/mach-socfpga/rsu_spl.c
+++ b/arch/arm/mach-socfpga/rsu_spl.c
@@ -3,6 +3,7 @@
* Copyright (C) 2022 Intel Corporation <www.intel.com>
*
*/
+#define DEBUG
#include <common.h>
#include <linux/errno.h>
#include <spi.h>
@@ -15,20 +16,24 @@
#define SSBL_PART_PREFIX "SSBL."
#define RSU_ADDR_MASK 0xFFFFFFFF
#define RSU_ADDR_SHIFT 32
+#define SSBL_PART_PREFIX "SSBL."
+#define UBOOT_ENV_EXT ".env"
+#define UBOOT_IMG_EXT ".img"
+#define UBOOT_ITB_EXT ".itb"
+#define UBOOT_ENV_PREFIX "uboot_"
+#define UBOOT_ENV_REDUND_PREFIX "uboot-redund_"
+#define UBOOT_PREFIX "u-boot_"
+#define FACTORY_IMG_NAME "FACTORY_IM"
-static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot)
+static int get_spl_slot(struct socfpga_rsu_s10_spt *rsu_spt,
+ size_t rsu_spt_size, int *crt_spt_index)
{
- struct socfpga_rsu_s10_spt rsu_spt = {0};
u32 rsu_spt0_offset = 0, rsu_spt1_offset = 0;
- u32 spt_offset[4];
- struct rsu_status_info rsu_status;
- int crt_spt_index = -EINVAL;
- char *result;
+ u32 spt_offset[4] = {0};
+ struct rsu_status_info rsu_status = {0};
struct spi_flash *flash;
int i;
- rsu_ssbl_slot->offset[0] = -EINVAL;
-
/* get rsu status */
if (mbox_rsu_status((u32 *)&rsu_status, sizeof(rsu_status) / 4)) {
puts("RSU: Error - mbox_rsu_status failed!\n");
@@ -55,23 +60,23 @@ static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot)
}
/* read spt0 */
- if (spi_flash_read(flash, rsu_spt0_offset, sizeof(rsu_spt), &rsu_spt)) {
+ if (spi_flash_read(flash, rsu_spt0_offset, rsu_spt_size, rsu_spt)) {
puts("RSU: Error - spi_flash_read failed!\n");
return -EINVAL;
}
/* if spt0 does not have the correct magic number */
- if (rsu_spt.magic_number != RSU_S10_SPT_MAGIC_NUMBER) {
+ if (rsu_spt->magic_number != RSU_S10_SPT_MAGIC_NUMBER) {
/* read spt1 */
- if (spi_flash_read(flash, rsu_spt1_offset, sizeof(rsu_spt), &rsu_spt)) {
+ if (spi_flash_read(flash, rsu_spt1_offset, rsu_spt_size, rsu_spt)) {
printf("RSU: Error - spi_flash_read failed!\n");
return -EINVAL;
}
/* bail out if spt1 does not have the correct magic number */
- if (rsu_spt.magic_number != RSU_S10_SPT_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);
+ rsu_spt->magic_number);
return -EINVAL;
}
}
@@ -83,24 +88,38 @@ static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot)
debug("RSU error details: 0x%08x\n", rsu_status.error_details);
/* display partitions */
- for (i = 0; i < rsu_spt.entries; i++) {
+ for (i = 0; i < rsu_spt->entries; 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);
+ 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 < rsu_spt.entries; i++) {
+ for (i = 0; i < rsu_spt->entries; i++) {
if (((rsu_status.current_image & RSU_ADDR_MASK) ==
- rsu_spt.spt_slot[i].offset[0]) &&
+ 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;
- break;
+ rsu_spt->spt_slot[i].offset[1])) {
+ *crt_spt_index = i;
+ return 0;
}
}
- if (crt_spt_index == -EINVAL) {
+ puts("RSU: Error - could not locate SPL partition in the SPT table!\n");
+ return -EINVAL;
+}
+
+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;
+ 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 -EINVAL;
}
@@ -121,7 +140,8 @@ static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot)
/* 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))) {
+ MAX_PART_NAME_LENGTH - strlen(SSBL_PART_PREFIX)) ||
+ !strncmp(result, FACTORY_IMG_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],
@@ -139,7 +159,100 @@ static int get_ssbl_slot(struct socfpga_rsu_s10_spt_slot *rsu_ssbl_slot)
return -EINVAL;
}
-u32 rsu_spl_ssbl_address(void)
+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, len;
+
+ if (!filename) {
+ printf("RSU: filename is NULL!\n");
+ return -ENOENT;
+ }
+
+ if ((strlen(UBOOT_PREFIX) + MAX_PART_NAME_LENGTH + strlen(UBOOT_ITB_EXT))
+ > 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 */
+ panic("ERROR: could not find u-boot proper(SSBL): SSBL.%s!",
+ rsu_spt.spt_slot[crt_spt_index].name);
+ }
+
+ /* add 1 to the length to copy for NULL terminated string */
+ strlcat(filename, UBOOT_PREFIX, strlen(UBOOT_PREFIX) + 1);
+ strlcat(filename + strlen(UBOOT_PREFIX),
+ rsu_spt.spt_slot[crt_spt_index].name,
+ strlen(rsu_spt.spt_slot[crt_spt_index].name) + 1);
+ len = strlen(UBOOT_PREFIX) + strlen(rsu_spt.spt_slot[crt_spt_index].name);
+#if IS_ENABLED(CONFIG_SPL_LOAD_FIT)
+ strlcat(filename + len,
+ UBOOT_ITB_EXT, strlen(UBOOT_ITB_EXT) + 1);
+#else
+ strlcat(filename + len,
+ UBOOT_IMG_EXT, strlen(UBOOT_IMG_EXT) + 1);
+#endif
+ 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, len;
+
+ if (!filename) {
+ printf("RSU: filename is NULL!\n");
+ return -ENOENT;
+ }
+
+ if ((strlen(UBOOT_ENV_REDUND_PREFIX) + strlen(UBOOT_ENV_PREFIX) +
+ MAX_PART_NAME_LENGTH + strlen(UBOOT_ENV_EXT)) > 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) {
+ strlcat(filename, UBOOT_ENV_REDUND_PREFIX,
+ strlen(UBOOT_ENV_REDUND_PREFIX) + 1);
+ strlcat(filename + strlen(UBOOT_ENV_REDUND_PREFIX),
+ rsu_spt.spt_slot[crt_spt_index].name,
+ strlen(rsu_spt.spt_slot[crt_spt_index].name) + 1);
+ len = strlen(UBOOT_ENV_REDUND_PREFIX) +
+ strlen(rsu_spt.spt_slot[crt_spt_index].name);
+ } else {
+ strlcat(filename, UBOOT_ENV_PREFIX, strlen(UBOOT_ENV_PREFIX) + 1);
+ strlcat(filename + strlen(UBOOT_ENV_PREFIX),
+ rsu_spt.spt_slot[crt_spt_index].name,
+ strlen(rsu_spt.spt_slot[crt_spt_index].name) + 1);
+ len = strlen(UBOOT_ENV_PREFIX) +
+ strlen(rsu_spt.spt_slot[crt_spt_index].name);
+ }
+ strlcat(filename + len, UBOOT_ENV_EXT, strlen(UBOOT_ENV_EXT) + 1);
+
+ 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};
@@ -152,33 +265,53 @@ u32 rsu_spl_ssbl_address(void)
}
/* should throw error if cannot find u-boot proper(SSBL) address */
- panic("ERROR: could not 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 ret;
+ }
}
- printf("RSU: Success found SSBL at offset: %08x.\n", rsu_ssbl_slot.offset[0]);
+ 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(void)
+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 */
- if (get_ssbl_slot(&rsu_ssbl_slot) == -EOPNOTSUPP) {
- printf("ERROR: Invalid address, could not retrieve SSBL size!");
- return 0;
+ ret = get_ssbl_slot(&rsu_ssbl_slot);
+ if (ret) {
+ if (ret == -EOPNOTSUPP) {
+ printf("ERROR: Invalid address, could not retrieve SSBL size!");
+ return 0;
+ }
+
+ /* 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 ret;
+ }
}
if (!rsu_ssbl_slot.length) {
/* throw error if cannot find u-boot proper(SSBL) size */
- panic("ERROR: could not retrieve u-boot proper(SSBL) size!");
+ printf("ERROR: could not retrieve u-boot proper(SSBL) size!");
+ return ret;
}
- printf("RSU: Success found SSBL with length: %08x.\n", rsu_ssbl_slot.length);
+ 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();
+ return rsu_spl_ssbl_address(true);
}
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 23a395e63d..1d6fbf81fa 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -498,15 +498,38 @@ int spl_mmc_load(struct spl_image_info *spl_image,
return err;
}
+__weak int rsu_spl_mmc_filename(char *filename, int max_size)
+{
+ return -ENOENT;
+}
+
int spl_mmc_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ const char *file;
+ char filename[SZ_256] = {0};
+ int ret;
+
+ ret = rsu_spl_mmc_filename(filename, SZ_256);
+ if (ret) {
+ printf("RSU: Multiboot filename is not found\n");
+ return ret;
+ }
+
+ file = filename;
+ printf("%s: Boot from filename: %s\n", __func__, filename);
+#endif
return spl_mmc_load(spl_image, bootdev,
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ file,
+#else
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
#else
NULL,
#endif
+#endif
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
spl_mmc_boot_partition(bootdev->boot_device),
#else
diff --git a/env/fat.c b/env/fat.c
index 3172130d75..d530eb18cd 100644
--- a/env/fat.c
+++ b/env/fat.c
@@ -5,7 +5,6 @@
* Author:
* Maximilian Schwerin <mvs@tigris.de>
*/
-
#include <common.h>
#include <command.h>
#include <env.h>
@@ -32,6 +31,10 @@
#endif
DECLARE_GLOBAL_DATA_PTR;
+__weak int rsu_spl_mmc_env_name(char *filename, int max_size, bool redund)
+{
+ return -ENOENT;
+}
__weak const char *env_fat_get_intf(void)
{
@@ -57,17 +60,42 @@ __weak char *env_fat_get_dev_part(void)
#endif
}
+static int get_env_filename(char *env_file, bool redund)
+{
+ int ret;
+
+ ret = rsu_spl_mmc_env_name(env_file, SZ_256, redund);
+ if (ret) {
+ printf("RSU: Multiboot env. filename is not found\n");
+ return ret;
+ }
+
+ return 0;
+}
+
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;
+ struct disk_partition info;
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();
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ char env_file[SZ_256] = {0};
+ int ret;
+
+ ret = get_env_filename(env_file, false);
+ if (ret) {
+ printf("RSU: Multiboot env. filename is not found\n");
+ return ret;
+ }
+
+ file = env_file;
+#endif
err = env_export(&env_new);
if (err)
@@ -90,8 +118,18 @@ static int env_fat_save(void)
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
if (gd->env_valid == ENV_VALID)
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ ret = get_env_filename(env_file, true);
+ if (ret) {
+ printf("RSU: Multiboot env. filename is not found\n");
+ return ret;
+ }
+
+ file = env_file;
+#else
file = CONFIG_ENV_FAT_FILE_REDUND;
#endif
+#endif
err = file_fat_write(file, (void *)&env_new, 0, sizeof(env_t), &size);
if (err == -1) {
@@ -124,6 +162,11 @@ static int env_fat_load(void)
int err1;
const char *ifname = env_fat_get_intf();
const char *dev_and_part = env_fat_get_dev_part();
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ const char *file;
+ char env_file[SZ_256] = {0};
+ int ret;
+#endif
#ifdef CONFIG_MMC
if (!strcmp(ifname, "mmc"))
@@ -150,10 +193,32 @@ static int env_fat_load(void)
goto err_env_relocate;
}
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ ret = get_env_filename(env_file, false);
+ if (ret) {
+ printf("RSU: Multiboot env. filename is not found\n");
+ return ret;
+ }
+
+ file = env_file;
+ err1 = file_fat_read(file, buf1, CONFIG_ENV_SIZE);
+#else
err1 = file_fat_read(CONFIG_ENV_FAT_FILE, buf1, CONFIG_ENV_SIZE);
+#endif
+
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
- err2 = file_fat_read(CONFIG_ENV_FAT_FILE_REDUND, buf2, CONFIG_ENV_SIZE);
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ ret = get_env_filename(env_file, true);
+ if (ret) {
+ printf("RSU: Multiboot env. filename is not found\n");
+ return ret;
+ }
+ file = env_file;
+ err2 = file_fat_read(file, buf2, CONFIG_ENV_SIZE);
+#else
+ err2 = file_fat_read(CONFIG_ENV_FAT_FILE_REDUND, buf2, CONFIG_ENV_SIZE);
+#endif
err1 = (err1 >= 0) ? 0 : -1;
err2 = (err2 >= 0) ? 0 : -1;
return env_import_redund(buf1, err1, buf2, err2, H_EXTERNAL);
@@ -163,8 +228,13 @@ 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);
+#if IS_ENABLED(CONFIG_SOCFPGA_RSU_MULTIBOOT)
+ printf("Unable to read \"%s\" from %s%d:%d...\n",
+ file, ifname, dev, part);
+#else
+ printf("Unable to read \"%s\" from %s%d:%d...\n",
+ CONFIG_ENV_FAT_FILE, ifname, dev, part);
+#endif
goto err_env_relocate;
}
diff --git a/env/sf.c b/env/sf.c
index 820cbe1da0..965e87bbbe 100644
--- a/env/sf.c
+++ b/env/sf.c
@@ -42,8 +42,8 @@ static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND;
#if (CONFIG_IS_ENABLED(SOCFPGA_RSU_MULTIBOOT))
#undef CONFIG_ENV_OFFSET
-#define CONFIG_ENV_OFFSET (rsu_spl_ssbl_address() +\
- rsu_spl_ssbl_size() -\
+#define CONFIG_ENV_OFFSET (rsu_spl_ssbl_address(false) +\
+ rsu_spl_ssbl_size(false) -\
CONFIG_ENV_SIZE)
#endif