[U-Boot] [PATCH 03/13] spl: Make image loader infrastructure more universal

Andreas Dannenberg
2019-05-07T17:25:32Z

The current U-Boot SPL image loader infrastructure is very powerful,
able to initialize and load from a variety of boot media however it
is strongly geared towards loading specific types of images in a very
specific way. To address the need being able to use this infrastructure
to load arbitrary image files go ahead and refactor it as follows:

- Refactor existing spl_mmc_load_image function into superset function,
accepting additional arguments such as filenames and media load offset
(same concept can also be applied toother spl_XXX_load_image functions)
- Extend the loader function to "remember" their peripheral initialization
status so that the init is only done once during the boot process,
- Extend the FIT image loading function to allow skipping the parsing/
processing of the FIT contents (so that this can be done separately
in a more customized fashion)
- Populate the SPL_LOAD_IMAGE_METHOD() list with a trampoline function,
invoking the newly refactored superset functions in a way to maintain
compatibility with the existing behavior

This refactoring initially covers MMC/SD card loading (RAW and FS-based).

Signed-off-by: Andreas Dannenberg <dannenberg@ti.com>
---
common/spl/spl_fit.c | 14 ++++++++
common/spl/spl_mmc.c | 76 +++++++++++++++++++++++++++++---------------
include/spl.h | 26 +++++++++++++++
3 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 87ecf0bb9e..969f7775c1 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -340,6 +340,16 @@ static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
#endif
}

+/*
+ * Weak default function to allow customizing SPL fit loading for load-only
+ * use cases by allowing to skip the parsing/processing of the FIT contents
+ * (so that this can be done separately in a more customized fashion)
+ */
+__weak bool spl_load_simple_fit_skip_processing(void)
+{
+ return false;
+}
+
int spl_load_simple_fit(struct spl_image_info *spl_image,
struct spl_load_info *info, ulong sector, void *fit)
{
@@ -389,6 +399,10 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
if (count == 0)
return -EIO;

+ /* skip further processing if requested to enable load-only use cases */
+ if (spl_load_simple_fit_skip_processing())
+ return 0;
+
/* find the node holding the images information */
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
if (images < 0) {
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 324d91c884..b3619889f7 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -151,7 +151,8 @@ static int spl_mmc_find_device(struct mmc **mmcp, u32 boot_device)

#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
- struct mmc *mmc, int partition)
+ struct mmc *mmc, int partition,
+ unsigned long sector)
{
disk_partition_t info;
int err;
@@ -180,8 +181,7 @@ static int mmc_load_image_raw_partition(struct spl_image_info *spl_image,
}

#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
- return mmc_load_image_raw_sector(spl_image, mmc,
- info.start + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+ return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector);
#else
return mmc_load_image_raw_sector(spl_image, mmc, info.start);
#endif
@@ -234,7 +234,8 @@ static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
#endif

#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION
-static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
+static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
+ const char *filename)
{
int err = -ENOSYS;

@@ -248,7 +249,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
- CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
+ filename);
if (!err)
return err;
#endif
@@ -263,7 +264,7 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
- CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
+ filename);
if (!err)
return err;
#endif
@@ -276,7 +277,8 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
return err;
}
#else
-static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
+static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc,
+ const char *filename)
{
return -ENOSYS;
}
@@ -301,24 +303,31 @@ int spl_boot_partition(const u32 boot_device)
}
#endif

-int spl_mmc_load_image(struct spl_image_info *spl_image,
- struct spl_boot_device *bootdev)
+int spl_mmc_load(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev,
+ const char *filename,
+ int raw_part,
+ unsigned long raw_sect)
{
- struct mmc *mmc = NULL;
+ static struct mmc *mmc;
u32 boot_mode;
int err = 0;
__maybe_unused int part;

- err = spl_mmc_find_device(&mmc, bootdev->boot_device);
- if (err)
- return err;
+ /* Perform peripheral init only once */
+ if (!mmc) {
+ err = spl_mmc_find_device(&mmc, bootdev->boot_device);
+ if (err)
+ return err;

- err = mmc_init(mmc);
- if (err) {
+ err = mmc_init(mmc);
+ if (err) {
+ mmc = NULL;
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
- printf("spl: mmc init failed with error: %d\n", err);
+ printf("spl: mmc init failed with error: %d\n", err);
#endif
- return err;
+ return err;
+ }
}

boot_mode = spl_boot_mode(bootdev->boot_device);
@@ -356,17 +365,13 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
return err;
}
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
- err = spl_boot_partition(bootdev->boot_device);
- if (!err)
- return err;
-
- err = mmc_load_image_raw_partition(spl_image, mmc, err);
+ err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,
+ raw_sect);
if (!err)
return err;
#endif
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
- err = mmc_load_image_raw_sector(spl_image, mmc,
- CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+ err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect);
if (!err)
return err;
#endif
@@ -374,7 +379,7 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
case MMCSD_MODE_FS:
debug("spl: mmc boot mode: fs\n");

- err = spl_mmc_do_fs_boot(spl_image, mmc);
+ err = spl_mmc_do_fs_boot(spl_image, mmc, filename);
if (!err)
return err;

@@ -388,6 +393,27 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
return err;
}

+int spl_mmc_load_image(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev)
+{
+ return spl_mmc_load(spl_image, bootdev,
+#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
+ CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
+#else
+ NULL,
+#endif
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION
+ spl_boot_partition(bootdev->boot_device),
+#else
+ 0,
+#endif
+#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
+#else
+ 0);
+#endif
+}
+
SPL_LOAD_IMAGE_METHOD("MMC1", 0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
SPL_LOAD_IMAGE_METHOD("MMC2", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image);
SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image);
diff --git a/include/spl.h b/include/spl.h
index f09909e189..94ca5d5c6a 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -108,6 +108,15 @@ struct spl_load_info {
*/
binman_sym_extern(ulong, u_boot_any, image_pos);

+/**
+ * spl_load_simple_fit_skip_processing() - Hook to allow skipping the FIT
+ * image processing during spl_load_simple_fit().
+ *
+ * Return true to skip FIT processing, false to preserve the full code flow
+ * of spl_load_simple_fit().
+ */
+bool spl_load_simple_fit_skip_processing(void);
+
/**
* spl_load_simple_fit() - Loads a fit image from a device.
* @spl_image: Image description to set up
@@ -330,6 +339,23 @@ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr);
int spl_mmc_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev);

+/**
+ * spl_mmc_load() - Load an image file from MMC/SD media
+ *
+ * @param spl_image Image data filled in by loading process
+ * @param bootdev Describes which device to load from
+ * @param filename Name of file to load (in FS mode)
+ * @param raw_part Partition to load from (in RAW mode)
+ * @param raw_sect Sector to load from (in RAW mode)
+ *
+ * @return 0 on success, otherwise error code
+ */
+int spl_mmc_load(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev,
+ const char *filename,
+ int raw_part,
+ unsigned long raw_sect);
+
/**
* spl_invoke_atf - boot using an ARM trusted firmware image
*/
--
2.17.1