#include <common.h>
#include <bloblist.h>
#include <binman_sym.h>
+#include <bootstage.h>
#include <dm.h>
#include <handoff.h>
#include <hang.h>
+#include <init.h>
#include <irq_func.h>
+#include <log.h>
+#include <mapmem.h>
#include <serial.h>
#include <spl.h>
+#include <asm/global_data.h>
#include <asm/u-boot.h>
#include <nand.h>
#include <fat.h>
#endif
/* Define board data structure */
-static bd_t bdata __attribute__ ((section(".data")));
+static struct bd_info bdata __attribute__ ((section(".data")));
+#if CONFIG_IS_ENABLED(BOOTSTAGE)
/*
* Board-specific Platform code can reimplement show_boot_progress () if needed
*/
__weak void show_boot_progress(int val) {}
+#endif
-#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF)
+#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) || \
+ defined(CONFIG_SPL_ATF)
/* weak, default platform-specific function to initialize dram banks */
__weak int dram_init_banksize(void)
{
{
}
-void spl_fixup_fdt(void)
+void spl_fixup_fdt(void *fdt_blob)
{
-#if defined(CONFIG_SPL_OF_LIBFDT) && defined(CONFIG_SYS_SPL_ARGS_ADDR)
- void *fdt_blob = (void *)CONFIG_SYS_SPL_ARGS_ADDR;
+#if defined(CONFIG_SPL_OF_LIBFDT)
int err;
+ if (!fdt_blob)
+ return;
+
err = fdt_check_header(fdt_blob);
if (err < 0) {
printf("fdt_root: %s\n", fdt_strerror(err));
binman_sym(ulong, u_boot_any, size);
}
+ulong spl_get_image_text_base(void)
+{
+ return spl_phase() == PHASE_TPL ? CONFIG_SPL_TEXT_BASE :
+ CONFIG_SYS_TEXT_BASE;
+}
+
/*
* Weak default function for board specific cleanup/preparation before
* Linux boot. Some boards/platforms might not need it, so just provide
__weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
{
- return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
+ return map_sysmem(CONFIG_SYS_TEXT_BASE + offset, 0);
}
void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
{
bootm_headers_t images;
const char *fit_uname_config = NULL;
- const char *fit_uname_fdt = FIT_FDT_PROP;
+ uintptr_t fdt_hack;
const char *uname;
ulong fw_data = 0, dt_data = 0, img_data = 0;
ulong fw_len = 0, dt_len = 0, img_len = 0;
ret = fit_image_load(&images, (ulong)header,
NULL, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
- FIT_LOAD_REQUIRED, &fw_data, &fw_len);
+ FIT_LOAD_OPTIONAL, &fw_data, &fw_len);
+ if (ret >= 0) {
+ printf("DEPRECATED: 'standalone = ' property.");
+ printf("Please use either 'firmware =' or 'kernel ='\n");
+ } else {
+ ret = fit_image_load(&images, (ulong)header, NULL,
+ &fit_uname_config, IH_ARCH_DEFAULT,
+ IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL,
+ &fw_data, &fw_len);
+ }
+
+ if (ret < 0) {
+ ret = fit_image_load(&images, (ulong)header, NULL,
+ &fit_uname_config, IH_ARCH_DEFAULT,
+ IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL,
+ &fw_data, &fw_len);
+ }
+
if (ret < 0)
return ret;
spl_image->size = fw_len;
spl_image->entry_point = fw_data;
spl_image->load_addr = fw_data;
- spl_image->os = IH_OS_U_BOOT;
- spl_image->name = "U-Boot";
+ if (fit_image_get_os(header, ret, &spl_image->os))
+ spl_image->os = IH_OS_INVALID;
+ spl_image->name = genimg_get_os_name(spl_image->os);
debug(SPL_TPL_PROMPT "payload image: %32s load addr: 0x%lx size: %d\n",
spl_image->name, spl_image->load_addr, spl_image->size);
#ifdef CONFIG_SPL_FIT_SIGNATURE
images.verify = 1;
#endif
- ret = fit_image_load(&images, (ulong)header,
- &fit_uname_fdt, &fit_uname_config,
+ ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
- if (ret >= 0)
+ if (ret >= 0) {
spl_image->fdt_addr = (void *)dt_data;
+ if (spl_image->os == IH_OS_U_BOOT) {
+ /* HACK: U-boot expects FDT at a specific address */
+ fdt_hack = spl_image->load_addr + spl_image->size;
+ fdt_hack = (fdt_hack + 3) & ~3;
+ debug("Relocating FDT to %p\n", spl_image->fdt_addr);
+ memcpy((void *)fdt_hack, spl_image->fdt_addr, dt_len);
+ }
+ }
+
conf_noffset = fit_conf_get_node((const void *)header,
fit_uname_config);
if (conf_noffset <= 0)
#endif /* HANDOFF */
+/**
+ * get_bootstage_id() - Get the bootstage ID to emit
+ *
+ * @start: true if this is for starting SPL, false for ending it
+ * @return bootstage ID to use
+ */
+static enum bootstage_id get_bootstage_id(bool start)
+{
+ enum u_boot_phase phase = spl_phase();
+
+ if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL)
+ return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL;
+ else
+ return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL;
+}
+
static int spl_common_init(bool setup_malloc)
{
int ret;
__func__, ret);
}
#endif /* CONFIG_BOOTSTAGE_STASH */
- bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL :
- BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME);
+ bootstage_mark_name(get_bootstage_id(true),
+ spl_phase_name(spl_phase()));
#if CONFIG_IS_ENABLED(LOG)
ret = log_init();
if (ret) {
}
}
if (CONFIG_IS_ENABLED(DM)) {
- bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL,
+ bootstage_start(BOOTSTAGE_ID_ACCUM_DM_SPL,
spl_phase() == PHASE_TPL ? "dm tpl" : "dm_spl");
/* With CONFIG_SPL_OF_PLATDATA, bring in all devices */
ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA));
- bootstage_accum(BOOTSTATE_ID_ACCUM_DM_SPL);
+ bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_SPL);
if (ret) {
debug("dm_init_and_scan() returned error %d\n", ret);
return ret;
* @spl_image: Place to put the image details if successful
* @spl_boot_list: List of boot devices to try
* @count: Number of elements in spl_boot_list
- * @return 0 if OK, -ve on error
+ * @return 0 if OK, -ENODEV if there were no boot devices
+ * if CONFIG_SHOW_ERRORS is enabled, returns -ENXIO if there were
+ * devices but none worked
*/
static int boot_from_devices(struct spl_image_info *spl_image,
u32 spl_boot_list[], int count)
{
+ int ret = -ENODEV;
int i;
for (i = 0; i < count && spl_boot_list[i] != BOOT_DEVICE_NONE; i++) {
struct spl_image_loader *loader;
-
- loader = spl_ll_find_loader(spl_boot_list[i]);
-#if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
- if (loader)
- printf("Trying to boot from %s\n", loader->name);
- else
- puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n");
-#endif
+ int bootdev = spl_boot_list[i];
+
+ if (CONFIG_IS_ENABLED(SHOW_ERRORS))
+ ret = -ENXIO;
+ loader = spl_ll_find_loader(bootdev);
+ if (CONFIG_IS_ENABLED(SERIAL_SUPPORT) &&
+ CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) &&
+ !IS_ENABLED(CONFIG_SILENT_CONSOLE)) {
+ if (loader)
+ printf("Trying to boot from %s\n",
+ spl_loader_name(loader));
+ else if (CONFIG_IS_ENABLED(SHOW_ERRORS))
+ printf(SPL_TPL_PROMPT
+ "Unsupported Boot Device %d\n", bootdev);
+ else
+ puts(SPL_TPL_PROMPT "Unsupported Boot Device!\n");
+ }
if (loader && !spl_load_image(spl_image, loader)) {
- spl_image->boot_device = spl_boot_list[i];
+ spl_image->boot_device = bootdev;
return 0;
}
}
- return -ENODEV;
+ return ret;
}
#if defined(CONFIG_SPL_FRAMEWORK_BOARD_INIT_F)
}
}
- if (CONFIG_IS_ENABLED(SERIAL_SUPPORT))
- preloader_console_init();
+ preloader_console_init();
}
#endif
initr_watchdog();
#endif
- if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF))
+ if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF) ||
+ IS_ENABLED(CONFIG_SPL_ATF))
dram_init_banksize();
bootcount_inc();
spl_image.boot_device = BOOT_DEVICE_NONE;
board_boot_order(spl_boot_list);
- if (boot_from_devices(&spl_image, spl_boot_list,
- ARRAY_SIZE(spl_boot_list))) {
- puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n");
+ ret = boot_from_devices(&spl_image, spl_boot_list,
+ ARRAY_SIZE(spl_boot_list));
+ if (ret) {
+ if (CONFIG_IS_ENABLED(SHOW_ERRORS) &&
+ CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT))
+ printf(SPL_TPL_PROMPT "failed to boot from all boot devices (err=%d)\n",
+ ret);
+ else
+ puts(SPL_TPL_PROMPT "failed to boot from all boot devices\n");
hang();
}
#endif
switch (spl_image.os) {
case IH_OS_U_BOOT:
- debug("Jumping to U-Boot\n");
+ debug("Jumping to %s...\n", spl_phase_name(spl_next_phase()));
break;
#if CONFIG_IS_ENABLED(ATF)
case IH_OS_ARM_TRUSTED_FIRMWARE:
debug("Jumping to U-Boot via ARM Trusted Firmware\n");
+ spl_fixup_fdt(spl_image.fdt_addr);
spl_invoke_atf(&spl_image);
break;
#endif
#ifdef CONFIG_SPL_OS_BOOT
case IH_OS_LINUX:
debug("Jumping to Linux\n");
- spl_fixup_fdt();
+#if defined(CONFIG_SYS_SPL_ARGS_ADDR)
+ spl_fixup_fdt((void *)CONFIG_SYS_SPL_ARGS_ADDR);
+#endif
spl_board_prepare_for_linux();
jump_to_image_linux(&spl_image);
#endif
debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr,
gd->malloc_ptr / 1024);
#endif
- bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL :
- BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME);
+ bootstage_mark_name(get_bootstage_id(false), "end phase");
#ifdef CONFIG_BOOTSTAGE_STASH
ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
CONFIG_BOOTSTAGE_STASH_SIZE);
debug("Failed to stash bootstage: err=%d\n", ret);
#endif
- debug("loaded - jumping to U-Boot...\n");
spl_board_prepare_for_boot();
jump_to_image_no_args(&spl_image);
}
-#ifdef CONFIG_SPL_SERIAL_SUPPORT
/*
* This requires UART clocks to be enabled. In order for this to work the
* caller must ensure that the gd pointer is valid.
*/
void preloader_console_init(void)
{
+#ifdef CONFIG_SPL_SERIAL_SUPPORT
gd->baudrate = CONFIG_BAUDRATE;
serial_init(); /* serial communications setup */
#ifdef CONFIG_SPL_DISPLAY_PRINT
spl_display_print();
#endif
-}
#endif
+}
/**
* This function is called before the stack is changed from initial stack to
#endif
}
-#if defined(CONFIG_BOOTCOUNT_LIMIT) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT)
+#if defined(CONFIG_BOOTCOUNT_LIMIT) && \
+ ((!defined(CONFIG_TPL_BUILD) && !defined(CONFIG_SPL_BOOTCOUNT_LIMIT)) || \
+ (defined(CONFIG_TPL_BUILD) && !defined(CONFIG_TPL_BOOTCOUNT_LIMIT)))
void bootcount_store(ulong a)
{
}