1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2011 The Chromium OS Authors.
5 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
9 * Linux x86 zImage and bzImage loading
11 * based on the procdure described in
12 * linux/Documentation/i386/boot.txt
15 #define LOG_CATEGORY LOGC_BOOT
25 #include <acpi/acpi_table.h>
27 #include <asm/ptrace.h>
28 #include <asm/zimage.h>
29 #include <asm/byteorder.h>
30 #include <asm/bootm.h>
31 #include <asm/bootparam.h>
32 #include <asm/global_data.h>
33 #ifdef CONFIG_SYS_COREBOOT
34 #include <asm/arch/timestamp.h>
36 #include <linux/compiler.h>
37 #include <linux/ctype.h>
38 #include <linux/libfdt.h>
40 DECLARE_GLOBAL_DATA_PTR
;
45 * relative to setup_base (which is 0x90000 currently)
47 * 0x0000-0x7FFF Real mode kernel
48 * 0x8000-0x8FFF Stack and heap
49 * 0x9000-0x90FF Kernel command line
51 #define DEFAULT_SETUP_BASE 0x90000
52 #define COMMAND_LINE_OFFSET 0x9000
53 #define HEAP_END_OFFSET 0x8e00
55 #define COMMAND_LINE_SIZE 2048
58 * struct zboot_state - Current state of the boot
60 * @bzimage_addr: Address of the bzImage to boot
61 * @bzimage_size: Size of the bzImage, or 0 to detect this
62 * @initrd_addr: Address of the initial ramdisk, or 0 if none
63 * @initrd_size: Size of the initial ramdisk, or 0 if none
64 * @load_address: Address where the bzImage is moved before booting, either
65 * BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
66 * @base_ptr: Pointer to the boot parameters, typically at address
68 * @cmdline: Environment variable containing the 'override' command line, or
69 * NULL to use the one in the setup block
77 struct boot_params
*base_ptr
;
82 ZBOOT_STATE_START
= BIT(0),
83 ZBOOT_STATE_LOAD
= BIT(1),
84 ZBOOT_STATE_SETUP
= BIT(2),
85 ZBOOT_STATE_INFO
= BIT(3),
86 ZBOOT_STATE_GO
= BIT(4),
88 /* This one doesn't execute automatically, so stop the count before 5 */
89 ZBOOT_STATE_DUMP
= BIT(5),
90 ZBOOT_STATE_COUNT
= 5,
93 static void build_command_line(char *command_line
, int auto_boot
)
95 char *env_command_line
;
97 command_line
[0] = '\0';
99 env_command_line
= env_get("bootargs");
101 /* set console= argument if we use a serial console */
102 if (!strstr(env_command_line
, "console=")) {
103 if (!strcmp(env_get("stdout"), "serial")) {
105 /* We seem to use serial console */
106 sprintf(command_line
, "console=ttyS0,%s ",
107 env_get("baudrate"));
112 strcat(command_line
, "auto ");
114 if (env_command_line
)
115 strcat(command_line
, env_command_line
);
117 printf("Kernel command line:");
123 static int kernel_magic_ok(struct setup_header
*hdr
)
125 if (KERNEL_MAGIC
!= hdr
->boot_flag
) {
126 printf("Error: Invalid Boot Flag "
127 "(found 0x%04x, expected 0x%04x)\n",
128 hdr
->boot_flag
, KERNEL_MAGIC
);
131 printf("Valid Boot Flag\n");
136 static int get_boot_protocol(struct setup_header
*hdr
, bool verbose
)
138 if (hdr
->header
== KERNEL_V2_MAGIC
) {
140 printf("Magic signature found\n");
143 /* Very old kernel */
145 printf("Magic signature not found\n");
150 static int setup_device_tree(struct setup_header
*hdr
, const void *fdt_blob
)
152 int bootproto
= get_boot_protocol(hdr
, false);
153 struct setup_data
*sd
;
156 if (bootproto
< 0x0209)
162 size
= fdt_totalsize(fdt_blob
);
166 size
+= sizeof(struct setup_data
);
167 sd
= (struct setup_data
*)malloc(size
);
169 printf("Not enough memory for DTB setup data\n");
173 sd
->next
= hdr
->setup_data
;
174 sd
->type
= SETUP_DTB
;
175 sd
->len
= fdt_totalsize(fdt_blob
);
176 memcpy(sd
->data
, fdt_blob
, sd
->len
);
177 hdr
->setup_data
= (unsigned long)sd
;
182 static const char *get_kernel_version(struct boot_params
*params
,
185 struct setup_header
*hdr
= ¶ms
->hdr
;
189 bootproto
= get_boot_protocol(hdr
, false);
190 if (bootproto
< 0x0200 || hdr
->setup_sects
< 15)
193 /* sanity-check the kernel version in case it is missing */
194 for (s
= kernel_base
+ hdr
->kernel_version
+ 0x200, end
= s
+ 0x100; *s
;
200 return kernel_base
+ hdr
->kernel_version
+ 0x200;
203 struct boot_params
*load_zimage(char *image
, unsigned long kernel_size
,
204 ulong
*load_addressp
)
206 struct boot_params
*setup_base
;
212 struct boot_params
*params
= (struct boot_params
*)image
;
213 struct setup_header
*hdr
= ¶ms
->hdr
;
215 /* base address for real-mode segment */
216 setup_base
= (struct boot_params
*)DEFAULT_SETUP_BASE
;
218 if (!kernel_magic_ok(hdr
))
221 /* determine size of setup */
222 if (0 == hdr
->setup_sects
) {
223 log_warning("Setup Sectors = 0 (defaulting to 4)\n");
224 setup_size
= 5 * 512;
226 setup_size
= (hdr
->setup_sects
+ 1) * 512;
229 log_debug("Setup Size = 0x%8.8lx\n", (ulong
)setup_size
);
231 if (setup_size
> SETUP_MAX_SIZE
)
232 printf("Error: Setup is too large (%d bytes)\n", setup_size
);
234 /* determine boot protocol version */
235 bootproto
= get_boot_protocol(hdr
, true);
237 log_debug("Using boot protocol version %x.%02x\n",
238 (bootproto
& 0xff00) >> 8, bootproto
& 0xff);
240 version
= get_kernel_version(params
, image
);
242 printf("Linux kernel version %s\n", version
);
244 printf("Setup Sectors < 15 - Cannot print kernel version\n");
246 /* Determine image type */
247 big_image
= (bootproto
>= 0x0200) &&
248 (hdr
->loadflags
& BIG_KERNEL_FLAG
);
250 /* Determine load address */
252 *load_addressp
= BZIMAGE_LOAD_ADDR
;
254 *load_addressp
= ZIMAGE_LOAD_ADDR
;
256 printf("Building boot_params at 0x%8.8lx\n", (ulong
)setup_base
);
257 memset(setup_base
, 0, sizeof(*setup_base
));
258 setup_base
->hdr
= params
->hdr
;
260 if (bootproto
>= 0x0204)
261 kernel_size
= hdr
->syssize
* 16;
263 kernel_size
-= setup_size
;
265 if (bootproto
== 0x0100) {
267 * A very old kernel MUST have its real-mode code
270 if ((ulong
)setup_base
!= 0x90000) {
271 /* Copy the real-mode kernel */
272 memmove((void *)0x90000, setup_base
, setup_size
);
274 /* Copy the command line */
275 memmove((void *)0x99000,
276 (u8
*)setup_base
+ COMMAND_LINE_OFFSET
,
280 setup_base
= (struct boot_params
*)0x90000;
283 /* It is recommended to clear memory up to the 32K mark */
284 memset((u8
*)0x90000 + setup_size
, 0,
285 SETUP_MAX_SIZE
- setup_size
);
289 if (kernel_size
> BZIMAGE_MAX_SIZE
) {
290 printf("Error: bzImage kernel too big! "
291 "(size: %ld, max: %d)\n",
292 kernel_size
, BZIMAGE_MAX_SIZE
);
295 } else if ((kernel_size
) > ZIMAGE_MAX_SIZE
) {
296 printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
297 kernel_size
, ZIMAGE_MAX_SIZE
);
301 printf("Loading %s at address %lx (%ld bytes)\n",
302 big_image
? "bzImage" : "zImage", *load_addressp
, kernel_size
);
304 memmove((void *)*load_addressp
, image
+ setup_size
, kernel_size
);
309 int setup_zimage(struct boot_params
*setup_base
, char *cmd_line
, int auto_boot
,
310 ulong initrd_addr
, ulong initrd_size
, ulong cmdline_force
)
312 struct setup_header
*hdr
= &setup_base
->hdr
;
313 int bootproto
= get_boot_protocol(hdr
, false);
315 log_debug("Setup E820 entries\n");
316 if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO
)) {
317 setup_base
->e820_entries
= cb_install_e820_map(
318 ARRAY_SIZE(setup_base
->e820_map
), setup_base
->e820_map
);
320 setup_base
->e820_entries
= install_e820_map(
321 ARRAY_SIZE(setup_base
->e820_map
), setup_base
->e820_map
);
324 if (bootproto
== 0x0100) {
325 setup_base
->screen_info
.cl_magic
= COMMAND_LINE_MAGIC
;
326 setup_base
->screen_info
.cl_offset
= COMMAND_LINE_OFFSET
;
328 if (bootproto
>= 0x0200) {
329 hdr
->type_of_loader
= 0x80; /* U-Boot version 0 */
331 printf("Initial RAM disk at linear address "
332 "0x%08lx, size %ld bytes\n",
333 initrd_addr
, initrd_size
);
335 hdr
->ramdisk_image
= initrd_addr
;
336 hdr
->ramdisk_size
= initrd_size
;
340 if (bootproto
>= 0x0201) {
341 hdr
->heap_end_ptr
= HEAP_END_OFFSET
;
342 hdr
->loadflags
|= HEAP_FLAG
;
349 log_debug("Setup cmdline\n");
350 if (bootproto
>= 0x0206)
351 max_size
= hdr
->cmdline_size
;
352 if (bootproto
>= 0x0202) {
353 hdr
->cmd_line_ptr
= (uintptr_t)cmd_line
;
354 } else if (bootproto
>= 0x0200) {
355 setup_base
->screen_info
.cl_magic
= COMMAND_LINE_MAGIC
;
356 setup_base
->screen_info
.cl_offset
=
357 (uintptr_t)cmd_line
- (uintptr_t)setup_base
;
359 hdr
->setup_move_size
= 0x9100;
362 /* build command line at COMMAND_LINE_OFFSET */
364 strcpy(cmd_line
, (char *)cmdline_force
);
366 build_command_line(cmd_line
, auto_boot
);
367 ret
= bootm_process_cmdline(cmd_line
, max_size
, BOOTM_CL_ALL
);
369 printf("Cmdline setup failed (max_size=%x, bootproto=%x, err=%d)\n",
370 max_size
, bootproto
, ret
);
373 printf("Kernel command line: \"");
378 if (IS_ENABLED(CONFIG_INTEL_MID
) && bootproto
>= 0x0207)
379 hdr
->hardware_subarch
= X86_SUBARCH_INTEL_MID
;
381 if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE
))
382 setup_base
->acpi_rsdp_addr
= acpi_get_rsdp_addr();
384 log_debug("Setup devicetree\n");
385 setup_device_tree(hdr
, (const void *)env_get_hex("fdtaddr", 0));
386 setup_video(&setup_base
->screen_info
);
388 if (IS_ENABLED(CONFIG_EFI_STUB
))
389 setup_efi_info(&setup_base
->efi_info
);
394 static int do_zboot_start(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
399 memset(&state
, '\0', sizeof(state
));
401 /* argv[1] holds the address of the bzImage */
404 s
= env_get("fileaddr");
408 state
.bzimage_addr
= hextoul(s
, NULL
);
411 /* argv[2] holds the size of the bzImage */
412 state
.bzimage_size
= hextoul(argv
[2], NULL
);
416 state
.initrd_addr
= hextoul(argv
[3], NULL
);
418 state
.initrd_size
= hextoul(argv
[4], NULL
);
421 * When the base_ptr is passed in, we assume that the image is
422 * already loaded at the address given by argv[1] and therefore
423 * the original bzImage is somewhere else, or not accessible.
424 * In any case, we don't need access to the bzImage since all
425 * the processing is assumed to be done.
427 * So set the base_ptr to the given address, use this arg as the
428 * load address and set bzimage_addr to 0 so we know that it
429 * cannot be proceesed (or processed again).
431 state
.base_ptr
= (void *)hextoul(argv
[5], NULL
);
432 state
.load_address
= state
.bzimage_addr
;
433 state
.bzimage_addr
= 0;
436 state
.cmdline
= env_get(argv
[6]);
441 static int do_zboot_load(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
444 struct boot_params
*base_ptr
;
446 if (state
.base_ptr
) {
447 struct boot_params
*from
= (struct boot_params
*)state
.base_ptr
;
449 base_ptr
= (struct boot_params
*)DEFAULT_SETUP_BASE
;
450 log_debug("Building boot_params at 0x%8.8lx\n",
452 memset(base_ptr
, '\0', sizeof(*base_ptr
));
453 base_ptr
->hdr
= from
->hdr
;
455 base_ptr
= load_zimage((void *)state
.bzimage_addr
, state
.bzimage_size
,
456 &state
.load_address
);
458 puts("## Kernel loading failed ...\n");
459 return CMD_RET_FAILURE
;
462 state
.base_ptr
= base_ptr
;
463 if (env_set_hex("zbootbase", (ulong
)base_ptr
) ||
464 env_set_hex("zbootaddr", state
.load_address
))
465 return CMD_RET_FAILURE
;
470 static int do_zboot_setup(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
473 struct boot_params
*base_ptr
= state
.base_ptr
;
477 printf("base is not set: use 'zboot load' first\n");
478 return CMD_RET_FAILURE
;
480 ret
= setup_zimage(base_ptr
, (char *)base_ptr
+ COMMAND_LINE_OFFSET
,
481 0, state
.initrd_addr
, state
.initrd_size
,
482 (ulong
)state
.cmdline
);
484 puts("Setting up boot parameters failed ...\n");
485 return CMD_RET_FAILURE
;
491 static int do_zboot_info(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
494 printf("Kernel loaded at %08lx, setup_base=%p\n",
495 state
.load_address
, state
.base_ptr
);
500 static int do_zboot_go(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
505 disable_interrupts();
507 /* we assume that the kernel is in place */
508 ret
= boot_linux_kernel((ulong
)state
.base_ptr
, state
.load_address
,
510 printf("Kernel returned! (err=%d)\n", ret
);
512 return CMD_RET_FAILURE
;
515 static void print_num(const char *name
, ulong value
)
517 printf("%-20s: %lx\n", name
, value
);
520 static void print_num64(const char *name
, u64 value
)
522 printf("%-20s: %llx\n", name
, value
);
525 static const char *const e820_type_name
[E820_COUNT
] = {
527 [E820_RESERVED
] = "Reserved",
528 [E820_ACPI
] = "ACPI",
529 [E820_NVS
] = "ACPI NVS",
530 [E820_UNUSABLE
] = "Unusable",
533 static const char *const bootloader_id
[] = {
538 "Etherboot/gPXE/iPXE",
546 "Arcturus Networks uCbootloader",
551 "Minimal Linux Bootloader",
552 "OVMF UEFI virtualization stack",
560 static struct flag_info load_flags
[] = {
561 { LOADED_HIGH
, "loaded-high" },
562 { QUIET_FLAG
, "quiet" },
563 { KEEP_SEGMENTS
, "keep-segments" },
564 { CAN_USE_HEAP
, "can-use-heap" },
567 static struct flag_info xload_flags
[] = {
568 { XLF_KERNEL_64
, "64-bit-entry" },
569 { XLF_CAN_BE_LOADED_ABOVE_4G
, "can-load-above-4gb" },
570 { XLF_EFI_HANDOVER_32
, "32-efi-handoff" },
571 { XLF_EFI_HANDOVER_64
, "64-efi-handoff" },
572 { XLF_EFI_KEXEC
, "kexec-efi-runtime" },
575 static void print_flags(struct flag_info
*flags
, int count
, uint value
)
579 printf("%-20s:", "");
580 for (i
= 0; i
< count
; i
++) {
581 uint mask
= flags
[i
].bit
;
584 printf(" %s", flags
[i
].name
);
589 static void show_loader(struct setup_header
*hdr
)
591 bool version_valid
= false;
595 type
= hdr
->type_of_loader
>> 4;
596 version
= hdr
->type_of_loader
& 0xf;
598 type
= 0x10 + hdr
->ext_loader_type
;
599 version
|= hdr
->ext_loader_ver
<< 4;
600 if (!hdr
->type_of_loader
) {
601 name
= "pre-2.00 bootloader";
602 } else if (hdr
->type_of_loader
== 0xff) {
604 } else if (type
< ARRAY_SIZE(bootloader_id
)) {
605 name
= bootloader_id
[type
];
606 version_valid
= true;
610 printf("%20s %s", "", name
);
612 printf(", version %x", version
);
616 void zimage_dump(struct boot_params
*base_ptr
)
618 struct setup_header
*hdr
;
622 printf("Setup located at %p:\n\n", base_ptr
);
623 print_num64("ACPI RSDP addr", base_ptr
->acpi_rsdp_addr
);
625 printf("E820: %d entries\n", base_ptr
->e820_entries
);
626 if (base_ptr
->e820_entries
) {
627 printf("%18s %16s %s\n", "Addr", "Size", "Type");
628 for (i
= 0; i
< base_ptr
->e820_entries
; i
++) {
629 struct e820_entry
*entry
= &base_ptr
->e820_map
[i
];
631 printf("%12llx %10llx %s\n", entry
->addr
, entry
->size
,
632 entry
->type
< E820_COUNT
?
633 e820_type_name
[entry
->type
] :
634 simple_itoa(entry
->type
));
638 hdr
= &base_ptr
->hdr
;
639 print_num("Setup sectors", hdr
->setup_sects
);
640 print_num("Root flags", hdr
->root_flags
);
641 print_num("Sys size", hdr
->syssize
);
642 print_num("RAM size", hdr
->ram_size
);
643 print_num("Video mode", hdr
->vid_mode
);
644 print_num("Root dev", hdr
->root_dev
);
645 print_num("Boot flag", hdr
->boot_flag
);
646 print_num("Jump", hdr
->jump
);
647 print_num("Header", hdr
->header
);
648 if (hdr
->header
== KERNEL_V2_MAGIC
)
649 printf("%-20s %s\n", "", "Kernel V2");
651 printf("%-20s %s\n", "", "Ancient kernel, using version 100");
652 print_num("Version", hdr
->version
);
653 print_num("Real mode switch", hdr
->realmode_swtch
);
654 print_num("Start sys", hdr
->start_sys
);
655 print_num("Kernel version", hdr
->kernel_version
);
656 version
= get_kernel_version(base_ptr
, (void *)state
.bzimage_addr
);
658 printf(" @%p: %s\n", version
, version
);
659 print_num("Type of loader", hdr
->type_of_loader
);
661 print_num("Load flags", hdr
->loadflags
);
662 print_flags(load_flags
, ARRAY_SIZE(load_flags
), hdr
->loadflags
);
663 print_num("Setup move size", hdr
->setup_move_size
);
664 print_num("Code32 start", hdr
->code32_start
);
665 print_num("Ramdisk image", hdr
->ramdisk_image
);
666 print_num("Ramdisk size", hdr
->ramdisk_size
);
667 print_num("Bootsect kludge", hdr
->bootsect_kludge
);
668 print_num("Heap end ptr", hdr
->heap_end_ptr
);
669 print_num("Ext loader ver", hdr
->ext_loader_ver
);
670 print_num("Ext loader type", hdr
->ext_loader_type
);
671 print_num("Command line ptr", hdr
->cmd_line_ptr
);
672 if (hdr
->cmd_line_ptr
) {
674 /* Use puts() to avoid limits from CONFIG_SYS_PBSIZE */
675 puts((char *)(ulong
)hdr
->cmd_line_ptr
);
678 print_num("Initrd addr max", hdr
->initrd_addr_max
);
679 print_num("Kernel alignment", hdr
->kernel_alignment
);
680 print_num("Relocatable kernel", hdr
->relocatable_kernel
);
681 print_num("Min alignment", hdr
->min_alignment
);
682 if (hdr
->min_alignment
)
683 printf("%-20s: %x\n", "", 1 << hdr
->min_alignment
);
684 print_num("Xload flags", hdr
->xloadflags
);
685 print_flags(xload_flags
, ARRAY_SIZE(xload_flags
), hdr
->xloadflags
);
686 print_num("Cmdline size", hdr
->cmdline_size
);
687 print_num("Hardware subarch", hdr
->hardware_subarch
);
688 print_num64("HW subarch data", hdr
->hardware_subarch_data
);
689 print_num("Payload offset", hdr
->payload_offset
);
690 print_num("Payload length", hdr
->payload_length
);
691 print_num64("Setup data", hdr
->setup_data
);
692 print_num64("Pref address", hdr
->pref_address
);
693 print_num("Init size", hdr
->init_size
);
694 print_num("Handover offset", hdr
->handover_offset
);
695 if (get_boot_protocol(hdr
, false) >= 0x215)
696 print_num("Kernel info offset", hdr
->kernel_info_offset
);
699 static int do_zboot_dump(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
702 struct boot_params
*base_ptr
= state
.base_ptr
;
705 base_ptr
= (void *)hextoul(argv
[1], NULL
);
707 printf("No zboot setup_base\n");
708 return CMD_RET_FAILURE
;
710 zimage_dump(base_ptr
);
715 /* Note: This defines the complete_zboot() function */
716 U_BOOT_SUBCMDS(zboot
,
717 U_BOOT_CMD_MKENT(start
, 8, 1, do_zboot_start
, "", ""),
718 U_BOOT_CMD_MKENT(load
, 1, 1, do_zboot_load
, "", ""),
719 U_BOOT_CMD_MKENT(setup
, 1, 1, do_zboot_setup
, "", ""),
720 U_BOOT_CMD_MKENT(info
, 1, 1, do_zboot_info
, "", ""),
721 U_BOOT_CMD_MKENT(go
, 1, 1, do_zboot_go
, "", ""),
722 U_BOOT_CMD_MKENT(dump
, 2, 1, do_zboot_dump
, "", ""),
725 int do_zboot_states(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
726 char *const argv
[], int state_mask
)
730 for (i
= 0; i
< ZBOOT_STATE_COUNT
; i
++) {
731 struct cmd_tbl
*cmd
= &zboot_subcmds
[i
];
735 if (mask
& state_mask
) {
736 ret
= cmd
->cmd(cmd
, flag
, argc
, argv
);
745 int do_zboot_parent(struct cmd_tbl
*cmdtp
, int flag
, int argc
,
746 char *const argv
[], int *repeatable
)
748 /* determine if we have a sub command */
752 hextoul(argv
[1], &endp
);
754 * endp pointing to nul means that argv[1] was just a valid
755 * number, so pass it along to the normal processing
758 return do_zboot(cmdtp
, flag
, argc
, argv
, repeatable
);
761 do_zboot_states(cmdtp
, flag
, argc
, argv
, ZBOOT_STATE_START
|
762 ZBOOT_STATE_LOAD
| ZBOOT_STATE_SETUP
|
763 ZBOOT_STATE_INFO
| ZBOOT_STATE_GO
);
765 return CMD_RET_FAILURE
;
768 U_BOOT_CMDREP_COMPLETE(
769 zboot
, 8, do_zboot_parent
, "Boot bzImage",
770 "[addr] [size] [initrd addr] [initrd size] [setup] [cmdline]\n"
771 " addr - The optional starting address of the bzimage.\n"
772 " If not set it defaults to the environment\n"
773 " variable \"fileaddr\".\n"
774 " size - The optional size of the bzimage. Defaults to\n"
776 " initrd addr - The address of the initrd image to use, if any.\n"
777 " initrd size - The size of the initrd image to use, if any.\n"
778 " setup - The address of the kernel setup region, if this\n"
780 " cmdline - Environment variable containing the kernel\n"
781 " command line, to override U-Boot's normal\n"
782 " cmdline generation\n"
784 "Sub-commands to do part of the zboot sequence:\n"
785 "\tstart [addr [arg ...]] - specify arguments\n"
786 "\tload - load OS image\n"
787 "\tsetup - set up table\n"
788 "\tinfo - show summary info\n"
790 "\tdump [addr] - dump info (optional address of boot params)",