Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / arch / powerpc / lib / bootm.c
index 306412114309fb3dd7528208c5677ef355412fb5..7088293a3647a6c249369a1e2d436497feb70c8b 100644 (file)
@@ -33,6 +33,7 @@
 #include <bzlib.h>
 #include <environment.h>
 #include <asm/byteorder.h>
+#include <asm/mp.h>
 
 #if defined(CONFIG_OF_LIBFDT)
 #include <fdt.h>
@@ -47,7 +48,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 extern ulong get_effective_memsize(void);
 static ulong get_sp (void);
 static void set_clocks_in_mhz (bd_t *kbd);
@@ -69,7 +69,7 @@ static void boot_jump_linux(bootm_headers_t *images)
        debug ("## Transferring control to Linux (at address %08lx) ...\n",
                (ulong)kernel);
 
-       show_boot_progress (15);
+       bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 
 #if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
        unlock_ram_in_cache();
@@ -87,16 +87,10 @@ static void boot_jump_linux(bootm_headers_t *images)
                 *   r8: 0
                 *   r9: 0
                 */
-#if defined(CONFIG_85xx) || defined(CONFIG_440)
- #define EPAPR_MAGIC   (0x45504150)
-#else
- #define EPAPR_MAGIC   (0x65504150)
-#endif
-
                debug ("   Booting using OF flat tree...\n");
                WATCHDOG_RESET ();
                (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
-                          CONFIG_SYS_BOOTMAPSZ, 0, 0);
+                          getenv_bootm_mapsize(), 0, 0);
                /* does not return */
        } else
 #endif
@@ -167,22 +161,27 @@ void arch_lmb_reserve(struct lmb *lmb)
        sp -= 4096;
        lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - sp));
 
+#ifdef CONFIG_MP
+       cpu_mp_lmb_reserve(lmb);
+#endif
+
        return ;
 }
 
-static void boot_prep_linux(void)
+static void boot_prep_linux(bootm_headers_t *images)
 {
 #ifdef CONFIG_MP
-       /* if we are MP make sure to flush the dcache() to any changes are made
-        * visibile to all other cores */
-       flush_dcache();
+       /*
+        * if we are MP make sure to flush the device tree so any changes are
+        * made visibile to all other cores.  In AMP boot scenarios the cores
+        * might not be HW cache coherent with each other.
+        */
+       flush_cache((unsigned long)images->ft_addr, images->ft_len);
 #endif
-       return ;
 }
 
 static int boot_cmdline_linux(bootm_headers_t *images)
 {
-       ulong bootmap_base = getenv_bootm_low();
        ulong of_size = images->ft_len;
        struct lmb *lmb = &images->lmb;
        ulong *cmd_start = &images->cmdline_start;
@@ -192,7 +191,7 @@ static int boot_cmdline_linux(bootm_headers_t *images)
 
        if (!of_size) {
                /* allocate space and init command line */
-               ret = boot_get_cmdline (lmb, cmd_start, cmd_end, bootmap_base);
+               ret = boot_get_cmdline (lmb, cmd_start, cmd_end);
                if (ret) {
                        puts("ERROR with allocation of cmdline\n");
                        return ret;
@@ -204,7 +203,6 @@ static int boot_cmdline_linux(bootm_headers_t *images)
 
 static int boot_bd_t_linux(bootm_headers_t *images)
 {
-       ulong bootmap_base = getenv_bootm_low();
        ulong of_size = images->ft_len;
        struct lmb *lmb = &images->lmb;
        bd_t **kbd = &images->kbd;
@@ -213,7 +211,7 @@ static int boot_bd_t_linux(bootm_headers_t *images)
 
        if (!of_size) {
                /* allocate space for kernel copy of board info */
-               ret = boot_get_kbd (lmb, kbd, bootmap_base);
+               ret = boot_get_kbd (lmb, kbd);
                if (ret) {
                        puts("ERROR with allocation of kernel bd\n");
                        return ret;
@@ -224,6 +222,24 @@ static int boot_bd_t_linux(bootm_headers_t *images)
        return ret;
 }
 
+/*
+ * Verify the device tree.
+ *
+ * This function is called after all device tree fix-ups have been enacted,
+ * so that the final device tree can be verified.  The definition of "verified"
+ * is up to the specific implementation.  However, it generally means that the
+ * addresses of some of the devices in the device tree are compared with the
+ * actual addresses at which U-Boot has placed them.
+ *
+ * Returns 1 on success, 0 on failure.  If 0 is returned, U-boot will halt the
+ * boot process.
+ */
+static int __ft_verify_fdt(void *fdt)
+{
+       return 1;
+}
+__attribute__((weak, alias("__ft_verify_fdt"))) int ft_verify_fdt(void *fdt);
+
 static int boot_body_linux(bootm_headers_t *images)
 {
        ulong rd_len;
@@ -231,13 +247,16 @@ static int boot_body_linux(bootm_headers_t *images)
        ulong *initrd_start = &images->initrd_start;
        ulong *initrd_end = &images->initrd_end;
 #if defined(CONFIG_OF_LIBFDT)
-       ulong bootmap_base = getenv_bootm_low();
        ulong of_size = images->ft_len;
        char **of_flat_tree = &images->ft_addr;
 #endif
 
        int ret;
 
+#if defined(CONFIG_OF_LIBFDT)
+       boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
+#endif
+
        /* allocate space and init command line */
        ret = boot_cmdline_linux(images);
        if (ret)
@@ -254,7 +273,7 @@ static int boot_body_linux(bootm_headers_t *images)
                return ret;
 
 #if defined(CONFIG_OF_LIBFDT)
-       ret = boot_relocate_fdt(lmb, bootmap_base, of_flat_tree, &of_size);
+       ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
        if (ret)
                return ret;
 
@@ -283,20 +302,25 @@ static int boot_body_linux(bootm_headers_t *images)
                        return ret;
                of_size = ret;
 
-               if (*initrd_start && *initrd_end)
+               if (*initrd_start && *initrd_end) {
                        of_size += FDT_RAMDISK_OVERHEAD;
+                       fdt_set_totalsize(*of_flat_tree, of_size);
+               }
                /* Create a new LMB reservation */
                lmb_reserve(lmb, (ulong)*of_flat_tree, of_size);
 
                /* fixup the initrd now that we know where it should be */
                if (*initrd_start && *initrd_end)
                        fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
+
+               if (!ft_verify_fdt(*of_flat_tree))
+                       return -1;
        }
 #endif /* CONFIG_OF_LIBFDT */
        return 0;
 }
 
-__attribute__((noinline))
+noinline
 int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
 {
        int     ret;
@@ -312,7 +336,7 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima
        }
 
        if (flag & BOOTM_STATE_OS_PREP) {
-               boot_prep_linux();
+               boot_prep_linux(images);
                return 0;
        }
 
@@ -321,7 +345,7 @@ int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *ima
                return 0;
        }
 
-       boot_prep_linux();
+       boot_prep_linux(images);
        ret = boot_body_linux(images);
        if (ret)
                return ret;