BOOT: Add "bootz" command to boot Linux zImage on ARM
authorMarek Vasut <marek.vasut@gmail.com>
Wed, 14 Mar 2012 21:52:45 +0000 (21:52 +0000)
committerWolfgang Denk <wd@denx.de>
Fri, 30 Mar 2012 20:58:55 +0000 (22:58 +0200)
This command boots Linux zImage from where the zImage is loaded to. Passing
initrd and fdt is supported.

Tested on i.MX28 based DENX M28EVK
Tested on PXA270 based Voipac PXA270.

NOTE: This currently only supports ARM, but other architectures can be easily
added by defining bootz_setup().

Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Cc: Tom Warren <TWarren@nvidia.com>
Cc: albert.u.boot@aribaud.net
Cc: afleming@gmail.com,
Cc: Simon Glass <sjg@chromium.org>,
Cc: Stephen Warren <swarren@nvidia.com>
Cc: Nicolas Pitre <nico@fluxnic.net>
Cc: Wolfgang Denk <wd@denx.de>
Cc: Detlev Zundel <dzu@denx.de>
README
arch/arm/lib/bootm.c
common/cmd_bootm.c
include/config_cmd_all.h

diff --git a/README b/README
index 92a11b4e11fc53f251ff235d2313e6aeb3565959..a9dc69bae0592c99544c575c01dd251b9deff0a1 100644 (file)
--- a/README
+++ b/README
@@ -3609,6 +3609,7 @@ go        - start application at address 'addr'
 run    - run commands in an environment variable
 bootm  - boot application image from memory
 bootp  - boot image via network using BootP/TFTP protocol
+bootz   - boot zImage from memory
 tftpboot- boot image via network using TFTP protocol
               and env variables "ipaddr" and "serverip"
               (and eventually "gatewayip")
@@ -4429,6 +4430,13 @@ U-Boot supports the following image types:
        useful when you configure U-Boot to use a real shell (hush)
        as command interpreter.
 
+Booting the Linux zImage:
+-------------------------
+
+On some platforms, it's possible to boot Linux zImage. This is done
+using the "bootz" command. The syntax of "bootz" command is the same
+as the syntax of "bootm" command.
+
 
 Standalone HOWTO:
 =================
index 160ba55111177f3f3f803c159e43ab2c9744fde4..1c1bee6aeb135251eac353783a6fb76196c2961a 100644 (file)
@@ -359,3 +359,33 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
        boot_jump_linux(images);
        return 0;
 }
+
+#ifdef CONFIG_CMD_BOOTZ
+
+struct zimage_header {
+       uint32_t        code[9];
+       uint32_t        zi_magic;
+       uint32_t        zi_start;
+       uint32_t        zi_end;
+};
+
+#define        LINUX_ARM_ZIMAGE_MAGIC  0x016f2818
+
+int bootz_setup(void *image, void **start, void **end)
+{
+       struct zimage_header *zi = (struct zimage_header *)image;
+
+       if (zi->zi_magic != LINUX_ARM_ZIMAGE_MAGIC) {
+               puts("Bad Linux ARM zImage magic!\n");
+               return 1;
+       }
+
+       *start = (void *)zi->zi_start;
+       *end = (void *)zi->zi_end;
+
+       debug("Kernel image @ 0x%08x [ 0x%08x - 0x%08x ]\n",
+               (uint32_t)image, (uint32_t)*start, (uint32_t)*end);
+
+       return 0;
+}
+#endif /* CONFIG_CMD_BOOTZ */
index d88f6c0253a1f0c8d12caaab61b127dd49391de6..5e5d572ebf294397fed0015efbfdb841ea3cf64f 100644 (file)
@@ -169,25 +169,25 @@ 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)
+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 +197,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");
 
@@ -1518,3 +1518,126 @@ 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[])
+{
+       ulong           iflag;
+       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...
+        */
+       iflag = disable_interrupts();
+
+#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;
+}
+
+U_BOOT_CMD(
+       bootz,  CONFIG_SYS_MAXARGS,     1,      do_bootz,
+       "boot Linux zImage image from memory",
+       "[addr [initrd] [fdt]]\n    - boot Linux zImage stored in memory\n"
+       "\tThe argument 'initrd' is optional and specifies the address\n"
+       "\tof the initrd in memory.\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 /* CONFIG_CMD_BOOTZ */
index 9716f9cad47ae93b563d3303e17f51a4a1203333..2c6b8295fb88f1c5a673bfb1c08f86a667c92fb2 100644 (file)
@@ -20,6 +20,7 @@
 #define CONFIG_CMD_BEDBUG      /* Include BedBug Debugger      */
 #define CONFIG_CMD_BMP         /* BMP support                  */
 #define CONFIG_CMD_BOOTD       /* bootd                        */
+#define CONFIG_CMD_BOOTZ       /* boot zImage                  */
 #define CONFIG_CMD_BSP         /* Board Specific functions     */
 #define CONFIG_CMD_CACHE       /* icache, dcache               */
 #define CONFIG_CMD_CDP         /* Cisco Discovery Protocol     */