]> git.sur5r.net Git - u-boot/blobdiff - common/cmd_bootm.c
Prepare v2013.01.01
[u-boot] / common / cmd_bootm.c
index d88f6c0253a1f0c8d12caaab61b127dd49391de6..1b8a8c15610f68954643f967081d61ca8eee0e74 100644 (file)
@@ -161,7 +161,7 @@ static boot_os_fn *boot_os[] = {
 bootm_headers_t images;                /* pointers to os/initrd/fdt images */
 
 /* Allow for arch specific config before we boot */
-void __arch_preboot_os(void)
+static void __arch_preboot_os(void)
 {
        /* please define platform specific arch_preboot_os() */
 }
@@ -169,25 +169,26 @@ void arch_preboot_os(void) __attribute__((weak, alias("__arch_preboot_os")));
 
 #define IH_INITRD_ARCH IH_ARCH_DEFAULT
 
-static void bootm_start_lmb(void)
-{
 #ifdef CONFIG_LMB
+static void boot_start_lmb(bootm_headers_t *images)
+{
        ulong           mem_start;
        phys_size_t     mem_size;
 
-       lmb_init(&images.lmb);
+       lmb_init(&images->lmb);
 
        mem_start = getenv_bootm_low();
        mem_size = getenv_bootm_size();
 
-       lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size);
+       lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size);
 
-       arch_lmb_reserve(&images.lmb);
-       board_lmb_reserve(&images.lmb);
+       arch_lmb_reserve(&images->lmb);
+       board_lmb_reserve(&images->lmb);
+}
 #else
-# define lmb_reserve(lmb, base, size)
+#define lmb_reserve(lmb, base, size)
+static inline void boot_start_lmb(bootm_headers_t *images) { }
 #endif
-}
 
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
@@ -197,7 +198,7 @@ static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]
        memset((void *)&images, 0, sizeof(images));
        images.verify = getenv_yesno("verify");
 
-       bootm_start_lmb();
+       boot_start_lmb(&images);
 
        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
 
@@ -473,7 +474,7 @@ static cmd_tbl_t cmd_bootm_sub[] = {
        U_BOOT_CMD_MKENT(go, 0, 1, (void *)BOOTM_STATE_OS_GO, "", ""),
 };
 
-int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
+static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
                        char * const argv[])
 {
        int ret = 0;
@@ -536,7 +537,7 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
                }
                        break;
 #endif
-#if defined(CONFIG_OF_LIBFDT)
+#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB)
                case BOOTM_STATE_FDT:
                {
                        boot_fdt_add_mem_rsv_regions(&images.lmb,
@@ -563,6 +564,13 @@ int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc,
                        break;
                case BOOTM_STATE_OS_GO:
                        disable_interrupts();
+#ifdef CONFIG_NETCONSOLE
+                       /*
+                        * Stop the ethernet stack if NetConsole could have
+                        * left it up
+                        */
+                       eth_halt();
+#endif
                        arch_preboot_os();
                        boot_fn(BOOTM_STATE_OS_GO, argc, argv, &images);
                        break;
@@ -584,12 +592,18 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef CONFIG_NEEDS_MANUAL_RELOC
        static int relocated = 0;
 
-       /* relocate boot function table */
        if (!relocated) {
                int i;
+
+               /* relocate boot function table */
                for (i = 0; i < ARRAY_SIZE(boot_os); i++)
                        if (boot_os[i] != NULL)
                                boot_os[i] += gd->reloc_off;
+
+               /* relocate names of sub-command table */
+               for (i = 0; i < ARRAY_SIZE(cmd_bootm_sub); i++)
+                       cmd_bootm_sub[i].name += gd->reloc_off;
+
                relocated = 1;
        }
 #endif
@@ -621,6 +635,11 @@ int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
         */
        iflag = disable_interrupts();
 
+#ifdef CONFIG_NETCONSOLE
+       /* Stop the ethernet stack if NetConsole could have left it up */
+       eth_halt();
+#endif
+
 #if defined(CONFIG_CMD_USB)
        /*
         * turn off USB to prevent the host controller from writing to the
@@ -936,8 +955,19 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
                         * node
                         */
                        bootstage_mark(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
+#ifdef CONFIG_FIT_BEST_MATCH
+                       if (fit_uname_config)
+                               cfg_noffset =
+                                       fit_conf_get_node(fit_hdr,
+                                                         fit_uname_config);
+                       else
+                               cfg_noffset =
+                                       fit_conf_find_compat(fit_hdr,
+                                                            gd->fdt_blob);
+#else
                        cfg_noffset = fit_conf_get_node(fit_hdr,
                                                        fit_uname_config);
+#endif
                        if (cfg_noffset < 0) {
                                bootstage_error(BOOTSTAGE_ID_FIT_NO_UNIT_NAME);
                                return NULL;
@@ -1000,9 +1030,8 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
        return (void *)img_addr;
 }
 
-U_BOOT_CMD(
-       bootm,  CONFIG_SYS_MAXARGS,     1,      do_bootm,
-       "boot application image from memory",
+#ifdef CONFIG_SYS_LONGHELP
+static char bootm_help_text[] =
        "[addr [arg ...]]\n    - boot application image stored in memory\n"
        "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
        "\t'arg' can be the address of an initrd image\n"
@@ -1035,7 +1064,12 @@ U_BOOT_CMD(
        "\tcmdline - OS specific command line processing/setup\n"
        "\tbdt     - OS specific bd_t processing\n"
        "\tprep    - OS specific prep before relocation or go\n"
-       "\tgo      - start OS"
+       "\tgo      - start OS";
+#endif
+
+U_BOOT_CMD(
+       bootm,  CONFIG_SYS_MAXARGS,     1,      do_bootm,
+       "boot application image from memory", bootm_help_text
 );
 
 /*******************************************************************/
@@ -1071,7 +1105,7 @@ U_BOOT_CMD(
 /* iminfo - print header info for a requested image */
 /*******************************************************************/
 #if defined(CONFIG_CMD_IMI)
-int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_iminfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        int     arg;
        ulong   addr;
@@ -1158,7 +1192,7 @@ U_BOOT_CMD(
 /* imls - list all images found in flash */
 /*******************************************************************/
 #if defined(CONFIG_CMD_IMLS)
-int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        flash_info_t *info;
        int i, j;
@@ -1518,3 +1552,137 @@ static int do_bootm_integrity(int flag, int argc, char * const argv[],
        return 1;
 }
 #endif
+
+#ifdef CONFIG_CMD_BOOTZ
+
+static int __bootz_setup(void *image, void **start, void **end)
+{
+       /* Please define bootz_setup() for your platform */
+
+       puts("Your platform's zImage format isn't supported yet!\n");
+       return -1;
+}
+int bootz_setup(void *image, void **start, void **end)
+       __attribute__((weak, alias("__bootz_setup")));
+
+/*
+ * zImage booting support
+ */
+static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char * const argv[], bootm_headers_t *images)
+{
+       int ret;
+       void *zi_start, *zi_end;
+
+       memset(images, 0, sizeof(bootm_headers_t));
+
+       boot_start_lmb(images);
+
+       /* Setup Linux kernel zImage entry point */
+       if (argc < 2) {
+               images->ep = load_addr;
+               debug("*  kernel: default image load address = 0x%08lx\n",
+                               load_addr);
+       } else {
+               images->ep = simple_strtoul(argv[1], NULL, 16);
+               debug("*  kernel: cmdline image address = 0x%08lx\n",
+                       images->ep);
+       }
+
+       ret = bootz_setup((void *)images->ep, &zi_start, &zi_end);
+       if (ret != 0)
+               return 1;
+
+       lmb_reserve(&images->lmb, images->ep, zi_end - zi_start);
+
+       /* Find ramdisk */
+       ret = boot_get_ramdisk(argc, argv, images, IH_INITRD_ARCH,
+                       &images->rd_start, &images->rd_end);
+       if (ret) {
+               puts("Ramdisk image is corrupt or invalid\n");
+               return 1;
+       }
+
+#if defined(CONFIG_OF_LIBFDT)
+       /* find flattened device tree */
+       ret = boot_get_fdt(flag, argc, argv, images,
+                          &images->ft_addr, &images->ft_len);
+       if (ret) {
+               puts("Could not find a valid device tree\n");
+               return 1;
+       }
+
+       set_working_fdt_addr(images->ft_addr);
+#endif
+
+       return 0;
+}
+
+static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+       bootm_headers_t images;
+
+       if (bootz_start(cmdtp, flag, argc, argv, &images))
+               return 1;
+
+       /*
+        * We have reached the point of no return: we are going to
+        * overwrite all exception vector code, so we cannot easily
+        * recover from any failures any more...
+        */
+       disable_interrupts();
+
+#ifdef CONFIG_NETCONSOLE
+       /* Stop the ethernet stack if NetConsole could have left it up */
+       eth_halt();
+#endif
+
+#if defined(CONFIG_CMD_USB)
+       /*
+        * turn off USB to prevent the host controller from writing to the
+        * SDRAM while Linux is booting. This could happen (at least for OHCI
+        * controller), because the HCCA (Host Controller Communication Area)
+        * lies within the SDRAM and the host controller writes continously to
+        * this area (as busmaster!). The HccaFrameNumber is for example
+        * updated every 1 ms within the HCCA structure in SDRAM! For more
+        * details see the OpenHCI specification.
+        */
+       usb_stop();
+#endif
+
+#ifdef CONFIG_SILENT_CONSOLE
+       fixup_silent_linux();
+#endif
+       arch_preboot_os();
+
+       do_bootm_linux(0, argc, argv, &images);
+#ifdef DEBUG
+       puts("\n## Control returned to monitor - resetting...\n");
+#endif
+       do_reset(cmdtp, flag, argc, argv);
+
+       return 1;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char bootz_help_text[] =
+       "[addr [initrd[:size]] [fdt]]\n"
+       "    - boot Linux zImage stored in memory\n"
+       "\tThe argument 'initrd' is optional and specifies the address\n"
+       "\tof the initrd in memory. The optional argument ':size' allows\n"
+       "\tspecifying the size of RAW initrd.\n"
+#if defined(CONFIG_OF_LIBFDT)
+       "\tWhen booting a Linux kernel which requires a flat device-tree\n"
+       "\ta third argument is required which is the address of the\n"
+       "\tdevice-tree blob. To boot that kernel without an initrd image,\n"
+       "\tuse a '-' for the second argument. If you do not pass a third\n"
+       "\ta bd_info struct will be passed instead\n"
+#endif
+       "";
+#endif
+
+U_BOOT_CMD(
+       bootz,  CONFIG_SYS_MAXARGS,     1,      do_bootz,
+       "boot Linux zImage image from memory", bootz_help_text
+);
+#endif /* CONFIG_CMD_BOOTZ */