]> Git Repo - J-u-boot.git/blobdiff - common/spl/spl.c
spl: Provide more information on boot failure
[J-u-boot.git] / common / spl / spl.c
index b0f0e1557b923f8be107e8bdee42f376295f3657..3b96f2fc3101576c929fba948b44782238078f51 100644 (file)
@@ -9,12 +9,17 @@
 #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>
@@ -51,14 +56,17 @@ binman_sym_declare(ulong, spl, size);
 #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)
 {
@@ -100,12 +108,14 @@ void __weak spl_perform_fixups(struct spl_image_info *spl_image)
 {
 }
 
-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));
@@ -141,6 +151,12 @@ ulong spl_get_image_size(void)
                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
@@ -158,7 +174,7 @@ __weak void spl_board_prepare_for_boot(void)
 
 __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)
@@ -191,7 +207,7 @@ static int spl_load_fit_image(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;
@@ -204,15 +220,33 @@ static int spl_load_fit_image(struct spl_image_info *spl_image,
        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);
@@ -220,13 +254,21 @@ static int spl_load_fit_image(struct spl_image_info *spl_image,
 #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)
@@ -376,6 +418,22 @@ static inline int write_spl_handoff(void) { return 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;
@@ -406,8 +464,8 @@ static int spl_common_init(bool setup_malloc)
                              __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) {
@@ -423,11 +481,11 @@ static int spl_common_init(bool setup_malloc)
                }
        }
        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;
@@ -535,30 +593,42 @@ static int spl_load_image(struct spl_image_info *spl_image,
  * @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)
@@ -574,8 +644,7 @@ void board_init_f(ulong dummy)
                }
        }
 
-       if (CONFIG_IS_ENABLED(SERIAL_SUPPORT))
-               preloader_console_init();
+       preloader_console_init();
 }
 #endif
 
@@ -638,7 +707,8 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        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();
@@ -650,9 +720,15 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        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();
        }
 
@@ -675,11 +751,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 #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
@@ -699,7 +776,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 #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
@@ -710,8 +789,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        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);
@@ -719,18 +797,17 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
                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 */
@@ -744,8 +821,8 @@ void preloader_console_init(void)
 #ifdef CONFIG_SPL_DISPLAY_PRINT
        spl_display_print();
 #endif
-}
 #endif
+}
 
 /**
  * This function is called before the stack is changed from initial stack to
@@ -822,7 +899,9 @@ ulong spl_relocate_stack_gd(void)
 #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)
 {
 }
This page took 0.037513 seconds and 4 git commands to generate.