]>
Commit | Line | Data |
---|---|---|
47d1a6e1 | 1 | /* |
15940c9a | 2 | * (C) Copyright 2000-2006 |
47d1a6e1 WD |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
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. | |
12 | * | |
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. | |
17 | * | |
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 | |
22 | */ | |
23 | ||
b97a2a0a | 24 | |
47d1a6e1 WD |
25 | /* |
26 | * Boot support | |
27 | */ | |
28 | #include <common.h> | |
29 | #include <watchdog.h> | |
30 | #include <command.h> | |
47d1a6e1 WD |
31 | #include <image.h> |
32 | #include <malloc.h> | |
33 | #include <zlib.h> | |
c29fdfc1 | 34 | #include <bzlib.h> |
7f70e853 | 35 | #include <environment.h> |
4ed6552f | 36 | #include <lmb.h> |
47d1a6e1 | 37 | #include <asm/byteorder.h> |
8bde7f77 | 38 | |
ebb86c4e | 39 | #if defined(CONFIG_CMD_USB) |
3d71c81a MK |
40 | #include <usb.h> |
41 | #endif | |
42 | ||
6d0f6bcf | 43 | #ifdef CONFIG_SYS_HUSH_PARSER |
47d1a6e1 WD |
44 | #include <hush.h> |
45 | #endif | |
46 | ||
54f9c866 KG |
47 | #if defined(CONFIG_OF_LIBFDT) |
48 | #include <fdt.h> | |
49 | #include <libfdt.h> | |
50 | #include <fdt_support.h> | |
51 | #endif | |
52 | ||
fc9c1727 LCM |
53 | #ifdef CONFIG_LZMA |
54 | #define _7ZIP_BYTE_DEFINED /* Byte already defined by zlib */ | |
55 | #include <lzma/LzmaTypes.h> | |
56 | #include <lzma/LzmaDecode.h> | |
57 | #include <lzma/LzmaTools.h> | |
58 | #endif /* CONFIG_LZMA */ | |
59 | ||
1ee1180b | 60 | DECLARE_GLOBAL_DATA_PTR; |
228f29ac | 61 | |
1ee1180b | 62 | extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp); |
6d0f6bcf JCPV |
63 | #ifndef CONFIG_SYS_BOOTM_LEN |
64 | #define CONFIG_SYS_BOOTM_LEN 0x800000 /* use 8MByte as default max gunzip size */ | |
2abbe075 WD |
65 | #endif |
66 | ||
321359f2 MB |
67 | #ifdef CONFIG_BZIP2 |
68 | extern void bz_internal_error(int); | |
47d1a6e1 WD |
69 | #endif |
70 | ||
baa26db4 | 71 | #if defined(CONFIG_CMD_IMI) |
47d1a6e1 WD |
72 | static int image_info (unsigned long addr); |
73 | #endif | |
27b207fd | 74 | |
baa26db4 | 75 | #if defined(CONFIG_CMD_IMLS) |
27b207fd | 76 | #include <flash.h> |
e6f2e902 | 77 | extern flash_info_t flash_info[]; /* info for FLASH chips */ |
27b207fd WD |
78 | static int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); |
79 | #endif | |
80 | ||
1ee1180b MB |
81 | #ifdef CONFIG_SILENT_CONSOLE |
82 | static void fixup_silent_linux (void); | |
83 | #endif | |
47d1a6e1 | 84 | |
6986a385 MB |
85 | static image_header_t *image_get_kernel (ulong img_addr, int verify); |
86 | #if defined(CONFIG_FIT) | |
87 | static int fit_check_kernel (const void *fit, int os_noffset, int verify); | |
2262cfee WD |
88 | #endif |
89 | ||
9a4daad0 | 90 | static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag,int argc, char *argv[], |
8a5ea3e6 | 91 | bootm_headers_t *images, ulong *os_data, ulong *os_len); |
1ee1180b | 92 | extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); |
47d1a6e1 WD |
93 | |
94 | /* | |
95 | * Continue booting an OS image; caller already has: | |
96 | * - copied image header to global variable `header' | |
97 | * - checked header magic number, checksums (both header & image), | |
98 | * - verified image architecture (PPC) and type (KERNEL or MULTI), | |
99 | * - loaded (first part of) image to header load address, | |
100 | * - disabled interrupts. | |
101 | */ | |
40d7e99d | 102 | typedef int boot_os_fn (int flag, int argc, char *argv[], |
8a5ea3e6 | 103 | bootm_headers_t *images); /* pointers to os/initrd/fdt */ |
1ee1180b MB |
104 | |
105 | extern boot_os_fn do_bootm_linux; | |
106 | static boot_os_fn do_bootm_netbsd; | |
f13e7b2e | 107 | #if defined(CONFIG_LYNXKDI) |
1ee1180b MB |
108 | static boot_os_fn do_bootm_lynxkdi; |
109 | extern void lynxkdi_boot (image_header_t *); | |
47d1a6e1 | 110 | #endif |
1ee1180b | 111 | static boot_os_fn do_bootm_rtems; |
baa26db4 | 112 | #if defined(CONFIG_CMD_ELF) |
1ee1180b MB |
113 | static boot_os_fn do_bootm_vxworks; |
114 | static boot_os_fn do_bootm_qnxelf; | |
115 | int do_bootvx (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
116 | int do_bootelf (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
90253178 | 117 | #endif |
f5ed9e39 PT |
118 | #if defined(CONFIG_INTEGRITY) |
119 | static boot_os_fn do_bootm_integrity; | |
120 | #endif | |
47d1a6e1 | 121 | |
6d0f6bcf | 122 | ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ |
d5934ad7 | 123 | static bootm_headers_t images; /* pointers to os/initrd/fdt images */ |
15940c9a | 124 | |
e822d7fc KG |
125 | void __board_lmb_reserve(struct lmb *lmb) |
126 | { | |
127 | /* please define platform specific board_lmb_reserve() */ | |
128 | } | |
129 | void board_lmb_reserve(struct lmb *lmb) __attribute__((weak, alias("__board_lmb_reserve"))); | |
47d1a6e1 | 130 | |
c4f9419c KG |
131 | #if defined(__ARM__) |
132 | #define IH_INITRD_ARCH IH_ARCH_ARM | |
133 | #elif defined(__avr32__) | |
134 | #define IH_INITRD_ARCH IH_ARCH_AVR32 | |
135 | #elif defined(__bfin__) | |
136 | #define IH_INITRD_ARCH IH_ARCH_BLACKFIN | |
137 | #elif defined(__I386__) | |
138 | #define IH_INITRD_ARCH IH_ARCH_I386 | |
139 | #elif defined(__M68K__) | |
140 | #define IH_INITRD_ARCH IH_ARCH_M68K | |
141 | #elif defined(__microblaze__) | |
142 | #define IH_INITRD_ARCH IH_ARCH_MICROBLAZE | |
143 | #elif defined(__mips__) | |
144 | #define IH_INITRD_ARCH IH_ARCH_MIPS | |
145 | #elif defined(__nios__) | |
146 | #define IH_INITRD_ARCH IH_ARCH_NIOS | |
147 | #elif defined(__nios2__) | |
148 | #define IH_INITRD_ARCH IH_ARCH_NIOS2 | |
149 | #elif defined(__PPC__) | |
150 | #define IH_INITRD_ARCH IH_ARCH_PPC | |
151 | #elif defined(__sh__) | |
152 | #define IH_INITRD_ARCH IH_ARCH_SH | |
153 | #elif defined(__sparc__) | |
154 | #define IH_INITRD_ARCH IH_ARCH_SPARC | |
155 | #else | |
156 | # error Unknown CPU type | |
157 | #endif | |
47d1a6e1 | 158 | |
396f635b | 159 | static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
47d1a6e1 | 160 | { |
391fd93a BB |
161 | ulong mem_start; |
162 | phys_size_t mem_size; | |
396f635b | 163 | void *os_hdr; |
c4f9419c | 164 | int ret; |
47d1a6e1 | 165 | |
d5934ad7 | 166 | memset ((void *)&images, 0, sizeof (images)); |
edbed247 | 167 | images.verify = getenv_yesno ("verify"); |
47d1a6e1 | 168 | |
e906cfae | 169 | lmb_init(&images.lmb); |
47d1a6e1 | 170 | |
d3f2fa0d KG |
171 | mem_start = getenv_bootm_low(); |
172 | mem_size = getenv_bootm_size(); | |
47d1a6e1 | 173 | |
e906cfae | 174 | lmb_add(&images.lmb, (phys_addr_t)mem_start, mem_size); |
47d1a6e1 | 175 | |
e906cfae | 176 | board_lmb_reserve(&images.lmb); |
47d1a6e1 | 177 | |
5cf746c3 | 178 | /* get kernel image header, start address and length */ |
9a4daad0 | 179 | os_hdr = boot_get_kernel (cmdtp, flag, argc, argv, |
396f635b KG |
180 | &images, &images.os.image_start, &images.os.image_len); |
181 | if (images.os.image_len == 0) { | |
6986a385 | 182 | puts ("ERROR: can't get kernel image!\n"); |
47d1a6e1 | 183 | return 1; |
bccae903 | 184 | } |
bccae903 | 185 | |
d5934ad7 | 186 | /* get image parameters */ |
9a4daad0 | 187 | switch (genimg_get_format (os_hdr)) { |
d5934ad7 | 188 | case IMAGE_FORMAT_LEGACY: |
396f635b KG |
189 | images.os.type = image_get_type (os_hdr); |
190 | images.os.comp = image_get_comp (os_hdr); | |
191 | images.os.os = image_get_os (os_hdr); | |
bccae903 | 192 | |
396f635b KG |
193 | images.os.end = image_get_image_end (os_hdr); |
194 | images.os.load = image_get_load (os_hdr); | |
d5934ad7 MB |
195 | break; |
196 | #if defined(CONFIG_FIT) | |
197 | case IMAGE_FORMAT_FIT: | |
3dfe1101 | 198 | if (fit_image_get_type (images.fit_hdr_os, |
396f635b | 199 | images.fit_noffset_os, &images.os.type)) { |
6986a385 | 200 | puts ("Can't get image type!\n"); |
1372cce2 | 201 | show_boot_progress (-109); |
6986a385 MB |
202 | return 1; |
203 | } | |
47d1a6e1 | 204 | |
3dfe1101 | 205 | if (fit_image_get_comp (images.fit_hdr_os, |
396f635b | 206 | images.fit_noffset_os, &images.os.comp)) { |
6986a385 | 207 | puts ("Can't get image compression!\n"); |
1372cce2 | 208 | show_boot_progress (-110); |
6986a385 MB |
209 | return 1; |
210 | } | |
47d1a6e1 | 211 | |
3dfe1101 | 212 | if (fit_image_get_os (images.fit_hdr_os, |
396f635b | 213 | images.fit_noffset_os, &images.os.os)) { |
6986a385 | 214 | puts ("Can't get image OS!\n"); |
1372cce2 | 215 | show_boot_progress (-111); |
47d1a6e1 WD |
216 | return 1; |
217 | } | |
47d1a6e1 | 218 | |
396f635b | 219 | images.os.end = fit_get_end (images.fit_hdr_os); |
6986a385 | 220 | |
3dfe1101 | 221 | if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os, |
396f635b | 222 | &images.os.load)) { |
6986a385 | 223 | puts ("Can't get image load address!\n"); |
1372cce2 | 224 | show_boot_progress (-112); |
6986a385 | 225 | return 1; |
b13fb01a WD |
226 | } |
227 | break; | |
d5934ad7 MB |
228 | #endif |
229 | default: | |
230 | puts ("ERROR: unknown image format type!\n"); | |
47d1a6e1 WD |
231 | return 1; |
232 | } | |
d5934ad7 | 233 | |
c160a954 KG |
234 | /* find kernel entry point */ |
235 | if (images.legacy_hdr_valid) { | |
236 | images.ep = image_get_ep (&images.legacy_hdr_os_copy); | |
237 | #if defined(CONFIG_FIT) | |
238 | } else if (images.fit_uname_os) { | |
239 | ret = fit_image_get_entry (images.fit_hdr_os, | |
240 | images.fit_noffset_os, &images.ep); | |
241 | if (ret) { | |
242 | puts ("Can't get entry point property!\n"); | |
243 | return 1; | |
244 | } | |
245 | #endif | |
246 | } else { | |
247 | puts ("Could not find kernel entry point!\n"); | |
248 | return 1; | |
249 | } | |
250 | ||
396f635b | 251 | if (images.os.os == IH_OS_LINUX) { |
c4f9419c KG |
252 | /* find ramdisk */ |
253 | ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH, | |
254 | &images.rd_start, &images.rd_end); | |
255 | if (ret) { | |
ea86b9e6 | 256 | puts ("Ramdisk image is corrupt or invalid\n"); |
c4f9419c KG |
257 | return 1; |
258 | } | |
06a09918 KG |
259 | |
260 | #if defined(CONFIG_OF_LIBFDT) | |
1d9af0be | 261 | #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) |
06a09918 KG |
262 | /* find flattened device tree */ |
263 | ret = boot_get_fdt (flag, argc, argv, &images, | |
264 | &images.ft_addr, &images.ft_len); | |
265 | if (ret) { | |
266 | puts ("Could not find a valid device tree\n"); | |
267 | return 1; | |
268 | } | |
54f9c866 KG |
269 | |
270 | set_working_fdt_addr(images.ft_addr); | |
1d9af0be | 271 | #endif |
06a09918 | 272 | #endif |
c4f9419c KG |
273 | } |
274 | ||
396f635b KG |
275 | images.os.start = (ulong)os_hdr; |
276 | images.valid = 1; | |
47d1a6e1 | 277 | |
396f635b KG |
278 | return 0; |
279 | } | |
3d71c81a | 280 | |
396f635b KG |
281 | #define BOOTM_ERR_RESET -1 |
282 | #define BOOTM_ERR_OVERLAP -2 | |
283 | #define BOOTM_ERR_UNIMPLEMENTED -3 | |
284 | static int bootm_load_os(image_info_t os, ulong *load_end, int boot_progress) | |
285 | { | |
286 | uint8_t comp = os.comp; | |
287 | ulong load = os.load; | |
288 | ulong blob_start = os.start; | |
289 | ulong blob_end = os.end; | |
290 | ulong image_start = os.image_start; | |
291 | ulong image_len = os.image_len; | |
6d0f6bcf | 292 | uint unc_len = CONFIG_SYS_BOOTM_LEN; |
3d71c81a | 293 | |
396f635b | 294 | const char *type_name = genimg_get_type_name (os.type); |
c7de829c | 295 | |
d5934ad7 | 296 | switch (comp) { |
47d1a6e1 | 297 | case IH_COMP_NONE: |
396f635b | 298 | if (load == blob_start) { |
42b73e8e | 299 | printf (" XIP %s ... ", type_name); |
47d1a6e1 | 300 | } else { |
42b73e8e | 301 | printf (" Loading %s ... ", type_name); |
47d1a6e1 | 302 | |
396f635b KG |
303 | memmove_wd ((void *)load, |
304 | (void *)image_start, image_len, CHUNKSZ); | |
47d1a6e1 | 305 | } |
396f635b | 306 | *load_end = load + image_len; |
2e752be3 | 307 | puts("OK\n"); |
47d1a6e1 WD |
308 | break; |
309 | case IH_COMP_GZIP: | |
42b73e8e | 310 | printf (" Uncompressing %s ... ", type_name); |
396f635b KG |
311 | if (gunzip ((void *)load, unc_len, |
312 | (uchar *)image_start, &image_len) != 0) { | |
2682ce8a MB |
313 | puts ("GUNZIP: uncompress or overwrite error " |
314 | "- must RESET board to recover\n"); | |
396f635b KG |
315 | if (boot_progress) |
316 | show_boot_progress (-6); | |
317 | return BOOTM_ERR_RESET; | |
47d1a6e1 | 318 | } |
7582438c | 319 | |
396f635b | 320 | *load_end = load + image_len; |
47d1a6e1 | 321 | break; |
c29fdfc1 WD |
322 | #ifdef CONFIG_BZIP2 |
323 | case IH_COMP_BZIP2: | |
42b73e8e | 324 | printf (" Uncompressing %s ... ", type_name); |
5653fc33 WD |
325 | /* |
326 | * If we've got less than 4 MB of malloc() space, | |
327 | * use slower decompression algorithm which requires | |
328 | * at most 2300 KB of memory. | |
329 | */ | |
396f635b KG |
330 | int i = BZ2_bzBuffToBuffDecompress ((char*)load, |
331 | &unc_len, (char *)image_start, image_len, | |
6d0f6bcf | 332 | CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); |
c29fdfc1 | 333 | if (i != BZ_OK) { |
2682ce8a MB |
334 | printf ("BUNZIP2: uncompress or overwrite error %d " |
335 | "- must RESET board to recover\n", i); | |
396f635b KG |
336 | if (boot_progress) |
337 | show_boot_progress (-6); | |
338 | return BOOTM_ERR_RESET; | |
c29fdfc1 | 339 | } |
7582438c | 340 | |
396f635b | 341 | *load_end = load + unc_len; |
c29fdfc1 WD |
342 | break; |
343 | #endif /* CONFIG_BZIP2 */ | |
fc9c1727 LCM |
344 | #ifdef CONFIG_LZMA |
345 | case IH_COMP_LZMA: | |
346 | printf (" Uncompressing %s ... ", type_name); | |
347 | ||
348 | int ret = lzmaBuffToBuffDecompress( | |
349 | (unsigned char *)load, &unc_len, | |
d977a573 | 350 | (unsigned char *)image_start, image_len); |
fc9c1727 LCM |
351 | if (ret != LZMA_RESULT_OK) { |
352 | printf ("LZMA: uncompress or overwrite error %d " | |
353 | "- must RESET board to recover\n", ret); | |
354 | show_boot_progress (-6); | |
355 | return BOOTM_ERR_RESET; | |
356 | } | |
357 | *load_end = load + unc_len; | |
358 | break; | |
359 | #endif /* CONFIG_LZMA */ | |
47d1a6e1 | 360 | default: |
d5934ad7 | 361 | printf ("Unimplemented compression type %d\n", comp); |
396f635b | 362 | return BOOTM_ERR_UNIMPLEMENTED; |
47d1a6e1 | 363 | } |
4b9206ed | 364 | puts ("OK\n"); |
54b4ab3c | 365 | debug (" kernel loaded at 0x%08lx, end = 0x%08lx\n", load, *load_end); |
396f635b KG |
366 | if (boot_progress) |
367 | show_boot_progress (7); | |
47d1a6e1 | 368 | |
396f635b KG |
369 | if ((load < blob_end) && (*load_end > blob_start)) { |
370 | debug ("images.os.start = 0x%lX, images.os.end = 0x%lx\n", blob_start, blob_end); | |
54b4ab3c | 371 | debug ("images.os.load = 0x%lx, load_end = 0x%lx\n", load, *load_end); |
47d1a6e1 | 372 | |
396f635b KG |
373 | return BOOTM_ERR_OVERLAP; |
374 | } | |
375 | ||
376 | return 0; | |
377 | } | |
378 | ||
379 | /*******************************************************************/ | |
380 | /* bootm - boot application image from image in memory */ | |
381 | /*******************************************************************/ | |
382 | int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
383 | { | |
384 | ||
385 | ulong iflag; | |
386 | ulong load_end = 0; | |
387 | int ret; | |
388 | ||
8e02494e AG |
389 | if (bootm_start(cmdtp, flag, argc, argv)) |
390 | return 1; | |
396f635b KG |
391 | |
392 | /* | |
393 | * We have reached the point of no return: we are going to | |
394 | * overwrite all exception vector code, so we cannot easily | |
395 | * recover from any failures any more... | |
396 | */ | |
397 | iflag = disable_interrupts(); | |
398 | ||
399 | #if defined(CONFIG_CMD_USB) | |
400 | /* | |
401 | * turn off USB to prevent the host controller from writing to the | |
402 | * SDRAM while Linux is booting. This could happen (at least for OHCI | |
403 | * controller), because the HCCA (Host Controller Communication Area) | |
404 | * lies within the SDRAM and the host controller writes continously to | |
405 | * this area (as busmaster!). The HccaFrameNumber is for example | |
406 | * updated every 1 ms within the HCCA structure in SDRAM! For more | |
407 | * details see the OpenHCI specification. | |
408 | */ | |
409 | usb_stop(); | |
410 | #endif | |
411 | ||
412 | #ifdef CONFIG_AMIGAONEG3SE | |
413 | /* | |
414 | * We've possible left the caches enabled during | |
415 | * bios emulation, so turn them off again | |
416 | */ | |
417 | icache_disable(); | |
418 | dcache_disable(); | |
419 | #endif | |
420 | ||
421 | ret = bootm_load_os(images.os, &load_end, 1); | |
422 | ||
423 | if (ret < 0) { | |
424 | if (ret == BOOTM_ERR_RESET) | |
cb1c4896 | 425 | do_reset (cmdtp, flag, argc, argv); |
396f635b KG |
426 | if (ret == BOOTM_ERR_OVERLAP) { |
427 | if (images.legacy_hdr_valid) { | |
428 | if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI) | |
429 | puts ("WARNING: legacy format multi component " | |
430 | "image overwritten\n"); | |
431 | } else { | |
432 | puts ("ERROR: new format image overwritten - " | |
433 | "must RESET the board to recover\n"); | |
434 | show_boot_progress (-113); | |
435 | do_reset (cmdtp, flag, argc, argv); | |
436 | } | |
437 | } | |
438 | if (ret == BOOTM_ERR_UNIMPLEMENTED) { | |
439 | if (iflag) | |
440 | enable_interrupts(); | |
441 | show_boot_progress (-7); | |
442 | return 1; | |
cb1c4896 | 443 | } |
47d1a6e1 | 444 | } |
7582438c | 445 | |
396f635b | 446 | lmb_reserve(&images.lmb, images.os.load, (load_end - images.os.load)); |
47d1a6e1 | 447 | |
396f635b | 448 | show_boot_progress (8); |
4ed6552f | 449 | |
396f635b | 450 | switch (images.os.os) { |
47d1a6e1 WD |
451 | default: /* handled by (original) Linux case */ |
452 | case IH_OS_LINUX: | |
f72da340 WD |
453 | #ifdef CONFIG_SILENT_CONSOLE |
454 | fixup_silent_linux(); | |
455 | #endif | |
40d7e99d | 456 | do_bootm_linux (0, argc, argv, &images); |
47d1a6e1 | 457 | break; |
1ee1180b | 458 | |
47d1a6e1 | 459 | case IH_OS_NETBSD: |
40d7e99d | 460 | do_bootm_netbsd (0, argc, argv, &images); |
47d1a6e1 | 461 | break; |
8bde7f77 | 462 | |
1f4bb37d WD |
463 | #ifdef CONFIG_LYNXKDI |
464 | case IH_OS_LYNXOS: | |
40d7e99d | 465 | do_bootm_lynxkdi (0, argc, argv, &images); |
1f4bb37d WD |
466 | break; |
467 | #endif | |
468 | ||
d791b1dc | 469 | case IH_OS_RTEMS: |
40d7e99d | 470 | do_bootm_rtems (0, argc, argv, &images); |
d791b1dc | 471 | break; |
8bde7f77 | 472 | |
baa26db4 | 473 | #if defined(CONFIG_CMD_ELF) |
47d1a6e1 | 474 | case IH_OS_VXWORKS: |
40d7e99d | 475 | do_bootm_vxworks (0, argc, argv, &images); |
47d1a6e1 | 476 | break; |
f13e7b2e | 477 | |
47d1a6e1 | 478 | case IH_OS_QNX: |
40d7e99d | 479 | do_bootm_qnxelf (0, argc, argv, &images); |
47d1a6e1 | 480 | break; |
90253178 | 481 | #endif |
1ee1180b | 482 | |
f5ed9e39 PT |
483 | #ifdef CONFIG_INTEGRITY |
484 | case IH_OS_INTEGRITY: | |
485 | do_bootm_integrity (0, argc, argv, &images); | |
486 | break; | |
487 | #endif | |
47d1a6e1 WD |
488 | } |
489 | ||
fad63407 | 490 | show_boot_progress (-9); |
47d1a6e1 | 491 | #ifdef DEBUG |
4b9206ed | 492 | puts ("\n## Control returned to monitor - resetting...\n"); |
47d1a6e1 | 493 | #endif |
40d7e99d | 494 | do_reset (cmdtp, flag, argc, argv); |
a44a269a | 495 | |
47d1a6e1 WD |
496 | return 1; |
497 | } | |
498 | ||
1efd4360 | 499 | /** |
9a4daad0 MB |
500 | * image_get_kernel - verify legacy format kernel image |
501 | * @img_addr: in RAM address of the legacy format image to be verified | |
502 | * @verify: data CRC verification flag | |
1efd4360 | 503 | * |
9a4daad0 MB |
504 | * image_get_kernel() verifies legacy image integrity and returns pointer to |
505 | * legacy image header if image verification was completed successfully. | |
1efd4360 MB |
506 | * |
507 | * returns: | |
9a4daad0 MB |
508 | * pointer to a legacy image header if valid image was found |
509 | * otherwise return NULL | |
1efd4360 MB |
510 | */ |
511 | static image_header_t *image_get_kernel (ulong img_addr, int verify) | |
f72da340 | 512 | { |
1efd4360 | 513 | image_header_t *hdr = (image_header_t *)img_addr; |
f72da340 | 514 | |
1efd4360 MB |
515 | if (!image_check_magic(hdr)) { |
516 | puts ("Bad Magic Number\n"); | |
517 | show_boot_progress (-1); | |
518 | return NULL; | |
519 | } | |
520 | show_boot_progress (2); | |
f72da340 | 521 | |
1efd4360 MB |
522 | if (!image_check_hcrc (hdr)) { |
523 | puts ("Bad Header Checksum\n"); | |
524 | show_boot_progress (-2); | |
525 | return NULL; | |
526 | } | |
527 | ||
528 | show_boot_progress (3); | |
529 | image_print_contents (hdr); | |
530 | ||
531 | if (verify) { | |
532 | puts (" Verifying Checksum ... "); | |
533 | if (!image_check_dcrc (hdr)) { | |
534 | printf ("Bad Data CRC\n"); | |
535 | show_boot_progress (-3); | |
536 | return NULL; | |
f72da340 | 537 | } |
1efd4360 | 538 | puts ("OK\n"); |
f72da340 | 539 | } |
1efd4360 | 540 | show_boot_progress (4); |
f72da340 | 541 | |
1efd4360 MB |
542 | if (!image_check_target_arch (hdr)) { |
543 | printf ("Unsupported Architecture 0x%x\n", image_get_arch (hdr)); | |
544 | show_boot_progress (-4); | |
545 | return NULL; | |
546 | } | |
547 | return hdr; | |
f72da340 | 548 | } |
f72da340 | 549 | |
6986a385 MB |
550 | /** |
551 | * fit_check_kernel - verify FIT format kernel subimage | |
552 | * @fit_hdr: pointer to the FIT image header | |
553 | * os_noffset: kernel subimage node offset within FIT image | |
554 | * @verify: data CRC verification flag | |
555 | * | |
556 | * fit_check_kernel() verifies integrity of the kernel subimage and from | |
557 | * specified FIT image. | |
558 | * | |
559 | * returns: | |
560 | * 1, on success | |
561 | * 0, on failure | |
562 | */ | |
563 | #if defined (CONFIG_FIT) | |
564 | static int fit_check_kernel (const void *fit, int os_noffset, int verify) | |
47d1a6e1 | 565 | { |
6986a385 | 566 | fit_image_print (fit, os_noffset, " "); |
47d1a6e1 | 567 | |
6986a385 MB |
568 | if (verify) { |
569 | puts (" Verifying Hash Integrity ... "); | |
570 | if (!fit_image_check_hashes (fit, os_noffset)) { | |
571 | puts ("Bad Data Hash\n"); | |
1372cce2 | 572 | show_boot_progress (-104); |
6986a385 MB |
573 | return 0; |
574 | } | |
575 | puts ("OK\n"); | |
47d1a6e1 | 576 | } |
1372cce2 | 577 | show_boot_progress (105); |
47d1a6e1 | 578 | |
6986a385 MB |
579 | if (!fit_image_check_target_arch (fit, os_noffset)) { |
580 | puts ("Unsupported Architecture\n"); | |
1372cce2 | 581 | show_boot_progress (-105); |
6986a385 MB |
582 | return 0; |
583 | } | |
56f94be3 | 584 | |
1372cce2 | 585 | show_boot_progress (106); |
6986a385 MB |
586 | if (!fit_image_check_type (fit, os_noffset, IH_TYPE_KERNEL)) { |
587 | puts ("Not a kernel image\n"); | |
1372cce2 | 588 | show_boot_progress (-106); |
6986a385 MB |
589 | return 0; |
590 | } | |
47d1a6e1 | 591 | |
1372cce2 | 592 | show_boot_progress (107); |
6986a385 MB |
593 | return 1; |
594 | } | |
595 | #endif /* CONFIG_FIT */ | |
47d1a6e1 | 596 | |
5cf746c3 | 597 | /** |
9a4daad0 | 598 | * boot_get_kernel - find kernel image |
5cf746c3 MB |
599 | * @os_data: pointer to a ulong variable, will hold os data start address |
600 | * @os_len: pointer to a ulong variable, will hold os data length | |
601 | * | |
9a4daad0 | 602 | * boot_get_kernel() tries to find a kernel image, verifies its integrity |
5cf746c3 MB |
603 | * and locates kernel data. |
604 | * | |
605 | * returns: | |
606 | * pointer to image header if valid image was found, plus kernel start | |
607 | * address and length, otherwise NULL | |
608 | */ | |
9a4daad0 | 609 | static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], |
8a5ea3e6 | 610 | bootm_headers_t *images, ulong *os_data, ulong *os_len) |
5cf746c3 MB |
611 | { |
612 | image_header_t *hdr; | |
613 | ulong img_addr; | |
d5934ad7 MB |
614 | #if defined(CONFIG_FIT) |
615 | void *fit_hdr; | |
616 | const char *fit_uname_config = NULL; | |
617 | const char *fit_uname_kernel = NULL; | |
6986a385 MB |
618 | const void *data; |
619 | size_t len; | |
f773bea8 | 620 | int cfg_noffset; |
6986a385 | 621 | int os_noffset; |
d5934ad7 | 622 | #endif |
56f94be3 | 623 | |
d5934ad7 | 624 | /* find out kernel image address */ |
5cf746c3 MB |
625 | if (argc < 2) { |
626 | img_addr = load_addr; | |
d5934ad7 MB |
627 | debug ("* kernel: default image load address = 0x%08lx\n", |
628 | load_addr); | |
629 | #if defined(CONFIG_FIT) | |
630 | } else if (fit_parse_conf (argv[1], load_addr, &img_addr, | |
631 | &fit_uname_config)) { | |
632 | debug ("* kernel: config '%s' from image at 0x%08lx\n", | |
633 | fit_uname_config, img_addr); | |
634 | } else if (fit_parse_subimage (argv[1], load_addr, &img_addr, | |
635 | &fit_uname_kernel)) { | |
636 | debug ("* kernel: subimage '%s' from image at 0x%08lx\n", | |
637 | fit_uname_kernel, img_addr); | |
638 | #endif | |
5cf746c3 MB |
639 | } else { |
640 | img_addr = simple_strtoul(argv[1], NULL, 16); | |
d5934ad7 | 641 | debug ("* kernel: cmdline image address = 0x%08lx\n", img_addr); |
5cf746c3 | 642 | } |
47d1a6e1 | 643 | |
5cf746c3 | 644 | show_boot_progress (1); |
56f94be3 | 645 | |
fff888a1 | 646 | /* copy from dataflash if needed */ |
9a4daad0 | 647 | img_addr = genimg_get_image (img_addr); |
5cf746c3 | 648 | |
d5934ad7 | 649 | /* check image type, for FIT images get FIT kernel node */ |
6986a385 | 650 | *os_data = *os_len = 0; |
9a4daad0 | 651 | switch (genimg_get_format ((void *)img_addr)) { |
d5934ad7 | 652 | case IMAGE_FORMAT_LEGACY: |
6986a385 MB |
653 | printf ("## Booting kernel from Legacy Image at %08lx ...\n", |
654 | img_addr); | |
1efd4360 MB |
655 | hdr = image_get_kernel (img_addr, images->verify); |
656 | if (!hdr) | |
d5934ad7 | 657 | return NULL; |
d5934ad7 MB |
658 | show_boot_progress (5); |
659 | ||
6986a385 | 660 | /* get os_data and os_len */ |
d5934ad7 MB |
661 | switch (image_get_type (hdr)) { |
662 | case IH_TYPE_KERNEL: | |
663 | *os_data = image_get_data (hdr); | |
664 | *os_len = image_get_data_size (hdr); | |
665 | break; | |
666 | case IH_TYPE_MULTI: | |
667 | image_multi_getimg (hdr, 0, os_data, os_len); | |
668 | break; | |
669 | default: | |
670 | printf ("Wrong Image Type for %s command\n", cmdtp->name); | |
671 | show_boot_progress (-5); | |
672 | return NULL; | |
673 | } | |
cb1c4896 MB |
674 | |
675 | /* | |
676 | * copy image header to allow for image overwrites during kernel | |
677 | * decompression. | |
678 | */ | |
679 | memmove (&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t)); | |
680 | ||
681 | /* save pointer to image header */ | |
d5934ad7 | 682 | images->legacy_hdr_os = hdr; |
47d1a6e1 | 683 | |
cb1c4896 | 684 | images->legacy_hdr_valid = 1; |
1372cce2 | 685 | show_boot_progress (6); |
5cf746c3 | 686 | break; |
d5934ad7 MB |
687 | #if defined(CONFIG_FIT) |
688 | case IMAGE_FORMAT_FIT: | |
689 | fit_hdr = (void *)img_addr; | |
6986a385 MB |
690 | printf ("## Booting kernel from FIT Image at %08lx ...\n", |
691 | img_addr); | |
692 | ||
693 | if (!fit_check_format (fit_hdr)) { | |
694 | puts ("Bad FIT kernel image format!\n"); | |
1372cce2 | 695 | show_boot_progress (-100); |
6986a385 MB |
696 | return NULL; |
697 | } | |
1372cce2 | 698 | show_boot_progress (100); |
47d1a6e1 | 699 | |
6986a385 MB |
700 | if (!fit_uname_kernel) { |
701 | /* | |
702 | * no kernel image node unit name, try to get config | |
703 | * node first. If config unit node name is NULL | |
704 | * fit_conf_get_node() will try to find default config node | |
705 | */ | |
1372cce2 | 706 | show_boot_progress (101); |
f773bea8 MB |
707 | cfg_noffset = fit_conf_get_node (fit_hdr, fit_uname_config); |
708 | if (cfg_noffset < 0) { | |
1372cce2 | 709 | show_boot_progress (-101); |
6986a385 | 710 | return NULL; |
1372cce2 | 711 | } |
f773bea8 MB |
712 | /* save configuration uname provided in the first |
713 | * bootm argument | |
714 | */ | |
715 | images->fit_uname_cfg = fdt_get_name (fit_hdr, cfg_noffset, NULL); | |
716 | printf (" Using '%s' configuration\n", images->fit_uname_cfg); | |
717 | show_boot_progress (103); | |
47d1a6e1 | 718 | |
f773bea8 | 719 | os_noffset = fit_conf_get_kernel_node (fit_hdr, cfg_noffset); |
6986a385 MB |
720 | fit_uname_kernel = fit_get_name (fit_hdr, os_noffset, NULL); |
721 | } else { | |
722 | /* get kernel component image node offset */ | |
1372cce2 | 723 | show_boot_progress (102); |
6986a385 MB |
724 | os_noffset = fit_image_get_node (fit_hdr, fit_uname_kernel); |
725 | } | |
1372cce2 MB |
726 | if (os_noffset < 0) { |
727 | show_boot_progress (-103); | |
6986a385 | 728 | return NULL; |
1372cce2 | 729 | } |
47d1a6e1 | 730 | |
6986a385 | 731 | printf (" Trying '%s' kernel subimage\n", fit_uname_kernel); |
47d1a6e1 | 732 | |
1372cce2 | 733 | show_boot_progress (104); |
6986a385 MB |
734 | if (!fit_check_kernel (fit_hdr, os_noffset, images->verify)) |
735 | return NULL; | |
47d1a6e1 | 736 | |
6986a385 MB |
737 | /* get kernel image data address and length */ |
738 | if (fit_image_get_data (fit_hdr, os_noffset, &data, &len)) { | |
739 | puts ("Could not find kernel subimage data!\n"); | |
1372cce2 | 740 | show_boot_progress (-107); |
6986a385 MB |
741 | return NULL; |
742 | } | |
1372cce2 | 743 | show_boot_progress (108); |
47d1a6e1 | 744 | |
6986a385 MB |
745 | *os_len = len; |
746 | *os_data = (ulong)data; | |
747 | images->fit_hdr_os = fit_hdr; | |
748 | images->fit_uname_os = fit_uname_kernel; | |
3dfe1101 | 749 | images->fit_noffset_os = os_noffset; |
6986a385 | 750 | break; |
9c4c5ae3 | 751 | #endif |
5cf746c3 | 752 | default: |
d5934ad7 | 753 | printf ("Wrong Image Format for %s command\n", cmdtp->name); |
1372cce2 | 754 | show_boot_progress (-108); |
5cf746c3 | 755 | return NULL; |
47d1a6e1 WD |
756 | } |
757 | ||
06c53bea | 758 | debug (" kernel data at 0x%08lx, len = 0x%08lx (%ld)\n", |
6986a385 | 759 | *os_data, *os_len, *os_len); |
47d1a6e1 | 760 | |
d5934ad7 | 761 | return (void *)img_addr; |
5cf746c3 | 762 | } |
98a9c4d4 | 763 | |
0d498393 | 764 | U_BOOT_CMD( |
6d0f6bcf | 765 | bootm, CONFIG_SYS_MAXARGS, 1, do_bootm, |
1ee1180b MB |
766 | "bootm - boot application image from memory\n", |
767 | "[addr [arg ...]]\n - boot application image stored in memory\n" | |
768 | "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n" | |
769 | "\t'arg' can be the address of an initrd image\n" | |
4a2ad5ff | 770 | #if defined(CONFIG_OF_LIBFDT) |
98a9c4d4 | 771 | "\tWhen booting a Linux kernel which requires a flat device-tree\n" |
5441f61a | 772 | "\ta third argument is required which is the address of the\n" |
98a9c4d4 MM |
773 | "\tdevice-tree blob. To boot that kernel without an initrd image,\n" |
774 | "\tuse a '-' for the second argument. If you do not pass a third\n" | |
775 | "\ta bd_info struct will be passed instead\n" | |
98a9c4d4 | 776 | #endif |
6986a385 MB |
777 | #if defined(CONFIG_FIT) |
778 | "\t\nFor the new multi component uImage format (FIT) addresses\n" | |
779 | "\tmust be extened to include component or configuration unit name:\n" | |
780 | "\taddr:<subimg_uname> - direct component image specification\n" | |
781 | "\taddr#<conf_uname> - configuration specification\n" | |
782 | "\tUse iminfo command to get the list of existing component\n" | |
783 | "\timages and configurations.\n" | |
784 | #endif | |
8bde7f77 | 785 | ); |
47d1a6e1 | 786 | |
1ee1180b MB |
787 | /*******************************************************************/ |
788 | /* bootd - boot default image */ | |
789 | /*******************************************************************/ | |
baa26db4 | 790 | #if defined(CONFIG_CMD_BOOTD) |
47d1a6e1 WD |
791 | int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
792 | { | |
793 | int rcode = 0; | |
47d1a6e1 | 794 | |
6d0f6bcf | 795 | #ifndef CONFIG_SYS_HUSH_PARSER |
1ee1180b MB |
796 | if (run_command (getenv ("bootcmd"), flag) < 0) |
797 | rcode = 1; | |
47d1a6e1 | 798 | #else |
1ee1180b MB |
799 | if (parse_string_outer (getenv ("bootcmd"), |
800 | FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) | |
801 | rcode = 1; | |
47d1a6e1 WD |
802 | #endif |
803 | return rcode; | |
804 | } | |
47d1a6e1 | 805 | |
0d498393 | 806 | U_BOOT_CMD( |
1ee1180b MB |
807 | boot, 1, 1, do_bootd, |
808 | "boot - boot default, i.e., run 'bootcmd'\n", | |
9d2b18a0 WD |
809 | NULL |
810 | ); | |
47d1a6e1 | 811 | |
9d2b18a0 | 812 | /* keep old command name "bootd" for backward compatibility */ |
0d498393 | 813 | U_BOOT_CMD( |
1ee1180b MB |
814 | bootd, 1, 1, do_bootd, |
815 | "bootd - boot default, i.e., run 'bootcmd'\n", | |
8bde7f77 WD |
816 | NULL |
817 | ); | |
47d1a6e1 | 818 | |
47d1a6e1 | 819 | #endif |
47d1a6e1 | 820 | |
47d1a6e1 | 821 | |
1ee1180b MB |
822 | /*******************************************************************/ |
823 | /* iminfo - print header info for a requested image */ | |
824 | /*******************************************************************/ | |
baa26db4 | 825 | #if defined(CONFIG_CMD_IMI) |
1ee1180b | 826 | int do_iminfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
47d1a6e1 WD |
827 | { |
828 | int arg; | |
829 | ulong addr; | |
1ee1180b | 830 | int rcode = 0; |
47d1a6e1 | 831 | |
47d1a6e1 WD |
832 | if (argc < 2) { |
833 | return image_info (load_addr); | |
834 | } | |
47d1a6e1 | 835 | |
1ee1180b MB |
836 | for (arg = 1; arg < argc; ++arg) { |
837 | addr = simple_strtoul (argv[arg], NULL, 16); | |
838 | if (image_info (addr) != 0) | |
839 | rcode = 1; | |
47d1a6e1 WD |
840 | } |
841 | return rcode; | |
842 | } | |
47d1a6e1 | 843 | |
47d1a6e1 WD |
844 | static int image_info (ulong addr) |
845 | { | |
d5934ad7 | 846 | void *hdr = (void *)addr; |
47d1a6e1 | 847 | |
47d1a6e1 | 848 | printf ("\n## Checking Image at %08lx ...\n", addr); |
47d1a6e1 | 849 | |
9a4daad0 | 850 | switch (genimg_get_format (hdr)) { |
d5934ad7 MB |
851 | case IMAGE_FORMAT_LEGACY: |
852 | puts (" Legacy image found\n"); | |
853 | if (!image_check_magic (hdr)) { | |
854 | puts (" Bad Magic Number\n"); | |
855 | return 1; | |
856 | } | |
47d1a6e1 | 857 | |
d5934ad7 MB |
858 | if (!image_check_hcrc (hdr)) { |
859 | puts (" Bad Header Checksum\n"); | |
860 | return 1; | |
47d1a6e1 WD |
861 | } |
862 | ||
d5934ad7 | 863 | image_print_contents (hdr); |
47d1a6e1 | 864 | |
d5934ad7 MB |
865 | puts (" Verifying Checksum ... "); |
866 | if (!image_check_dcrc (hdr)) { | |
867 | puts (" Bad Data CRC\n"); | |
868 | return 1; | |
47d1a6e1 | 869 | } |
d5934ad7 MB |
870 | puts ("OK\n"); |
871 | return 0; | |
872 | #if defined(CONFIG_FIT) | |
873 | case IMAGE_FORMAT_FIT: | |
874 | puts (" FIT image found\n"); | |
47d1a6e1 | 875 | |
e32fea6a MB |
876 | if (!fit_check_format (hdr)) { |
877 | puts ("Bad FIT image format!\n"); | |
878 | return 1; | |
47d1a6e1 WD |
879 | } |
880 | ||
e32fea6a | 881 | fit_print_contents (hdr); |
a4f24345 BS |
882 | |
883 | if (!fit_all_image_check_hashes (hdr)) { | |
884 | puts ("Bad hash in FIT image!\n"); | |
885 | return 1; | |
886 | } | |
887 | ||
d5934ad7 MB |
888 | return 0; |
889 | #endif | |
890 | default: | |
891 | puts ("Unknown image format!\n"); | |
892 | break; | |
47d1a6e1 WD |
893 | } |
894 | ||
d5934ad7 | 895 | return 1; |
47d1a6e1 | 896 | } |
0d498393 WD |
897 | |
898 | U_BOOT_CMD( | |
6d0f6bcf | 899 | iminfo, CONFIG_SYS_MAXARGS, 1, do_iminfo, |
8bde7f77 WD |
900 | "iminfo - print header information for application image\n", |
901 | "addr [addr ...]\n" | |
902 | " - print header information for application image starting at\n" | |
903 | " address 'addr' in memory; this includes verification of the\n" | |
904 | " image contents (magic number, header and payload checksums)\n" | |
905 | ); | |
25c751e9 | 906 | #endif |
87a449c8 | 907 | |
25c751e9 | 908 | |
1ee1180b MB |
909 | /*******************************************************************/ |
910 | /* imls - list all images found in flash */ | |
911 | /*******************************************************************/ | |
baa26db4 | 912 | #if defined(CONFIG_CMD_IMLS) |
27b207fd WD |
913 | int do_imls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
914 | { | |
915 | flash_info_t *info; | |
916 | int i, j; | |
d5934ad7 | 917 | void *hdr; |
25c751e9 | 918 | |
1ee1180b | 919 | for (i = 0, info = &flash_info[0]; |
6d0f6bcf | 920 | i < CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) { |
25c751e9 | 921 | |
27b207fd WD |
922 | if (info->flash_id == FLASH_UNKNOWN) |
923 | goto next_bank; | |
1ee1180b | 924 | for (j = 0; j < info->sector_count; ++j) { |
25c751e9 | 925 | |
d5934ad7 MB |
926 | hdr = (void *)info->start[j]; |
927 | if (!hdr) | |
b97a2a0a | 928 | goto next_sector; |
27b207fd | 929 | |
9a4daad0 | 930 | switch (genimg_get_format (hdr)) { |
d5934ad7 | 931 | case IMAGE_FORMAT_LEGACY: |
d5934ad7 MB |
932 | if (!image_check_hcrc (hdr)) |
933 | goto next_sector; | |
934 | ||
935 | printf ("Legacy Image at %08lX:\n", (ulong)hdr); | |
936 | image_print_contents (hdr); | |
937 | ||
938 | puts (" Verifying Checksum ... "); | |
939 | if (!image_check_dcrc (hdr)) { | |
940 | puts ("Bad Data CRC\n"); | |
941 | } else { | |
942 | puts ("OK\n"); | |
943 | } | |
944 | break; | |
945 | #if defined(CONFIG_FIT) | |
946 | case IMAGE_FORMAT_FIT: | |
e32fea6a MB |
947 | if (!fit_check_format (hdr)) |
948 | goto next_sector; | |
949 | ||
d5934ad7 | 950 | printf ("FIT Image at %08lX:\n", (ulong)hdr); |
e32fea6a | 951 | fit_print_contents (hdr); |
d5934ad7 | 952 | break; |
213bf8c8 | 953 | #endif |
d5934ad7 | 954 | default: |
27b207fd | 955 | goto next_sector; |
25c751e9 | 956 | } |
87a449c8 | 957 | |
bdccc4fe | 958 | next_sector: ; |
c76f951a | 959 | } |
bdccc4fe | 960 | next_bank: ; |
27b207fd | 961 | } |
c76f951a | 962 | |
27b207fd WD |
963 | return (0); |
964 | } | |
c76f951a | 965 | |
27b207fd WD |
966 | U_BOOT_CMD( |
967 | imls, 1, 1, do_imls, | |
968 | "imls - list all images found in flash\n", | |
969 | "\n" | |
970 | " - Prints information about all images found at sector\n" | |
971 | " boundaries in flash.\n" | |
972 | ); | |
98a9c4d4 | 973 | #endif |
47d1a6e1 | 974 | |
1ee1180b | 975 | /*******************************************************************/ |
5cf746c3 | 976 | /* helper routines */ |
1ee1180b | 977 | /*******************************************************************/ |
1ee1180b MB |
978 | #ifdef CONFIG_SILENT_CONSOLE |
979 | static void fixup_silent_linux () | |
980 | { | |
981 | char buf[256], *start, *end; | |
982 | char *cmdline = getenv ("bootargs"); | |
47d1a6e1 | 983 | |
1ee1180b MB |
984 | /* Only fix cmdline when requested */ |
985 | if (!(gd->flags & GD_FLG_SILENT)) | |
986 | return; | |
47d1a6e1 | 987 | |
1ee1180b MB |
988 | debug ("before silent fix-up: %s\n", cmdline); |
989 | if (cmdline) { | |
990 | if ((start = strstr (cmdline, "console=")) != NULL) { | |
991 | end = strchr (start, ' '); | |
992 | strncpy (buf, cmdline, (start - cmdline + 8)); | |
993 | if (end) | |
994 | strcpy (buf + (start - cmdline + 8), end); | |
995 | else | |
996 | buf[start - cmdline + 8] = '\0'; | |
997 | } else { | |
998 | strcpy (buf, cmdline); | |
999 | strcat (buf, " console="); | |
47d1a6e1 | 1000 | } |
47d1a6e1 | 1001 | } else { |
1ee1180b | 1002 | strcpy (buf, "console="); |
e7902122 | 1003 | } |
10aaf716 | 1004 | |
1ee1180b MB |
1005 | setenv ("bootargs", buf); |
1006 | debug ("after silent fix-up: %s\n", buf); | |
1007 | } | |
1008 | #endif /* CONFIG_SILENT_CONSOLE */ | |
38eb508e | 1009 | |
38eb508e | 1010 | |
1ee1180b MB |
1011 | /*******************************************************************/ |
1012 | /* OS booting routines */ | |
1013 | /*******************************************************************/ | |
c76f951a | 1014 | |
40d7e99d | 1015 | static int do_bootm_netbsd (int flag, int argc, char *argv[], |
8a5ea3e6 | 1016 | bootm_headers_t *images) |
d791b1dc | 1017 | { |
1ee1180b | 1018 | void (*loader)(bd_t *, image_header_t *, char *, char *); |
d5934ad7 | 1019 | image_header_t *os_hdr, *hdr; |
f13e7b2e | 1020 | ulong kernel_data, kernel_len; |
1ee1180b MB |
1021 | char *consdev; |
1022 | char *cmdline; | |
1023 | ||
d5934ad7 MB |
1024 | #if defined(CONFIG_FIT) |
1025 | if (!images->legacy_hdr_valid) { | |
1026 | fit_unsupported_reset ("NetBSD"); | |
40d7e99d | 1027 | return 1; |
38eb508e GVB |
1028 | } |
1029 | #endif | |
d5934ad7 | 1030 | hdr = images->legacy_hdr_os; |
47d1a6e1 WD |
1031 | |
1032 | /* | |
1033 | * Booting a (NetBSD) kernel image | |
1034 | * | |
1035 | * This process is pretty similar to a standalone application: | |
1036 | * The (first part of an multi-) image must be a stage-2 loader, | |
1037 | * which in turn is responsible for loading & invoking the actual | |
1038 | * kernel. The only differences are the parameters being passed: | |
1039 | * besides the board info strucure, the loader expects a command | |
1040 | * line, the name of the console device, and (optionally) the | |
1041 | * address of the original image header. | |
1042 | */ | |
d5934ad7 | 1043 | os_hdr = NULL; |
cb1c4896 | 1044 | if (image_check_type (&images->legacy_hdr_os_copy, IH_TYPE_MULTI)) { |
f13e7b2e MB |
1045 | image_multi_getimg (hdr, 1, &kernel_data, &kernel_len); |
1046 | if (kernel_len) | |
d5934ad7 | 1047 | os_hdr = hdr; |
f13e7b2e | 1048 | } |
47d1a6e1 WD |
1049 | |
1050 | consdev = ""; | |
1051 | #if defined (CONFIG_8xx_CONS_SMC1) | |
1052 | consdev = "smc1"; | |
1053 | #elif defined (CONFIG_8xx_CONS_SMC2) | |
1054 | consdev = "smc2"; | |
1055 | #elif defined (CONFIG_8xx_CONS_SCC2) | |
1056 | consdev = "scc2"; | |
1057 | #elif defined (CONFIG_8xx_CONS_SCC3) | |
1058 | consdev = "scc3"; | |
1059 | #endif | |
1060 | ||
1061 | if (argc > 2) { | |
1062 | ulong len; | |
1063 | int i; | |
1064 | ||
1ee1180b | 1065 | for (i = 2, len = 0; i < argc; i += 1) |
47d1a6e1 WD |
1066 | len += strlen (argv[i]) + 1; |
1067 | cmdline = malloc (len); | |
1068 | ||
1ee1180b | 1069 | for (i = 2, len = 0; i < argc; i += 1) { |
47d1a6e1 WD |
1070 | if (i > 2) |
1071 | cmdline[len++] = ' '; | |
1072 | strcpy (&cmdline[len], argv[i]); | |
1073 | len += strlen (argv[i]); | |
1074 | } | |
1ee1180b | 1075 | } else if ((cmdline = getenv ("bootargs")) == NULL) { |
47d1a6e1 WD |
1076 | cmdline = ""; |
1077 | } | |
1078 | ||
c160a954 | 1079 | loader = (void (*)(bd_t *, image_header_t *, char *, char *))images->ep; |
47d1a6e1 WD |
1080 | |
1081 | printf ("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", | |
1082 | (ulong)loader); | |
1083 | ||
fad63407 | 1084 | show_boot_progress (15); |
47d1a6e1 WD |
1085 | |
1086 | /* | |
1087 | * NetBSD Stage-2 Loader Parameters: | |
1088 | * r3: ptr to board info data | |
1089 | * r4: image address | |
1090 | * r5: console device | |
1091 | * r6: boot args string | |
1092 | */ | |
d5934ad7 | 1093 | (*loader) (gd->bd, os_hdr, consdev, cmdline); |
40d7e99d KG |
1094 | |
1095 | return 1; | |
47d1a6e1 WD |
1096 | } |
1097 | ||
1ee1180b | 1098 | #ifdef CONFIG_LYNXKDI |
40d7e99d | 1099 | static int do_bootm_lynxkdi (int flag, int argc, char *argv[], |
8a5ea3e6 | 1100 | bootm_headers_t *images) |
1ee1180b | 1101 | { |
cb1c4896 | 1102 | image_header_t *hdr = &images->legacy_hdr_os_copy; |
d5934ad7 MB |
1103 | |
1104 | #if defined(CONFIG_FIT) | |
1105 | if (!images->legacy_hdr_valid) { | |
1106 | fit_unsupported_reset ("Lynx"); | |
40d7e99d | 1107 | return 1; |
d5934ad7 MB |
1108 | } |
1109 | #endif | |
1110 | ||
1111 | lynxkdi_boot ((image_header_t *)hdr); | |
40d7e99d KG |
1112 | |
1113 | return 1; | |
1ee1180b MB |
1114 | } |
1115 | #endif /* CONFIG_LYNXKDI */ | |
1116 | ||
40d7e99d | 1117 | static int do_bootm_rtems (int flag, int argc, char *argv[], |
8a5ea3e6 | 1118 | bootm_headers_t *images) |
1ee1180b | 1119 | { |
1ee1180b | 1120 | void (*entry_point)(bd_t *); |
d791b1dc | 1121 | |
d5934ad7 MB |
1122 | #if defined(CONFIG_FIT) |
1123 | if (!images->legacy_hdr_valid) { | |
1124 | fit_unsupported_reset ("RTEMS"); | |
40d7e99d | 1125 | return 1; |
d5934ad7 MB |
1126 | } |
1127 | #endif | |
1128 | ||
c160a954 | 1129 | entry_point = (void (*)(bd_t *))images->ep; |
d791b1dc WD |
1130 | |
1131 | printf ("## Transferring control to RTEMS (at address %08lx) ...\n", | |
1132 | (ulong)entry_point); | |
1133 | ||
fad63407 | 1134 | show_boot_progress (15); |
d791b1dc WD |
1135 | |
1136 | /* | |
1137 | * RTEMS Parameters: | |
1138 | * r3: ptr to board info data | |
1139 | */ | |
1ee1180b | 1140 | (*entry_point)(gd->bd); |
40d7e99d KG |
1141 | |
1142 | return 1; | |
d791b1dc | 1143 | } |
7f70e853 | 1144 | |
baa26db4 | 1145 | #if defined(CONFIG_CMD_ELF) |
40d7e99d | 1146 | static int do_bootm_vxworks (int flag, int argc, char *argv[], |
8a5ea3e6 | 1147 | bootm_headers_t *images) |
47d1a6e1 | 1148 | { |
47d1a6e1 | 1149 | char str[80]; |
7f70e853 | 1150 | |
d5934ad7 | 1151 | #if defined(CONFIG_FIT) |
cb1c4896 | 1152 | if (!images->legacy_hdr_valid) { |
d5934ad7 | 1153 | fit_unsupported_reset ("VxWorks"); |
40d7e99d | 1154 | return 1; |
d5934ad7 MB |
1155 | } |
1156 | #endif | |
47d1a6e1 | 1157 | |
c160a954 | 1158 | sprintf(str, "%lx", images->ep); /* write entry-point into string */ |
47d1a6e1 | 1159 | setenv("loadaddr", str); |
40d7e99d KG |
1160 | do_bootvx(NULL, 0, 0, NULL); |
1161 | ||
1162 | return 1; | |
47d1a6e1 WD |
1163 | } |
1164 | ||
40d7e99d | 1165 | static int do_bootm_qnxelf(int flag, int argc, char *argv[], |
8a5ea3e6 | 1166 | bootm_headers_t *images) |
47d1a6e1 | 1167 | { |
47d1a6e1 WD |
1168 | char *local_args[2]; |
1169 | char str[16]; | |
d5934ad7 MB |
1170 | |
1171 | #if defined(CONFIG_FIT) | |
1172 | if (!images->legacy_hdr_valid) { | |
1173 | fit_unsupported_reset ("QNX"); | |
40d7e99d | 1174 | return 1; |
d5934ad7 MB |
1175 | } |
1176 | #endif | |
47d1a6e1 | 1177 | |
c160a954 | 1178 | sprintf(str, "%lx", images->ep); /* write entry-point into string */ |
47d1a6e1 WD |
1179 | local_args[0] = argv[0]; |
1180 | local_args[1] = str; /* and provide it via the arguments */ | |
40d7e99d KG |
1181 | do_bootelf(NULL, 0, 2, local_args); |
1182 | ||
1183 | return 1; | |
47d1a6e1 | 1184 | } |
90253178 | 1185 | #endif |
f5ed9e39 PT |
1186 | |
1187 | #ifdef CONFIG_INTEGRITY | |
1188 | static int do_bootm_integrity (int flag, int argc, char *argv[], | |
1189 | bootm_headers_t *images) | |
1190 | { | |
1191 | void (*entry_point)(void); | |
1192 | ||
1193 | #if defined(CONFIG_FIT) | |
1194 | if (!images->legacy_hdr_valid) { | |
1195 | fit_unsupported_reset ("INTEGRITY"); | |
1196 | return 1; | |
1197 | } | |
1198 | #endif | |
1199 | ||
1200 | entry_point = (void (*)(void))images->ep; | |
1201 | ||
1202 | printf ("## Transferring control to INTEGRITY (at address %08lx) ...\n", | |
1203 | (ulong)entry_point); | |
1204 | ||
1205 | show_boot_progress (15); | |
1206 | ||
1207 | /* | |
1208 | * INTEGRITY Parameters: | |
1209 | * None | |
1210 | */ | |
1211 | (*entry_point)(); | |
1212 | ||
1213 | return 1; | |
1214 | } | |
1215 | #endif |