Blame view
common/bootm.c
25.2 KB
b63964037 bootm: Split out ... |
1 2 3 4 5 6 |
/* * (C) Copyright 2000-2009 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * SPDX-License-Identifier: GPL-2.0+ */ |
ea51a6282 Allow compiling c... |
7 |
#ifndef USE_HOSTCC |
b63964037 bootm: Split out ... |
8 |
#include <common.h> |
ea51a6282 Allow compiling c... |
9 |
#include <bootstage.h> |
b63964037 bootm: Split out ... |
10 |
#include <bzlib.h> |
90268b878 x86: Support load... |
11 |
#include <errno.h> |
b63964037 bootm: Split out ... |
12 13 14 |
#include <fdt_support.h> #include <lmb.h> #include <malloc.h> |
0eb25b619 common: Make sure... |
15 |
#include <mapmem.h> |
b63964037 bootm: Split out ... |
16 17 18 19 20 |
#include <asm/io.h> #include <linux/lzo.h> #include <lzma/LzmaTypes.h> #include <lzma/LzmaDec.h> #include <lzma/LzmaTools.h> |
b63964037 bootm: Split out ... |
21 22 23 |
#if defined(CONFIG_CMD_USB) #include <usb.h> #endif |
ea51a6282 Allow compiling c... |
24 25 26 |
#else #include "mkimage.h" #endif |
b63964037 bootm: Split out ... |
27 |
|
ea51a6282 Allow compiling c... |
28 29 30 |
#include <command.h> #include <bootm.h> #include <image.h> |
b63964037 bootm: Split out ... |
31 32 33 34 35 36 37 |
#ifndef CONFIG_SYS_BOOTM_LEN /* use 8MByte as default max gunzip size */ #define CONFIG_SYS_BOOTM_LEN 0x800000 #endif #define IH_INITRD_ARCH IH_ARCH_DEFAULT |
ea51a6282 Allow compiling c... |
38 39 40 |
#ifndef USE_HOSTCC DECLARE_GLOBAL_DATA_PTR; |
5db28905c cmd: Split 'bootz... |
41 |
bootm_headers_t images; /* pointers to os/initrd/fdt images */ |
b63964037 bootm: Split out ... |
42 43 44 45 46 47 48 49 50 51 52 |
static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len); #ifdef CONFIG_LMB static void boot_start_lmb(bootm_headers_t *images) { ulong mem_start; phys_size_t mem_size; lmb_init(&images->lmb); |
723806cc5 env: Rename some ... |
53 54 |
mem_start = env_get_bootm_low(); mem_size = env_get_bootm_size(); |
b63964037 bootm: Split out ... |
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size); arch_lmb_reserve(&images->lmb); board_lmb_reserve(&images->lmb); } #else #define lmb_reserve(lmb, base, size) static inline void boot_start_lmb(bootm_headers_t *images) { } #endif static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { memset((void *)&images, 0, sizeof(images)); |
bfebc8c96 env: Rename geten... |
70 |
images.verify = env_get_yesno("verify"); |
b63964037 bootm: Split out ... |
71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
boot_start_lmb(&images); bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start"); images.state = BOOTM_STATE_START; return 0; } static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { const void *os_hdr; bool ep_found = false; |
90268b878 x86: Support load... |
85 |
int ret; |
b63964037 bootm: Split out ... |
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
/* get kernel image header, start address and length */ os_hdr = boot_get_kernel(cmdtp, flag, argc, argv, &images, &images.os.image_start, &images.os.image_len); if (images.os.image_len == 0) { puts("ERROR: can't get kernel image! "); return 1; } /* get image parameters */ switch (genimg_get_format(os_hdr)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: images.os.type = image_get_type(os_hdr); images.os.comp = image_get_comp(os_hdr); images.os.os = image_get_os(os_hdr); images.os.end = image_get_image_end(os_hdr); images.os.load = image_get_load(os_hdr); |
90268b878 x86: Support load... |
106 |
images.os.arch = image_get_arch(os_hdr); |
b63964037 bootm: Split out ... |
107 108 |
break; #endif |
73223f0e1 Kconfig: Move CON... |
109 |
#if IMAGE_ENABLE_FIT |
b63964037 bootm: Split out ... |
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
case IMAGE_FORMAT_FIT: if (fit_image_get_type(images.fit_hdr_os, images.fit_noffset_os, &images.os.type)) { puts("Can't get image type! "); bootstage_error(BOOTSTAGE_ID_FIT_TYPE); return 1; } if (fit_image_get_comp(images.fit_hdr_os, images.fit_noffset_os, &images.os.comp)) { puts("Can't get image compression! "); bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION); return 1; } if (fit_image_get_os(images.fit_hdr_os, images.fit_noffset_os, &images.os.os)) { puts("Can't get image OS! "); bootstage_error(BOOTSTAGE_ID_FIT_OS); return 1; } |
90268b878 x86: Support load... |
136 137 138 139 140 141 142 |
if (fit_image_get_arch(images.fit_hdr_os, images.fit_noffset_os, &images.os.arch)) { puts("Can't get image ARCH! "); return 1; } |
b63964037 bootm: Split out ... |
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
images.os.end = fit_get_end(images.fit_hdr_os); if (fit_image_get_load(images.fit_hdr_os, images.fit_noffset_os, &images.os.load)) { puts("Can't get image load address! "); bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR); return 1; } break; #endif #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: images.os.type = IH_TYPE_KERNEL; images.os.comp = IH_COMP_NONE; images.os.os = IH_OS_LINUX; |
b63964037 bootm: Split out ... |
159 160 161 |
images.os.end = android_image_get_end(os_hdr); images.os.load = android_image_get_kload(os_hdr); |
86f4695bd image: Fix Androi... |
162 163 |
images.ep = images.os.load; ep_found = true; |
b63964037 bootm: Split out ... |
164 165 166 167 168 169 170 |
break; #endif default: puts("ERROR: unknown image format type! "); return 1; } |
90268b878 x86: Support load... |
171 |
/* If we have a valid setup.bin, we will use that for entry (x86) */ |
5bda35cff x86: image: Add n... |
172 173 |
if (images.os.arch == IH_ARCH_I386 || images.os.arch == IH_ARCH_X86_64) { |
90268b878 x86: Support load... |
174 175 176 177 178 179 180 181 182 183 |
ulong len; ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len); if (ret < 0 && ret != -ENOENT) { puts("Could not find a valid setup.bin for x86 "); return 1; } /* Kernel entry point is the setup.bin */ } else if (images.legacy_hdr_valid) { |
b63964037 bootm: Split out ... |
184 |
images.ep = image_get_ep(&images.legacy_hdr_os_copy); |
73223f0e1 Kconfig: Move CON... |
185 |
#if IMAGE_ENABLE_FIT |
b63964037 bootm: Split out ... |
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
} else if (images.fit_uname_os) { int ret; ret = fit_image_get_entry(images.fit_hdr_os, images.fit_noffset_os, &images.ep); if (ret) { puts("Can't get entry point property! "); return 1; } #endif } else if (!ep_found) { puts("Could not find kernel entry point! "); return 1; } if (images.os.type == IH_TYPE_KERNEL_NOLOAD) { images.os.load = images.os.image_start; images.ep += images.os.load; } |
7a80de464 image: Correct th... |
207 |
images.os.start = map_to_sysmem(os_hdr); |
b63964037 bootm: Split out ... |
208 209 210 |
return 0; } |
d52e8575d Combine bootm_fin... |
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
/** * bootm_find_images - wrapper to find and locate various images * @flag: Ignored Argument * @argc: command argument count * @argv: command argument list * * boot_find_images() will attempt to load an available ramdisk, * flattened device tree, as well as specifically marked * "loadable" images (loadables are FIT only) * * Note: bootm_find_images will skip an image if it is not found * * @return: * 0, if all existing images were loaded correctly * 1, if an image is found but corrupted, or invalid */ int bootm_find_images(int flag, int argc, char * const argv[]) |
b63964037 bootm: Split out ... |
228 229 230 231 232 233 234 235 236 237 238 |
{ int ret; /* find ramdisk */ ret = boot_get_ramdisk(argc, argv, &images, IH_INITRD_ARCH, &images.rd_start, &images.rd_end); if (ret) { puts("Ramdisk image is corrupt or invalid "); return 1; } |
aa34fbc08 fdt: Allow libfdt... |
239 |
#if IMAGE_ENABLE_OF_LIBFDT |
b63964037 bootm: Split out ... |
240 241 242 243 244 245 246 247 |
/* find flattened device tree */ ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, &images, &images.ft_addr, &images.ft_len); if (ret) { puts("Could not find a valid device tree "); return 1; } |
90fbee3e4 cmd_fdt: Actually... |
248 |
set_working_fdt_addr((ulong)images.ft_addr); |
b63964037 bootm: Split out ... |
249 |
#endif |
73223f0e1 Kconfig: Move CON... |
250 |
#if IMAGE_ENABLE_FIT |
8b93a92f6 fpga: allow progr... |
251 |
#if defined(CONFIG_FPGA) |
62afc6018 image: Add boot_g... |
252 253 254 255 256 257 258 259 260 |
/* find bitstreams */ ret = boot_get_fpga(argc, argv, &images, IH_ARCH_DEFAULT, NULL, NULL); if (ret) { printf("FPGA image is corrupted or invalid "); return 1; } #endif |
84a07dbfd add boot_get_load... |
261 262 263 264 265 266 267 268 |
/* find all of the loadables */ ret = boot_get_loadable(argc, argv, &images, IH_ARCH_DEFAULT, NULL, NULL); if (ret) { printf("Loadable(s) is corrupt or invalid "); return 1; } |
84a07dbfd add boot_get_load... |
269 |
#endif |
b63964037 bootm: Split out ... |
270 271 272 273 274 275 276 277 278 279 280 |
return 0; } static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (((images.os.type == IH_TYPE_KERNEL) || (images.os.type == IH_TYPE_KERNEL_NOLOAD) || (images.os.type == IH_TYPE_MULTI)) && (images.os.os == IH_OS_LINUX || images.os.os == IH_OS_VXWORKS)) |
d52e8575d Combine bootm_fin... |
281 |
return bootm_find_images(flag, argc, argv); |
b63964037 bootm: Split out ... |
282 283 284 |
return 0; } |
40e5975f9 bootm: Move compr... |
285 |
#endif /* USE_HOSTC */ |
8fd6a4b51 bootm: Use print_... |
286 287 288 289 290 291 292 293 |
/** * print_decomp_msg() - Print a suitable decompression/loading message * * @type: OS type (IH_OS_...) * @comp_type: Compression type being used (IH_COMP_...) * @is_xip: true if the load address matches the image start */ static void print_decomp_msg(int comp_type, int type, bool is_xip) |
40e5975f9 bootm: Move compr... |
294 |
{ |
8fd6a4b51 bootm: Use print_... |
295 296 297 298 299 300 |
const char *name = genimg_get_type_name(type); if (comp_type == IH_COMP_NONE) printf(" %s %s ... ", is_xip ? "XIP" : "Loading", name); else printf(" Uncompressing %s ... ", name); |
40e5975f9 bootm: Move compr... |
301 |
} |
3086c055a bootm: Factor out... |
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
/** * handle_decomp_error() - display a decompression error * * This function tries to produce a useful message. In the case where the * uncompressed size is the same as the available space, we can assume that * the image is too large for the buffer. * * @comp_type: Compression type being used (IH_COMP_...) * @uncomp_size: Number of bytes uncompressed * @unc_len: Amount of space available for decompression * @ret: Error code to report * @return BOOTM_ERR_RESET, indicating that the board must be reset */ static int handle_decomp_error(int comp_type, size_t uncomp_size, size_t unc_len, int ret) |
40e5975f9 bootm: Move compr... |
317 |
{ |
3086c055a bootm: Factor out... |
318 319 320 321 322 |
const char *name = genimg_get_comp_name(comp_type); if (uncomp_size >= unc_len) printf("Image too large: increase CONFIG_SYS_BOOTM_LEN "); |
40e5975f9 bootm: Move compr... |
323 |
else |
3086c055a bootm: Factor out... |
324 325 326 327 328 329 330 331 332 333 |
printf("%s: uncompress error %d ", name, ret); /* * The decompression routines are now safe, so will not write beyond * their bounds. Probably it is not necessary to reset, but maintain * the current behaviour for now. */ printf("Must RESET board to recover "); |
40e5975f9 bootm: Move compr... |
334 335 336 337 338 339 |
#ifndef USE_HOSTCC bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); #endif return BOOTM_ERR_RESET; } |
b63964037 bootm: Split out ... |
340 |
|
081cc1974 bootm: Export boo... |
341 342 343 |
int bootm_decomp_image(int comp, ulong load, ulong image_start, int type, void *load_buf, void *image_buf, ulong image_len, uint unc_len, ulong *load_end) |
b63964037 bootm: Split out ... |
344 |
{ |
3086c055a bootm: Factor out... |
345 |
int ret = 0; |
2b164f1ce bootm: Move decom... |
346 |
*load_end = load; |
8fd6a4b51 bootm: Use print_... |
347 |
print_decomp_msg(comp, type, load == image_start); |
3086c055a bootm: Factor out... |
348 349 350 351 352 353 |
/* * Load the image to the right place, decompressing if needed. After * this, image_len will be set to the number of uncompressed bytes * loaded, ret will be non-zero on error. */ |
b63964037 bootm: Split out ... |
354 355 |
switch (comp) { case IH_COMP_NONE: |
3086c055a bootm: Factor out... |
356 357 358 |
if (load == image_start) break; if (image_len <= unc_len) |
b63964037 bootm: Split out ... |
359 |
memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); |
3086c055a bootm: Factor out... |
360 361 |
else ret = 1; |
b63964037 bootm: Split out ... |
362 363 |
break; #ifdef CONFIG_GZIP |
40e5975f9 bootm: Move compr... |
364 |
case IH_COMP_GZIP: { |
40e5975f9 bootm: Move compr... |
365 |
ret = gunzip(load_buf, unc_len, image_buf, &image_len); |
b63964037 bootm: Split out ... |
366 |
break; |
40e5975f9 bootm: Move compr... |
367 |
} |
b63964037 bootm: Split out ... |
368 369 |
#endif /* CONFIG_GZIP */ #ifdef CONFIG_BZIP2 |
40e5975f9 bootm: Move compr... |
370 |
case IH_COMP_BZIP2: { |
3086c055a bootm: Factor out... |
371 |
uint size = unc_len; |
40e5975f9 bootm: Move compr... |
372 |
|
b63964037 bootm: Split out ... |
373 374 375 376 377 |
/* * If we've got less than 4 MB of malloc() space, * use slower decompression algorithm which requires * at most 2300 KB of memory. */ |
3086c055a bootm: Factor out... |
378 |
ret = BZ2_bzBuffToBuffDecompress(load_buf, &size, |
b63964037 bootm: Split out ... |
379 380 |
image_buf, image_len, CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); |
3086c055a bootm: Factor out... |
381 |
image_len = size; |
b63964037 bootm: Split out ... |
382 |
break; |
40e5975f9 bootm: Move compr... |
383 |
} |
b63964037 bootm: Split out ... |
384 385 386 387 |
#endif /* CONFIG_BZIP2 */ #ifdef CONFIG_LZMA case IH_COMP_LZMA: { SizeT lzma_len = unc_len; |
2b164f1ce bootm: Move decom... |
388 |
|
b63964037 bootm: Split out ... |
389 390 |
ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, image_buf, image_len); |
3086c055a bootm: Factor out... |
391 |
image_len = lzma_len; |
b63964037 bootm: Split out ... |
392 393 394 395 396 397 |
break; } #endif /* CONFIG_LZMA */ #ifdef CONFIG_LZO case IH_COMP_LZO: { size_t size = unc_len; |
b63964037 bootm: Split out ... |
398 |
ret = lzop_decompress(image_buf, image_len, load_buf, &size); |
3086c055a bootm: Factor out... |
399 |
image_len = size; |
b63964037 bootm: Split out ... |
400 401 402 |
break; } #endif /* CONFIG_LZO */ |
027b728d4 Add support for L... |
403 404 405 406 407 408 409 410 411 |
#ifdef CONFIG_LZ4 case IH_COMP_LZ4: { size_t size = unc_len; ret = ulz4fn(image_buf, image_len, load_buf, &size); image_len = size; break; } #endif /* CONFIG_LZ4 */ |
b63964037 bootm: Split out ... |
412 413 414 415 416 |
default: printf("Unimplemented compression type %d ", comp); return BOOTM_ERR_UNIMPLEMENTED; } |
3086c055a bootm: Factor out... |
417 418 419 |
if (ret) return handle_decomp_error(comp, image_len, unc_len, ret); *load_end = load + image_len; |
2b164f1ce bootm: Move decom... |
420 421 422 423 424 |
puts("OK "); return 0; } |
ce1400f69 Enhance fit_check... |
425 |
#ifndef USE_HOSTCC |
2b164f1ce bootm: Move decom... |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
static int bootm_load_os(bootm_headers_t *images, unsigned long *load_end, int boot_progress) { image_info_t os = images->os; ulong load = os.load; ulong blob_start = os.start; ulong blob_end = os.end; ulong image_start = os.image_start; ulong image_len = os.image_len; bool no_overlap; void *load_buf, *image_buf; int err; load_buf = map_sysmem(load, 0); image_buf = map_sysmem(os.image_start, image_len); |
081cc1974 bootm: Export boo... |
441 442 443 |
err = bootm_decomp_image(os.comp, load, os.image_start, os.type, load_buf, image_buf, image_len, CONFIG_SYS_BOOTM_LEN, load_end); |
2b164f1ce bootm: Move decom... |
444 445 446 447 |
if (err) { bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return err; } |
b4d956f6b bootm: Align cach... |
448 |
flush_cache(load, ALIGN(*load_end - load, ARCH_DMA_MINALIGN)); |
b63964037 bootm: Split out ... |
449 |
|
b63964037 bootm: Split out ... |
450 451 452 |
debug(" kernel loaded at 0x%08lx, end = 0x%08lx ", load, *load_end); bootstage_mark(BOOTSTAGE_ID_KERNEL_LOADED); |
2b164f1ce bootm: Move decom... |
453 |
no_overlap = (os.comp == IH_COMP_NONE && load == image_start); |
b63964037 bootm: Split out ... |
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 |
if (!no_overlap && (load < blob_end) && (*load_end > blob_start)) { debug("images.os.start = 0x%lX, images.os.end = 0x%lx ", blob_start, blob_end); debug("images.os.load = 0x%lx, load_end = 0x%lx ", load, *load_end); /* Check what type of image this is. */ if (images->legacy_hdr_valid) { if (image_get_type(&images->legacy_hdr_os_copy) == IH_TYPE_MULTI) puts("WARNING: legacy format multi component image overwritten "); return BOOTM_ERR_OVERLAP; } else { puts("ERROR: new format image overwritten - must RESET the board to recover "); bootstage_error(BOOTSTAGE_ID_OVERWRITTEN); return BOOTM_ERR_RESET; } } return 0; } /** * bootm_disable_interrupts() - Disable interrupts in preparation for load/boot * * @return interrupt flag (0 if interrupts were disabled, non-zero if they were * enabled) */ ulong bootm_disable_interrupts(void) { ulong iflag; /* * We have reached the point of no return: we are going to * overwrite all exception vector code, so we cannot easily * recover from any failures any more... */ iflag = disable_interrupts(); #ifdef CONFIG_NETCONSOLE /* Stop the ethernet stack if NetConsole could have left it up */ eth_halt(); |
4917c061a net: avoid eth_un... |
499 |
# ifndef CONFIG_DM_ETH |
b63964037 bootm: Split out ... |
500 |
eth_unregister(eth_get_dev()); |
4917c061a net: avoid eth_un... |
501 |
# endif |
b63964037 bootm: Split out ... |
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 |
#endif #if defined(CONFIG_CMD_USB) /* * turn off USB to prevent the host controller from writing to the * SDRAM while Linux is booting. This could happen (at least for OHCI * controller), because the HCCA (Host Controller Communication Area) * lies within the SDRAM and the host controller writes continously to * this area (as busmaster!). The HccaFrameNumber is for example * updated every 1 ms within the HCCA structure in SDRAM! For more * details see the OpenHCI specification. */ usb_stop(); #endif return iflag; } #if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) #define CONSOLE_ARG "console=" #define CONSOLE_ARG_LEN (sizeof(CONSOLE_ARG) - 1) static void fixup_silent_linux(void) { char *buf; const char *env_val; |
00caae6d4 env: Rename geten... |
528 |
char *cmdline = env_get("bootargs"); |
b63964037 bootm: Split out ... |
529 530 531 532 533 534 535 536 537 |
int want_silent; /* * Only fix cmdline when requested. The environment variable can be: * * no - we never fixup * yes - we always fixup * unset - we rely on the console silent flag */ |
bfebc8c96 env: Rename geten... |
538 |
want_silent = env_get_yesno("silent_linux"); |
b63964037 bootm: Split out ... |
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
if (want_silent == 0) return; else if (want_silent == -1 && !(gd->flags & GD_FLG_SILENT)) return; debug("before silent fix-up: %s ", cmdline); if (cmdline && (cmdline[0] != '\0')) { char *start = strstr(cmdline, CONSOLE_ARG); /* Allocate space for maximum possible new command line */ buf = malloc(strlen(cmdline) + 1 + CONSOLE_ARG_LEN + 1); if (!buf) { debug("%s: out of memory ", __func__); return; } if (start) { char *end = strchr(start, ' '); int num_start_bytes = start - cmdline + CONSOLE_ARG_LEN; strncpy(buf, cmdline, num_start_bytes); if (end) strcpy(buf + num_start_bytes, end); else buf[num_start_bytes] = '\0'; } else { sprintf(buf, "%s %s", cmdline, CONSOLE_ARG); } env_val = buf; } else { buf = NULL; env_val = CONSOLE_ARG; } |
382bee57f env: Rename seten... |
574 |
env_set("bootargs", env_val); |
b63964037 bootm: Split out ... |
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
debug("after silent fix-up: %s ", env_val); free(buf); } #endif /* CONFIG_SILENT_CONSOLE */ /** * Execute selected states of the bootm command. * * Note the arguments to this state must be the first argument, Any 'bootm' * or sub-command arguments must have already been taken. * * Note that if states contains more than one flag it MUST contain * BOOTM_STATE_START, since this handles and consumes the command line args. * * Also note that aside from boot_os_fn functions and bootm_load_os no other * functions we store the return value of in 'ret' may use a negative return * value, without special handling. * * @param cmdtp Pointer to bootm command table entry * @param flag Command flags (CMD_FLAG_...) * @param argc Number of subcommand arguments (0 = no arguments) * @param argv Arguments * @param states Mask containing states to run (BOOTM_STATE_...) * @param images Image header information * @param boot_progress 1 to show boot progress, 0 to not do this * @return 0 if ok, something else on error. Some errors will cause this * function to perform a reboot! If states contains BOOTM_STATE_OS_GO * then the intent is to boot an OS, so this function will not return * unless the image type is standalone. */ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int states, bootm_headers_t *images, int boot_progress) { boot_os_fn *boot_fn; ulong iflag = 0; int ret = 0, need_boot_fn; images->state |= states; /* * Work through the states and see how far we get. We stop on * any error. */ if (states & BOOTM_STATE_START) ret = bootm_start(cmdtp, flag, argc, argv); if (!ret && (states & BOOTM_STATE_FINDOS)) ret = bootm_find_os(cmdtp, flag, argc, argv); |
ba0798406 bootm: fix passin... |
624 |
if (!ret && (states & BOOTM_STATE_FINDOTHER)) |
b63964037 bootm: Split out ... |
625 |
ret = bootm_find_other(cmdtp, flag, argc, argv); |
b63964037 bootm: Split out ... |
626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
/* Load the OS */ if (!ret && (states & BOOTM_STATE_LOADOS)) { ulong load_end; iflag = bootm_disable_interrupts(); ret = bootm_load_os(images, &load_end, 0); if (ret == 0) lmb_reserve(&images->lmb, images->os.load, (load_end - images->os.load)); else if (ret && ret != BOOTM_ERR_OVERLAP) goto err; else if (ret == BOOTM_ERR_OVERLAP) ret = 0; |
b63964037 bootm: Split out ... |
640 641 642 643 644 645 646 647 648 649 |
} /* Relocate the ramdisk */ #ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH if (!ret && (states & BOOTM_STATE_RAMDISK)) { ulong rd_len = images->rd_end - images->rd_start; ret = boot_ramdisk_high(&images->lmb, images->rd_start, rd_len, &images->initrd_start, &images->initrd_end); if (!ret) { |
018f53032 env: Rename commo... |
650 651 |
env_set_hex("initrd_start", images->initrd_start); env_set_hex("initrd_end", images->initrd_end); |
b63964037 bootm: Split out ... |
652 653 654 |
} } #endif |
aa34fbc08 fdt: Allow libfdt... |
655 |
#if IMAGE_ENABLE_OF_LIBFDT && defined(CONFIG_LMB) |
b63964037 bootm: Split out ... |
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 |
if (!ret && (states & BOOTM_STATE_FDT)) { boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr); ret = boot_relocate_fdt(&images->lmb, &images->ft_addr, &images->ft_len); } #endif /* From now on, we need the OS boot function */ if (ret) return ret; boot_fn = bootm_os_get_boot_func(images->os.os); need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE | BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO); if (boot_fn == NULL && need_boot_fn) { if (iflag) enable_interrupts(); printf("ERROR: booting os '%s' (%d) is not supported ", genimg_get_os_name(images->os.os), images->os.os); bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS); return 1; } |
19e8649e5 bootm: fixup sile... |
679 |
|
b63964037 bootm: Split out ... |
680 681 682 683 684 |
/* Call various other states that are not generally used */ if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); |
19e8649e5 bootm: fixup sile... |
685 686 687 688 689 |
if (!ret && (states & BOOTM_STATE_OS_PREP)) { #if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) if (images->os.os == IH_OS_LINUX) fixup_silent_linux(); #endif |
b63964037 bootm: Split out ... |
690 |
ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images); |
19e8649e5 bootm: fixup sile... |
691 |
} |
b63964037 bootm: Split out ... |
692 693 694 695 |
#ifdef CONFIG_TRACE /* Pretend to run the OS, then run a user command */ if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) { |
00caae6d4 env: Rename geten... |
696 |
char *cmd_list = env_get("fakegocmd"); |
b63964037 bootm: Split out ... |
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 |
ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO, images, boot_fn); if (!ret && cmd_list) ret = run_command_list(cmd_list, -1, flag); } #endif /* Check for unsupported subcommand. */ if (ret) { puts("subcommand not supported "); return ret; } /* Now run the OS! We hope this doesn't return */ if (!ret && (states & BOOTM_STATE_OS_GO)) ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO, images, boot_fn); /* Deal with any fallout */ err: if (iflag) enable_interrupts(); if (ret == BOOTM_ERR_UNIMPLEMENTED) bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL); else if (ret == BOOTM_ERR_RESET) do_reset(cmdtp, flag, argc, argv); return ret; } #if defined(CONFIG_IMAGE_FORMAT_LEGACY) /** * image_get_kernel - verify legacy format kernel image * @img_addr: in RAM address of the legacy format image to be verified * @verify: data CRC verification flag * * image_get_kernel() verifies legacy image integrity and returns pointer to * legacy image header if image verification was completed successfully. * * returns: * pointer to a legacy image header if valid image was found * otherwise return NULL */ static image_header_t *image_get_kernel(ulong img_addr, int verify) { image_header_t *hdr = (image_header_t *)img_addr; if (!image_check_magic(hdr)) { puts("Bad Magic Number "); bootstage_error(BOOTSTAGE_ID_CHECK_MAGIC); return NULL; } bootstage_mark(BOOTSTAGE_ID_CHECK_HEADER); if (!image_check_hcrc(hdr)) { puts("Bad Header Checksum "); bootstage_error(BOOTSTAGE_ID_CHECK_HEADER); return NULL; } bootstage_mark(BOOTSTAGE_ID_CHECK_CHECKSUM); image_print_contents(hdr); if (verify) { puts(" Verifying Checksum ... "); if (!image_check_dcrc(hdr)) { printf("Bad Data CRC "); bootstage_error(BOOTSTAGE_ID_CHECK_CHECKSUM); return NULL; } puts("OK "); } bootstage_mark(BOOTSTAGE_ID_CHECK_ARCH); if (!image_check_target_arch(hdr)) { printf("Unsupported Architecture 0x%x ", image_get_arch(hdr)); bootstage_error(BOOTSTAGE_ID_CHECK_ARCH); return NULL; } return hdr; } #endif /** * boot_get_kernel - find kernel image * @os_data: pointer to a ulong variable, will hold os data start address * @os_len: pointer to a ulong variable, will hold os data length * * boot_get_kernel() tries to find a kernel image, verifies its integrity * and locates kernel data. * * returns: * pointer to image header if valid image was found, plus kernel start * address and length, otherwise NULL */ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], bootm_headers_t *images, ulong *os_data, ulong *os_len) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) image_header_t *hdr; #endif ulong img_addr; const void *buf; |
b63964037 bootm: Split out ... |
809 810 |
const char *fit_uname_config = NULL; const char *fit_uname_kernel = NULL; |
73223f0e1 Kconfig: Move CON... |
811 |
#if IMAGE_ENABLE_FIT |
b63964037 bootm: Split out ... |
812 813 |
int os_noffset; #endif |
e6c88a6bb bootm: make sure ... |
814 815 816 |
img_addr = genimg_get_kernel_addr_fit(argc < 1 ? NULL : argv[0], &fit_uname_config, &fit_uname_kernel); |
b63964037 bootm: Split out ... |
817 818 |
bootstage_mark(BOOTSTAGE_ID_CHECK_MAGIC); |
b63964037 bootm: Split out ... |
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 |
/* check image type, for FIT images get FIT kernel node */ *os_data = *os_len = 0; buf = map_sysmem(img_addr, 0); switch (genimg_get_format(buf)) { #if defined(CONFIG_IMAGE_FORMAT_LEGACY) case IMAGE_FORMAT_LEGACY: printf("## Booting kernel from Legacy Image at %08lx ... ", img_addr); hdr = image_get_kernel(img_addr, images->verify); if (!hdr) return NULL; bootstage_mark(BOOTSTAGE_ID_CHECK_IMAGETYPE); /* get os_data and os_len */ switch (image_get_type(hdr)) { case IH_TYPE_KERNEL: case IH_TYPE_KERNEL_NOLOAD: *os_data = image_get_data(hdr); *os_len = image_get_data_size(hdr); break; case IH_TYPE_MULTI: image_multi_getimg(hdr, 0, os_data, os_len); break; case IH_TYPE_STANDALONE: *os_data = image_get_data(hdr); *os_len = image_get_data_size(hdr); break; default: printf("Wrong Image Type for %s command ", cmdtp->name); bootstage_error(BOOTSTAGE_ID_CHECK_IMAGETYPE); return NULL; } /* * copy image header to allow for image overwrites during * kernel decompression. */ memmove(&images->legacy_hdr_os_copy, hdr, sizeof(image_header_t)); /* save pointer to image header */ images->legacy_hdr_os = hdr; images->legacy_hdr_valid = 1; bootstage_mark(BOOTSTAGE_ID_DECOMP_IMAGE); break; #endif |
73223f0e1 Kconfig: Move CON... |
869 |
#if IMAGE_ENABLE_FIT |
b63964037 bootm: Split out ... |
870 |
case IMAGE_FORMAT_FIT: |
126cc8642 image: Remove the... |
871 |
os_noffset = fit_image_load(images, img_addr, |
b63964037 bootm: Split out ... |
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 |
&fit_uname_kernel, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_KERNEL, BOOTSTAGE_ID_FIT_KERNEL_START, FIT_LOAD_IGNORED, os_data, os_len); if (os_noffset < 0) return NULL; images->fit_hdr_os = map_sysmem(img_addr, 0); images->fit_uname_os = fit_uname_kernel; images->fit_uname_cfg = fit_uname_config; images->fit_noffset_os = os_noffset; break; #endif #ifdef CONFIG_ANDROID_BOOT_IMAGE case IMAGE_FORMAT_ANDROID: printf("## Booting Android Image at 0x%08lx ... ", img_addr); |
07c0cd713 bootm: Support an... |
889 |
if (android_image_get_kernel(buf, images->verify, |
b63964037 bootm: Split out ... |
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 |
os_data, os_len)) return NULL; break; #endif default: printf("Wrong Image Format for %s command ", cmdtp->name); bootstage_error(BOOTSTAGE_ID_FIT_KERNEL_INFO); return NULL; } debug(" kernel data at 0x%08lx, len = 0x%08lx (%ld) ", *os_data, *os_len, *os_len); return buf; } |
ce1400f69 Enhance fit_check... |
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 |
#else /* USE_HOSTCC */ void memmove_wd(void *to, void *from, size_t len, ulong chunksz) { memmove(to, from, len); } static int bootm_host_load_image(const void *fit, int req_image_type) { const char *fit_uname_config = NULL; ulong data, len; bootm_headers_t images; int noffset; ulong load_end; uint8_t image_type; uint8_t imape_comp; void *load_buf; int ret; memset(&images, '\0', sizeof(images)); images.verify = 1; noffset = fit_image_load(&images, (ulong)fit, NULL, &fit_uname_config, IH_ARCH_DEFAULT, req_image_type, -1, FIT_LOAD_IGNORED, &data, &len); if (noffset < 0) return noffset; if (fit_image_get_type(fit, noffset, &image_type)) { puts("Can't get image type! "); return -EINVAL; } if (fit_image_get_comp(fit, noffset, &imape_comp)) { puts("Can't get image compression! "); return -EINVAL; } /* Allow the image to expand by a factor of 4, should be safe */ load_buf = malloc((1 << 20) + len * 4); |
081cc1974 bootm: Export boo... |
948 949 950 |
ret = bootm_decomp_image(imape_comp, 0, data, image_type, load_buf, (void *)data, len, CONFIG_SYS_BOOTM_LEN, &load_end); |
ce1400f69 Enhance fit_check... |
951 |
free(load_buf); |
081cc1974 bootm: Export boo... |
952 |
|
ce1400f69 Enhance fit_check... |
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 |
if (ret && ret != BOOTM_ERR_UNIMPLEMENTED) return ret; return 0; } int bootm_host_load_images(const void *fit, int cfg_noffset) { static uint8_t image_types[] = { IH_TYPE_KERNEL, IH_TYPE_FLATDT, IH_TYPE_RAMDISK, }; int err = 0; int i; for (i = 0; i < ARRAY_SIZE(image_types); i++) { int ret; ret = bootm_host_load_image(fit, image_types[i]); if (!err && ret && ret != -ENOENT) err = ret; } /* Return the first error we found */ return err; } |
ea51a6282 Allow compiling c... |
980 981 |
#endif /* ndef USE_HOSTCC */ |