spl: Make image loader infrastructure more universal

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>
Reviewed-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
Andreas Dannenberg 2019-06-04 17:55:46 -05:00 committed by Tom Rini
parent a5a5d997b4
commit e1eb6ada4e
3 changed files with 91 additions and 25 deletions

View File

@ -340,6 +340,16 @@ static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
#endif #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, int spl_load_simple_fit(struct spl_image_info *spl_image,
struct spl_load_info *info, ulong sector, void *fit) 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) if (count == 0)
return -EIO; 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 */ /* find the node holding the images information */
images = fdt_path_offset(fit, FIT_IMAGES_PATH); images = fdt_path_offset(fit, FIT_IMAGES_PATH);
if (images < 0) { if (images < 0) {

View File

@ -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 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
static int mmc_load_image_raw_partition(struct spl_image_info *spl_image, 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; disk_partition_t info;
int err; 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 #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
return mmc_load_image_raw_sector(spl_image, mmc, return mmc_load_image_raw_sector(spl_image, mmc, info.start + sector);
info.start + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
#else #else
return mmc_load_image_raw_sector(spl_image, mmc, info.start); return mmc_load_image_raw_sector(spl_image, mmc, info.start);
#endif #endif
@ -234,7 +234,8 @@ static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
#endif #endif
#ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION #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; 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 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc), err = spl_load_image_fat(spl_image, mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); filename);
if (!err) if (!err)
return err; return err;
#endif #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 #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc), err = spl_load_image_ext(spl_image, mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); filename);
if (!err) if (!err)
return err; return err;
#endif #endif
@ -276,7 +277,8 @@ static int spl_mmc_do_fs_boot(struct spl_image_info *spl_image, struct mmc *mmc)
return err; return err;
} }
#else #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; return -ENOSYS;
} }
@ -301,24 +303,31 @@ int spl_boot_partition(const u32 boot_device)
} }
#endif #endif
int spl_mmc_load_image(struct spl_image_info *spl_image, int spl_mmc_load(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev) 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; u32 boot_mode;
int err = 0; int err = 0;
__maybe_unused int part; __maybe_unused int part;
err = spl_mmc_find_device(&mmc, bootdev->boot_device); /* Perform peripheral init only once */
if (err) if (!mmc) {
return err; err = spl_mmc_find_device(&mmc, bootdev->boot_device);
if (err)
return err;
err = mmc_init(mmc); err = mmc_init(mmc);
if (err) { if (err) {
mmc = NULL;
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT #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 #endif
return err; return err;
}
} }
boot_mode = spl_boot_mode(bootdev->boot_device); 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; return err;
} }
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
err = spl_boot_partition(bootdev->boot_device); err = mmc_load_image_raw_partition(spl_image, mmc, raw_part,
if (!err) raw_sect);
return err;
err = mmc_load_image_raw_partition(spl_image, mmc, err);
if (!err) if (!err)
return err; return err;
#endif #endif
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
err = mmc_load_image_raw_sector(spl_image, mmc, err = mmc_load_image_raw_sector(spl_image, mmc, raw_sect);
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR);
if (!err) if (!err)
return err; return err;
#endif #endif
@ -374,7 +379,7 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
case MMCSD_MODE_FS: case MMCSD_MODE_FS:
debug("spl: mmc boot mode: fs\n"); 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) if (!err)
return err; return err;
@ -388,6 +393,27 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
return err; 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("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", 0, BOOT_DEVICE_MMC2, spl_mmc_load_image);
SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image); SPL_LOAD_IMAGE_METHOD("MMC2_2", 0, BOOT_DEVICE_MMC2_2, spl_mmc_load_image);

View File

@ -108,6 +108,15 @@ struct spl_load_info {
*/ */
binman_sym_extern(ulong, u_boot_any, image_pos); 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_load_simple_fit() - Loads a fit image from a device.
* @spl_image: Image description to set up * @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, int spl_mmc_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev); 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 * spl_invoke_atf - boot using an ARM trusted firmware image
*/ */