2 * (C) Copyright 2000-2006
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
35 #include <environment.h>
36 #include <asm/byteorder.h>
45 #include <asm-generic/memory_layout.h>
48 * Continue booting an OS image; caller already has:
49 * - copied image header to global variable `header'
50 * - checked header magic number, checksums (both header & image),
51 * - verified image architecture (PPC) and type (KERNEL or MULTI),
52 * - loaded (first part of) image to header load address,
53 * - disabled interrupts.
55 typedef void boot_os_Fcn(struct command
*cmdtp
, int flag
,
56 int argc
, char *argv
[],
57 ulong addr
, /* of image to boot */
58 ulong
*len_ptr
, /* multi-file image length table */
59 int verify
); /* getenv("verify")[0] != 'n' */
62 #define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */
65 #ifdef CONFIG_SILENT_CONSOLE
69 char buf
[256], *start
, *end
;
70 char *cmdline
= getenv ("bootargs");
72 /* Only fix cmdline when requested */
73 if (!(gd
->flags
& GD_FLG_SILENT
))
76 debug ("before silent fix-up: %s\n", cmdline
);
78 if ((start
= strstr (cmdline
, "console=")) != NULL
) {
79 end
= strchr (start
, ' ');
80 strncpy (buf
, cmdline
, (start
- cmdline
+ 8));
82 strcpy (buf
+ (start
- cmdline
+ 8), end
);
84 buf
[start
- cmdline
+ 8] = '\0';
86 strcpy (buf
, cmdline
);
87 strcat (buf
, " console=");
90 strcpy (buf
, "console=");
93 setenv ("bootargs", buf
);
94 debug ("after silent fix-up: %s\n", buf
);
96 #endif /* CONFIG_SILENT_CONSOLE */
98 #ifdef CONFIG_CMD_BOOTM_SHOW_TYPE
99 static const char *image_os(image_header_t
*hdr
)
103 switch (hdr
->ih_os
) {
104 case IH_OS_INVALID
: os
= "Invalid OS"; break;
105 case IH_OS_NETBSD
: os
= "NetBSD"; break;
106 case IH_OS_LINUX
: os
= "Linux"; break;
107 case IH_OS_VXWORKS
: os
= "VxWorks"; break;
108 case IH_OS_QNX
: os
= "QNX"; break;
109 case IH_OS_BAREBOX
: os
= "barebox"; break;
110 case IH_OS_RTEMS
: os
= "RTEMS"; break;
112 case IH_OS_ARTOS
: os
= "ARTOS"; break;
114 #ifdef CONFIG_LYNXKDI
115 case IH_OS_LYNXOS
: os
= "LynxOS"; break;
117 default: os
= "Unknown OS"; break;
123 static const char *image_arch(image_header_t
*hdr
)
127 switch (hdr
->ih_arch
) {
128 case IH_CPU_INVALID
: arch
= "Invalid CPU"; break;
129 case IH_CPU_ALPHA
: arch
= "Alpha"; break;
130 case IH_CPU_ARM
: arch
= "ARM"; break;
131 case IH_CPU_AVR32
: arch
= "AVR32"; break;
132 case IH_CPU_I386
: arch
= "Intel x86"; break;
133 case IH_CPU_IA64
: arch
= "IA64"; break;
134 case IH_CPU_MIPS
: arch
= "MIPS"; break;
135 case IH_CPU_MIPS64
: arch
= "MIPS 64 Bit"; break;
136 case IH_CPU_PPC
: arch
= "PowerPC"; break;
137 case IH_CPU_S390
: arch
= "IBM S390"; break;
138 case IH_CPU_SH
: arch
= "SuperH"; break;
139 case IH_CPU_SPARC
: arch
= "SPARC"; break;
140 case IH_CPU_SPARC64
: arch
= "SPARC 64 Bit"; break;
141 case IH_CPU_M68K
: arch
= "M68K"; break;
142 case IH_CPU_MICROBLAZE
: arch
= "Microblaze"; break;
143 case IH_CPU_NIOS
: arch
= "Nios"; break;
144 case IH_CPU_NIOS2
: arch
= "Nios-II"; break;
145 default: arch
= "Unknown Architecture"; break;
151 static const char *image_type(image_header_t
*hdr
)
155 switch (hdr
->ih_type
) {
156 case IH_TYPE_INVALID
: type
= "Invalid Image"; break;
157 case IH_TYPE_STANDALONE
:type
= "Standalone Program"; break;
158 case IH_TYPE_KERNEL
: type
= "Kernel Image"; break;
159 case IH_TYPE_RAMDISK
: type
= "RAMDisk Image"; break;
160 case IH_TYPE_MULTI
: type
= "Multi-File Image"; break;
161 case IH_TYPE_FIRMWARE
: type
= "Firmware"; break;
162 case IH_TYPE_SCRIPT
: type
= "Script"; break;
163 case IH_TYPE_FLATDT
: type
= "Flat Device Tree"; break;
164 default: type
= "Unknown Image"; break;
169 static const char *image_compression(image_header_t
*hdr
)
173 switch (hdr
->ih_comp
) {
174 case IH_COMP_NONE
: comp
= "uncompressed"; break;
175 case IH_COMP_GZIP
: comp
= "gzip compressed"; break;
176 case IH_COMP_BZIP2
: comp
= "bzip2 compressed"; break;
177 default: comp
= "unknown compression"; break;
184 int relocate_image(struct image_handle
*handle
, void *load_address
)
186 image_header_t
*hdr
= &handle
->header
;
187 unsigned long len
= ntohl(hdr
->ih_size
);
188 unsigned long data
= (unsigned long)(handle
->data
);
190 #if defined CONFIG_CMD_BOOTM_ZLIB || defined CONFIG_CMD_BOOTM_BZLIB
191 uint unc_len
= CFG_BOOTM_LEN
;
194 switch (hdr
->ih_comp
) {
196 if(ntohl(hdr
->ih_load
) == data
) {
197 printf (" XIP ... ");
199 memmove ((void *) ntohl(hdr
->ih_load
), (uchar
*)data
, len
);
202 #ifdef CONFIG_CMD_BOOTM_ZLIB
204 printf (" Uncompressing ... ");
205 if (gunzip (load_address
, unc_len
,
206 (uchar
*)data
, &len
) != 0)
210 #ifdef CONFIG_CMD_BOOTM_BZLIB
212 printf (" Uncompressing ... ");
214 * If we've got less than 4 MB of malloc() space,
215 * use slower decompression algorithm which requires
216 * at most 2300 KB of memory.
218 if (BZ2_bzBuffToBuffDecompress (load_address
,
219 &unc_len
, (char *)data
, len
,
220 MALLOC_SIZE
< (4096 * 1024), 0)
226 printf ("Unimplemented compression type %d\n", hdr
->ih_comp
);
232 EXPORT_SYMBOL(relocate_image
);
234 struct image_handle
*map_image(const char *filename
, int verify
)
237 uint32_t checksum
, len
;
238 struct image_handle
*handle
;
239 image_header_t
*header
;
241 fd
= open(filename
, O_RDONLY
);
243 printf("could not open: %s\n", errno_str());
247 handle
= xzalloc(sizeof(struct image_handle
));
248 header
= &handle
->header
;
250 if (read(fd
, header
, sizeof(image_header_t
)) < 0) {
251 printf("could not read: %s\n", errno_str());
255 if (ntohl(header
->ih_magic
) != IH_MAGIC
) {
256 puts ("Bad Magic Number\n");
260 checksum
= ntohl(header
->ih_hcrc
);
263 if (crc32 (0, (uchar
*)header
, sizeof(image_header_t
)) != checksum
) {
264 puts ("Bad Header Checksum\n");
267 len
= ntohl(header
->ih_size
);
269 handle
->data
= memmap(fd
, PROT_READ
);
270 if (handle
->data
== (void *)-1) {
271 handle
->data
= xmalloc(len
);
272 handle
->flags
= IH_MALLOC
;
273 if (read(fd
, handle
->data
, len
) < 0) {
274 printf("could not read: %s\n", errno_str());
278 handle
->data
= (void *)((unsigned long)handle
->data
+ sizeof(image_header_t
));
282 puts (" Verifying Checksum ... ");
283 if (crc32 (0, handle
->data
, len
) != ntohl(header
->ih_dcrc
)) {
284 printf ("Bad Data CRC\n");
290 print_image_hdr(header
);
297 if (handle
->flags
& IH_MALLOC
)
302 EXPORT_SYMBOL(map_image
);
304 void unmap_image(struct image_handle
*handle
)
306 if (handle
->flags
& IH_MALLOC
)
310 EXPORT_SYMBOL(unmap_image
);
312 LIST_HEAD(handler_list
);
314 int register_image_handler(struct image_handler
*handler
)
316 list_add_tail(&handler
->list
, &handler_list
);
320 static int initrd_handler_parse_options(struct image_data
*data
, int opt
,
325 printf("use initrd %s\n", optarg
);
326 data
->initrd
= map_image(optarg
, data
->verify
);
335 static struct image_handler initrd_handler
= {
336 .cmdline_options
= "r:",
337 .cmdline_parse
= initrd_handler_parse_options
,
338 .help_string
= " -r <initrd> specify an initrd image",
341 static int initrd_register_image_handler(void)
343 return register_image_handler(&initrd_handler
);
346 late_initcall(initrd_register_image_handler
);
348 static int handler_parse_options(struct image_data
*data
, int opt
, char *optarg
)
350 struct image_handler
*handler
;
353 list_for_each_entry(handler
, &handler_list
, list
) {
354 if (!handler
->cmdline_parse
)
357 ret
= handler
->cmdline_parse(data
, opt
, optarg
);
367 static int do_bootm(struct command
*cmdtp
, int argc
, char *argv
[])
371 image_header_t
*os_header
;
372 struct image_handle
*os_handle
, *initrd_handle
= NULL
;
373 struct image_handler
*handler
;
374 struct image_data data
;
375 char options
[53]; /* worst case: whole alphabet with colons */
377 memset(&data
, 0, sizeof(struct image_data
));
380 /* Collect options from registered handlers */
381 strcpy(options
, "nh");
382 list_for_each_entry(handler
, &handler_list
, list
) {
383 if (handler
->cmdline_options
)
384 strcat(options
, handler
->cmdline_options
);
387 while((opt
= getopt(argc
, argv
, options
)) > 0) {
393 printf("bootm advanced options:\n");
395 list_for_each_entry(handler
, &handler_list
, list
) {
396 if (handler
->help_string
)
397 printf("%s\n", handler
->help_string
);
402 if (!handler_parse_options(&data
, opt
, optarg
))
410 return COMMAND_ERROR_USAGE
;
412 os_handle
= map_image(argv
[optind
], data
.verify
);
417 os_header
= &os_handle
->header
;
419 if (os_header
->ih_arch
!= IH_CPU
) {
420 printf ("Unsupported Architecture 0x%x\n", os_header
->ih_arch
);
425 * We have reached the point of no return: we are going to
426 * overwrite all exception vector code, so we cannot easily
427 * recover from any failures any more...
430 iflag
= disable_interrupts();
434 /* loop through the registered handlers */
435 list_for_each_entry(handler
, &handler_list
, list
) {
436 if (handler
->image_type
== os_header
->ih_os
) {
437 handler
->bootm(&data
);
438 printf("handler returned!\n");
443 printf("no image handler found for image type %d\n", os_header
->ih_os
);
447 unmap_image(os_handle
);
449 unmap_image(initrd_handle
);
453 static const __maybe_unused
char cmd_bootm_help
[] =
454 "Usage: bootm [OPTION] image\n"
455 "Boot application image\n"
456 " -n do not verify the images (speeds up boot process)\n"
457 " -h show advanced options\n";
460 BAREBOX_CMD_START(bootm
)
462 .usage
= "boot application image",
463 BAREBOX_CMD_HELP(cmd_bootm_help
)
466 #ifdef CONFIG_CMD_IMI
467 static int do_iminfo(struct command
*cmdtp
, int argc
, char *argv
[])
474 return image_info (load_addr
);
477 for (arg
=1; arg
<argc
; ++arg
) {
478 addr
= simple_strtoul(argv
[arg
], NULL
, 16);
479 if (image_info (addr
) != 0) rcode
= 1;
484 static int image_info (ulong addr
)
486 ulong data
, len
, checksum
;
487 image_header_t
*hdr
= &header
;
489 printf ("\n## Checking Image at %08lx ...\n", addr
);
491 /* Copy header so we can blank CRC field for re-calculation */
492 memmove (&header
, (char *)addr
, sizeof(image_header_t
));
494 if (ntohl(hdr
->ih_magic
) != IH_MAGIC
) {
495 puts (" Bad Magic Number\n");
499 data
= (ulong
)&header
;
500 len
= sizeof(image_header_t
);
502 checksum
= ntohl(hdr
->ih_hcrc
);
505 if (crc32 (0, (uchar
*)data
, len
) != checksum
) {
506 puts (" Bad Header Checksum\n");
510 /* for multi-file images we need the data part, too */
511 print_image_hdr ((image_header_t
*)addr
);
513 data
= addr
+ sizeof(image_header_t
);
514 len
= ntohl(hdr
->ih_size
);
516 puts (" Verifying Checksum ... ");
517 if (crc32 (0, (uchar
*)data
, len
) != ntohl(hdr
->ih_dcrc
)) {
518 puts (" Bad Data CRC\n");
526 iminfo
, 1, do_iminfo
,
527 "iminfo - print header information for application image\n",
529 " - print header information for application image starting at\n"
530 " address 'addr' in memory; this includes verification of the\n"
531 " image contents (magic number, header and payload checksums)\n"
534 #endif /* CONFIG_CMD_IMI */
537 print_image_hdr (image_header_t
*hdr
)
539 #if defined(CONFIG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
540 time_t timestamp
= (time_t)ntohl(hdr
->ih_time
);
544 printf (" Image Name: %.*s\n", IH_NMLEN
, hdr
->ih_name
);
545 #if defined(CONFIG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
546 to_tm (timestamp
, &tm
);
547 printf (" Created: %4d-%02d-%02d %2d:%02d:%02d UTC\n",
548 tm
.tm_year
, tm
.tm_mon
, tm
.tm_mday
,
549 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
550 #endif /* CONFIG_CMD_DATE, CONFIG_TIMESTAMP */
551 #ifdef CONFIG_CMD_BOOTM_SHOW_TYPE
552 printf (" Image Type: %s %s %s (%s)\n", image_arch(hdr
), image_os(hdr
),
553 image_type(hdr
), image_compression(hdr
));
555 printf (" Data Size: %d Bytes = %s\n"
556 " Load Address: %08x\n"
557 " Entry Point: %08x\n",
559 size_human_readable(ntohl(hdr
->ih_size
)),
563 if (hdr
->ih_type
== IH_TYPE_MULTI
) {
566 ulong
*len_ptr
= (ulong
*)((ulong
)hdr
+ sizeof(image_header_t
));
568 puts (" Contents:\n");
569 for (i
=0; (len
= ntohl(*len_ptr
)); ++i
, ++len_ptr
) {
570 printf (" Image %d: %8ld Bytes = %s", i
, len
,
571 size_human_readable (len
));
577 void bz_internal_error(int errcode
)
579 printf ("BZIP2 internal error %d\n", errcode
);
581 #endif /* CONFIG_BZLIB */
585 * @brief Boot support for Linux
589 * @page boot_preparation Preparing for Boot
591 * This chapter describes what's to be done to forward the control from
592 * barebox to Linux. This part describes the generic part, below you can find
593 * the architecture specific part.
595 * - @subpage arm_boot_preparation
596 * - @subpage ppc_boot_preparation
597 * - @subpage x86_boot_preparation
598 * - @subpage m68k_boot_preparation