]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/cmd_bootm.c
Merge branch 'master' of git://git.denx.de/u-boot-usb
[karo-tx-uboot.git] / common / cmd_bootm.c
index b07b0f48b20a9053ecef1d0cf9a3282fba17bd17..34b4b583baafc1bb0ca62df3ea89fc7bb2ae2da9 100644 (file)
 #include <asm/io.h>
 #include <linux/compiler.h>
 
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+       (defined(CONFIG_PPC) || defined(CONFIG_ARM))
+#include <vxworks.h>
+#endif
+
 #if defined(CONFIG_CMD_USB)
 #include <usb.h>
 #endif
@@ -77,6 +82,9 @@ static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 static void fixup_silent_linux(void);
 #endif
 
+static int do_bootm_standalone(int flag, int argc, char * const argv[],
+                              bootm_headers_t *images);
+
 static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
                                char * const argv[], bootm_headers_t *images,
                                ulong *os_data, ulong *os_len);
@@ -120,8 +128,11 @@ static boot_os_fn do_bootm_ose;
 #if defined(CONFIG_BOOTM_PLAN9)
 static boot_os_fn do_bootm_plan9;
 #endif
-#if defined(CONFIG_CMD_ELF)
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+       (defined(CONFIG_PPC) || defined(CONFIG_ARM))
 static boot_os_fn do_bootm_vxworks;
+#endif
+#if defined(CONFIG_CMD_ELF)
 static boot_os_fn do_bootm_qnxelf;
 int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
@@ -131,6 +142,7 @@ static boot_os_fn do_bootm_integrity;
 #endif
 
 static boot_os_fn *boot_os[] = {
+       [IH_OS_U_BOOT] = do_bootm_standalone,
 #ifdef CONFIG_BOOTM_LINUX
        [IH_OS_LINUX] = do_bootm_linux,
 #endif
@@ -149,8 +161,11 @@ static boot_os_fn *boot_os[] = {
 #if defined(CONFIG_BOOTM_PLAN9)
        [IH_OS_PLAN9] = do_bootm_plan9,
 #endif
-#if defined(CONFIG_CMD_ELF)
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+       (defined(CONFIG_PPC) || defined(CONFIG_ARM))
        [IH_OS_VXWORKS] = do_bootm_vxworks,
+#endif
+#if defined(CONFIG_CMD_ELF)
        [IH_OS_QNX] = do_bootm_qnxelf,
 #endif
 #ifdef CONFIG_INTEGRITY
@@ -207,6 +222,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
                         char * const argv[])
 {
        const void *os_hdr;
+       bool ep_found = false;
 
        /* get kernel image header, start address and length */
        os_hdr = boot_get_kernel(cmdtp, flag, argc, argv,
@@ -258,6 +274,18 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
                        return 1;
                }
                break;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+       case IMAGE_FORMAT_ANDROID:
+               images.os.type = IH_TYPE_KERNEL;
+               images.os.comp = IH_COMP_NONE;
+               images.os.os = IH_OS_LINUX;
+               images.ep = images.os.load;
+               ep_found = true;
+
+               images.os.end = android_image_get_end(os_hdr);
+               images.os.load = android_image_get_kload(os_hdr);
+               break;
 #endif
        default:
                puts("ERROR: unknown image format type!\n");
@@ -278,7 +306,7 @@ static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
                        return 1;
                }
 #endif
-       } else {
+       } else if (!ep_found) {
                puts("Could not find kernel entry point!\n");
                return 1;
        }
@@ -333,7 +361,8 @@ static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc,
        if (((images.os.type == IH_TYPE_KERNEL) ||
             (images.os.type == IH_TYPE_KERNEL_NOLOAD) ||
             (images.os.type == IH_TYPE_MULTI)) &&
-           (images.os.os == IH_OS_LINUX)) {
+           (images.os.os == IH_OS_LINUX ||
+                images.os.os == IH_OS_VXWORKS)) {
                if (bootm_find_ramdisk(flag, argc, argv))
                        return 1;
 
@@ -372,7 +401,7 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
        image_buf = map_sysmem(image_start, image_len);
        switch (comp) {
        case IH_COMP_NONE:
-               if (load == blob_start || load == image_start) {
+               if (load == image_start) {
                        printf("   XIP %s ... ", type_name);
                        no_overlap = 1;
                } else {
@@ -437,7 +466,7 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
 #endif /* CONFIG_LZMA */
 #ifdef CONFIG_LZO
        case IH_COMP_LZO: {
-               size_t size;
+               size_t size = unc_len;
 
                printf("   Uncompressing %s ... ", type_name);
 
@@ -487,18 +516,19 @@ static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end,
        return 0;
 }
 
-static int bootm_start_standalone(int argc, char * const argv[])
+static int do_bootm_standalone(int flag, int argc, char * const argv[],
+                              bootm_headers_t *images)
 {
        char  *s;
        int   (*appl)(int, char * const []);
 
        /* Don't start if "autostart" is set to "no" */
        if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) {
-               setenv_hex("filesize", images.os.image_len);
+               setenv_hex("filesize", images->os.image_len);
                return 0;
        }
-       appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep);
-       (*appl)(argc, argv);
+       appl = (int (*)(int, char * const []))images->ep;
+       appl(argc, argv);
        return 0;
 }
 
@@ -523,14 +553,12 @@ static cmd_tbl_t cmd_bootm_sub[] = {
 static int boot_selected_os(int argc, char * const argv[], int state,
                bootm_headers_t *images, boot_os_fn *boot_fn)
 {
-       if (images->os.type == IH_TYPE_STANDALONE) {
-               /* This may return when 'autostart' is 'no' */
-               bootm_start_standalone(argc, argv);
-               return 0;
-       }
        arch_preboot_os();
        boot_fn(state, argc, argv, images);
-       if (state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
+
+       /* Stand-alone may return when 'autostart' is 'no' */
+       if (images->os.type == IH_TYPE_STANDALONE ||
+           state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */
                return 0;
        bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED);
 #ifdef DEBUG
@@ -558,6 +586,7 @@ static ulong bootm_disable_interrupts(void)
 #ifdef CONFIG_NETCONSOLE
        /* Stop the ethernet stack if NetConsole could have left it up */
        eth_halt();
+       eth_unregister(eth_get_dev());
 #endif
 
 #if defined(CONFIG_CMD_USB)
@@ -799,8 +828,12 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START |
                BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER |
-               BOOTM_STATE_LOADOS | BOOTM_STATE_OS_PREP |
-               BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO, &images, 1);
+               BOOTM_STATE_LOADOS |
+#if defined(CONFIG_PPC) || defined(CONFIG_MIPS)
+               BOOTM_STATE_OS_CMDLINE |
+#endif
+               BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
+               BOOTM_STATE_OS_GO, &images, 1);
 }
 
 int bootm_maybe_autostart(cmd_tbl_t *cmdtp, const char *cmd)
@@ -981,6 +1014,14 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
                images->fit_uname_cfg = fit_uname_config;
                images->fit_noffset_os = os_noffset;
                break;
+#endif
+#ifdef CONFIG_ANDROID_BOOT_IMAGE
+       case IMAGE_FORMAT_ANDROID:
+               printf("## Booting Android Image at 0x%08lx ...\n", img_addr);
+               if (android_image_get_kernel((void *)img_addr, images->verify,
+                                            os_data, os_len))
+                       return NULL;
+               break;
 #endif
        default:
                printf("Wrong Image Format for %s command\n", cmdtp->name);
@@ -1464,10 +1505,8 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[],
        char *consdev;
        char *cmdline;
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1528,10 +1567,10 @@ static int do_bootm_netbsd(int flag, int argc, char * const argv[],
 
        /*
         * NetBSD Stage-2 Loader Parameters:
-        *   r3: ptr to board info data
-        *   r4: image address
-        *   r5: console device
-        *   r6: boot args string
+        *   arg[0]: pointer to board info data
+        *   arg[1]: image load address
+        *   arg[2]: char pointer to the console device to use
+        *   arg[3]: char pointer to the boot arguments
         */
        (*loader)(gd->bd, os_hdr, consdev, cmdline);
 
@@ -1545,10 +1584,8 @@ static int do_bootm_lynxkdi(int flag, int argc, char * const argv[],
 {
        image_header_t *hdr = &images->legacy_hdr_os_copy;
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1569,10 +1606,8 @@ static int do_bootm_rtems(int flag, int argc, char * const argv[],
 {
        void (*entry_point)(bd_t *);
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1604,10 +1639,8 @@ static int do_bootm_ose(int flag, int argc, char * const argv[],
 {
        void (*entry_point)(void);
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1640,10 +1673,8 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[],
        void (*entry_point)(void);
        char *s;
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1683,16 +1714,68 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[],
 }
 #endif /* CONFIG_BOOTM_PLAN9 */
 
-#if defined(CONFIG_CMD_ELF)
+#if defined(CONFIG_BOOTM_VXWORKS) && \
+       (defined(CONFIG_PPC) || defined(CONFIG_ARM))
+
+void do_bootvx_fdt(bootm_headers_t *images)
+{
+#if defined(CONFIG_OF_LIBFDT)
+       int ret;
+       char *bootline;
+       ulong of_size = images->ft_len;
+       char **of_flat_tree = &images->ft_addr;
+       struct lmb *lmb = &images->lmb;
+
+       if (*of_flat_tree) {
+               boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
+
+               ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
+               if (ret)
+                       return;
+
+               ret = fdt_add_subnode(*of_flat_tree, 0, "chosen");
+               if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) {
+                       bootline = getenv("bootargs");
+                       if (bootline) {
+                               ret = fdt_find_and_setprop(*of_flat_tree,
+                                               "/chosen", "bootargs",
+                                               bootline,
+                                               strlen(bootline) + 1, 1);
+                               if (ret < 0) {
+                                       printf("## ERROR: %s : %s\n", __func__,
+                                              fdt_strerror(ret));
+                                       return;
+                               }
+                       }
+               } else {
+                       printf("## ERROR: %s : %s\n", __func__,
+                              fdt_strerror(ret));
+                       return;
+               }
+       }
+#endif
+
+       boot_prep_vxworks(images);
+
+       bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+
+#if defined(CONFIG_OF_LIBFDT)
+       printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n",
+              (ulong)images->ep, (ulong)*of_flat_tree);
+#else
+       printf("## Starting vxWorks at 0x%08lx\n", (ulong)images->ep);
+#endif
+
+       boot_jump_vxworks(images);
+
+       puts("## vxWorks terminated\n");
+}
+
 static int do_bootm_vxworks(int flag, int argc, char * const argv[],
                             bootm_headers_t *images)
 {
-       char str[80];
-
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1701,23 +1784,21 @@ static int do_bootm_vxworks(int flag, int argc, char * const argv[],
        }
 #endif
 
-       sprintf(str, "%lx", images->ep); /* write entry-point into string */
-       setenv("loadaddr", str);
-       do_bootvx(NULL, 0, 0, NULL);
+       do_bootvx_fdt(images);
 
        return 1;
 }
+#endif
 
+#if defined(CONFIG_CMD_ELF)
 static int do_bootm_qnxelf(int flag, int argc, char * const argv[],
                            bootm_headers_t *images)
 {
        char *local_args[2];
        char str[16];
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {
@@ -1741,10 +1822,8 @@ static int do_bootm_integrity(int flag, int argc, char * const argv[],
 {
        void (*entry_point)(void);
 
-       if (flag & BOOTM_STATE_OS_PREP)
+       if (flag != BOOTM_STATE_OS_GO)
                return 0;
-       if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-               return 1;
 
 #if defined(CONFIG_FIT)
        if (!images->legacy_hdr_valid) {