implement ping using new network stack
[barebox-mini2440.git] / commands / bootm.c
blob11325dc075ad9126f5b08ce134db81ad39f3a84e
1 /*
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
6 * project.
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,
21 * MA 02111-1307 USA
25 * Boot support
27 #include <common.h>
28 #include <watchdog.h>
29 #include <driver.h>
30 #include <command.h>
31 #include <image.h>
32 #include <malloc.h>
33 #include <zlib.h>
34 #include <bzlib.h>
35 #include <environment.h>
36 #include <asm/byteorder.h>
37 #include <xfuncs.h>
38 #include <getopt.h>
39 #include <fcntl.h>
40 #include <fs.h>
41 #include <errno.h>
42 #include <boot.h>
43 #include <rtc.h>
44 #include <init.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' */
61 #ifndef CFG_BOOTM_LEN
62 #define CFG_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */
63 #endif
65 #ifdef CONFIG_SILENT_CONSOLE
66 static void
67 fixup_silent_linux ()
69 char buf[256], *start, *end;
70 char *cmdline = getenv ("bootargs");
72 /* Only fix cmdline when requested */
73 if (!(gd->flags & GD_FLG_SILENT))
74 return;
76 debug ("before silent fix-up: %s\n", cmdline);
77 if (cmdline) {
78 if ((start = strstr (cmdline, "console=")) != NULL) {
79 end = strchr (start, ' ');
80 strncpy (buf, cmdline, (start - cmdline + 8));
81 if (end)
82 strcpy (buf + (start - cmdline + 8), end);
83 else
84 buf[start - cmdline + 8] = '\0';
85 } else {
86 strcpy (buf, cmdline);
87 strcat (buf, " console=");
89 } else {
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)
101 char *os;
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;
111 #ifdef CONFIG_ARTOS
112 case IH_OS_ARTOS: os = "ARTOS"; break;
113 #endif
114 #ifdef CONFIG_LYNXKDI
115 case IH_OS_LYNXOS: os = "LynxOS"; break;
116 #endif
117 default: os = "Unknown OS"; break;
120 return os;
123 static const char *image_arch(image_header_t *hdr)
125 char *arch;
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;
148 return arch;
151 static const char *image_type(image_header_t *hdr)
153 char *type;
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;
166 return type;
169 static const char *image_compression(image_header_t *hdr)
171 char *comp;
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;
180 return comp;
182 #endif
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;
192 #endif
194 switch (hdr->ih_comp) {
195 case IH_COMP_NONE:
196 if(ntohl(hdr->ih_load) == data) {
197 printf (" XIP ... ");
198 } else {
199 memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);
201 break;
202 #ifdef CONFIG_CMD_BOOTM_ZLIB
203 case IH_COMP_GZIP:
204 printf (" Uncompressing ... ");
205 if (gunzip (load_address, unc_len,
206 (uchar *)data, &len) != 0)
207 return -1;
208 break;
209 #endif
210 #ifdef CONFIG_CMD_BOOTM_BZLIB
211 case IH_COMP_BZIP2:
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)
221 != BZ_OK)
222 return -1;
223 break;
224 #endif
225 default:
226 printf ("Unimplemented compression type %d\n", hdr->ih_comp);
227 return -1;
230 return 0;
232 EXPORT_SYMBOL(relocate_image);
234 struct image_handle *map_image(const char *filename, int verify)
236 int fd;
237 uint32_t checksum, len;
238 struct image_handle *handle;
239 image_header_t *header;
241 fd = open(filename, O_RDONLY);
242 if (fd < 0) {
243 printf("could not open: %s\n", errno_str());
244 return NULL;
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());
252 goto err_out;
255 if (ntohl(header->ih_magic) != IH_MAGIC) {
256 puts ("Bad Magic Number\n");
257 goto err_out;
260 checksum = ntohl(header->ih_hcrc);
261 header->ih_hcrc = 0;
263 if (crc32 (0, (uchar *)header, sizeof(image_header_t)) != checksum) {
264 puts ("Bad Header Checksum\n");
265 goto err_out;
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());
275 goto err_out;
277 } else {
278 handle->data = (void *)((unsigned long)handle->data + sizeof(image_header_t));
281 if (verify) {
282 puts (" Verifying Checksum ... ");
283 if (crc32 (0, handle->data, len) != ntohl(header->ih_dcrc)) {
284 printf ("Bad Data CRC\n");
285 goto err_out;
287 puts ("OK\n");
290 print_image_hdr(header);
292 close(fd);
294 return handle;
295 err_out:
296 close(fd);
297 if (handle->flags & IH_MALLOC)
298 free(handle->data);
299 free(handle);
300 return NULL;
302 EXPORT_SYMBOL(map_image);
304 void unmap_image(struct image_handle *handle)
306 if (handle->flags & IH_MALLOC)
307 free(handle->data);
308 free(handle);
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);
317 return 0;
320 static int initrd_handler_parse_options(struct image_data *data, int opt,
321 char *optarg)
323 switch(opt) {
324 case 'r':
325 printf("use initrd %s\n", optarg);
326 data->initrd = map_image(optarg, data->verify);
327 if (!data->initrd)
328 return -1;
329 return 0;
330 default:
331 return 1;
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;
351 int ret;
353 list_for_each_entry(handler, &handler_list, list) {
354 if (!handler->cmdline_parse)
355 continue;
357 ret = handler->cmdline_parse(data, opt, optarg);
358 if (ret > 0)
359 continue;
361 return ret;
364 return -1;
367 static int do_bootm(struct command *cmdtp, int argc, char *argv[])
369 ulong iflag;
370 int opt;
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));
378 data.verify = 1;
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) {
388 switch(opt) {
389 case 'n':
390 data.verify = 0;
391 break;
392 case 'h':
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);
400 return 0;
401 default:
402 if (!handler_parse_options(&data, opt, optarg))
403 continue;
405 return 1;
409 if (optind == argc)
410 return COMMAND_ERROR_USAGE;
412 os_handle = map_image(argv[optind], data.verify);
413 if (!os_handle)
414 return 1;
415 data.os = os_handle;
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);
421 goto err_out;
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();
432 puts ("OK\n");
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");
439 goto err_out;
443 printf("no image handler found for image type %d\n", os_header->ih_os);
445 err_out:
446 if (os_handle)
447 unmap_image(os_handle);
448 if (initrd_handle)
449 unmap_image(initrd_handle);
450 return 1;
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)
461 .cmd = do_bootm,
462 .usage = "boot application image",
463 BAREBOX_CMD_HELP(cmd_bootm_help)
464 BAREBOX_CMD_END
466 #ifdef CONFIG_CMD_IMI
467 static int do_iminfo(struct command *cmdtp, int argc, char *argv[])
469 int arg;
470 ulong addr;
471 int rcode=0;
473 if (argc < 2) {
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;
481 return rcode;
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");
496 return 1;
499 data = (ulong)&header;
500 len = sizeof(image_header_t);
502 checksum = ntohl(hdr->ih_hcrc);
503 hdr->ih_hcrc = 0;
505 if (crc32 (0, (uchar *)data, len) != checksum) {
506 puts (" Bad Header Checksum\n");
507 return 1;
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");
519 return 1;
521 puts ("OK\n");
522 return 0;
525 BAREBOX_CMD(
526 iminfo, 1, do_iminfo,
527 "iminfo - print header information for application image\n",
528 "addr [addr ...]\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 */
536 void
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);
541 struct rtc_time tm;
542 #endif
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));
554 #endif
555 printf (" Data Size: %d Bytes = %s\n"
556 " Load Address: %08x\n"
557 " Entry Point: %08x\n",
558 ntohl(hdr->ih_size),
559 size_human_readable(ntohl(hdr->ih_size)),
560 ntohl(hdr->ih_load),
561 ntohl(hdr->ih_ep));
563 if (hdr->ih_type == IH_TYPE_MULTI) {
564 int i;
565 ulong len;
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));
576 #ifdef CONFIG_BZLIB
577 void bz_internal_error(int errcode)
579 printf ("BZIP2 internal error %d\n", errcode);
581 #endif /* CONFIG_BZLIB */
584 * @file
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