diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 162 | ||||
-rw-r--r-- | common/autoboot.c | 121 | ||||
-rw-r--r-- | common/board_r.c | 4 | ||||
-rw-r--r-- | common/bootm.c | 150 | ||||
-rw-r--r-- | common/edid.c | 26 | ||||
-rw-r--r-- | common/image-fit.c | 143 | ||||
-rw-r--r-- | common/image.c | 111 | ||||
-rw-r--r-- | common/main.c | 5 |
8 files changed, 478 insertions, 244 deletions
diff --git a/common/Kconfig b/common/Kconfig index b556b59e9f0..28d5e9a0ccf 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -125,6 +125,168 @@ config BOOTSTAGE_STASH_SIZE This should be large enough to hold the bootstage stash. A value of 4096 (4KiB) is normally plenty. +config SHOW_BOOT_PROGRESS + bool "Show boot progress in a board-specific manner" + help + Defining this option allows to add some board-specific code (calling + a user-provided function show_boot_progress(int) that enables you to + show the system's boot progress on some display (for example, some + LEDs) on your board. At the moment, the following checkpoints are + implemented: + + Legacy uImage format: + + Arg Where When + 1 common/cmd_bootm.c before attempting to boot an image + -1 common/cmd_bootm.c Image header has bad magic number + 2 common/cmd_bootm.c Image header has correct magic number + -2 common/cmd_bootm.c Image header has bad checksum + 3 common/cmd_bootm.c Image header has correct checksum + -3 common/cmd_bootm.c Image data has bad checksum + 4 common/cmd_bootm.c Image data has correct checksum + -4 common/cmd_bootm.c Image is for unsupported architecture + 5 common/cmd_bootm.c Architecture check OK + -5 common/cmd_bootm.c Wrong Image Type (not kernel, multi) + 6 common/cmd_bootm.c Image Type check OK + -6 common/cmd_bootm.c gunzip uncompression error + -7 common/cmd_bootm.c Unimplemented compression type + 7 common/cmd_bootm.c Uncompression OK + 8 common/cmd_bootm.c No uncompress/copy overwrite error + -9 common/cmd_bootm.c Unsupported OS (not Linux, BSD, VxWorks, QNX) + + 9 common/image.c Start initial ramdisk verification + -10 common/image.c Ramdisk header has bad magic number + -11 common/image.c Ramdisk header has bad checksum + 10 common/image.c Ramdisk header is OK + -12 common/image.c Ramdisk data has bad checksum + 11 common/image.c Ramdisk data has correct checksum + 12 common/image.c Ramdisk verification complete, start loading + -13 common/image.c Wrong Image Type (not PPC Linux ramdisk) + 13 common/image.c Start multifile image verification + 14 common/image.c No initial ramdisk, no multifile, continue. + + 15 arch/<arch>/lib/bootm.c All preparation done, transferring control to OS + + -30 arch/powerpc/lib/board.c Fatal error, hang the system + -31 post/post.c POST test failed, detected by post_output_backlog() + -32 post/post.c POST test failed, detected by post_run_single() + + 34 common/cmd_doc.c before loading a Image from a DOC device + -35 common/cmd_doc.c Bad usage of "doc" command + 35 common/cmd_doc.c correct usage of "doc" command + -36 common/cmd_doc.c No boot device + 36 common/cmd_doc.c correct boot device + -37 common/cmd_doc.c Unknown Chip ID on boot device + 37 common/cmd_doc.c correct chip ID found, device available + -38 common/cmd_doc.c Read Error on boot device + 38 common/cmd_doc.c reading Image header from DOC device OK + -39 common/cmd_doc.c Image header has bad magic number + 39 common/cmd_doc.c Image header has correct magic number + -40 common/cmd_doc.c Error reading Image from DOC device + 40 common/cmd_doc.c Image header has correct magic number + 41 common/cmd_ide.c before loading a Image from a IDE device + -42 common/cmd_ide.c Bad usage of "ide" command + 42 common/cmd_ide.c correct usage of "ide" command + -43 common/cmd_ide.c No boot device + 43 common/cmd_ide.c boot device found + -44 common/cmd_ide.c Device not available + 44 common/cmd_ide.c Device available + -45 common/cmd_ide.c wrong partition selected + 45 common/cmd_ide.c partition selected + -46 common/cmd_ide.c Unknown partition table + 46 common/cmd_ide.c valid partition table found + -47 common/cmd_ide.c Invalid partition type + 47 common/cmd_ide.c correct partition type + -48 common/cmd_ide.c Error reading Image Header on boot device + 48 common/cmd_ide.c reading Image Header from IDE device OK + -49 common/cmd_ide.c Image header has bad magic number + 49 common/cmd_ide.c Image header has correct magic number + -50 common/cmd_ide.c Image header has bad checksum + 50 common/cmd_ide.c Image header has correct checksum + -51 common/cmd_ide.c Error reading Image from IDE device + 51 common/cmd_ide.c reading Image from IDE device OK + 52 common/cmd_nand.c before loading a Image from a NAND device + -53 common/cmd_nand.c Bad usage of "nand" command + 53 common/cmd_nand.c correct usage of "nand" command + -54 common/cmd_nand.c No boot device + 54 common/cmd_nand.c boot device found + -55 common/cmd_nand.c Unknown Chip ID on boot device + 55 common/cmd_nand.c correct chip ID found, device available + -56 common/cmd_nand.c Error reading Image Header on boot device + 56 common/cmd_nand.c reading Image Header from NAND device OK + -57 common/cmd_nand.c Image header has bad magic number + 57 common/cmd_nand.c Image header has correct magic number + -58 common/cmd_nand.c Error reading Image from NAND device + 58 common/cmd_nand.c reading Image from NAND device OK + + -60 common/env_common.c Environment has a bad CRC, using default + + 64 net/eth.c starting with Ethernet configuration. + -64 net/eth.c no Ethernet found. + 65 net/eth.c Ethernet found. + + -80 common/cmd_net.c usage wrong + 80 common/cmd_net.c before calling net_loop() + -81 common/cmd_net.c some error in net_loop() occurred + 81 common/cmd_net.c net_loop() back without error + -82 common/cmd_net.c size == 0 (File with size 0 loaded) + 82 common/cmd_net.c trying automatic boot + 83 common/cmd_net.c running "source" command + -83 common/cmd_net.c some error in automatic boot or "source" command + 84 common/cmd_net.c end without errors + + FIT uImage format: + + Arg Where When + 100 common/cmd_bootm.c Kernel FIT Image has correct format + -100 common/cmd_bootm.c Kernel FIT Image has incorrect format + 101 common/cmd_bootm.c No Kernel subimage unit name, using configuration + -101 common/cmd_bootm.c Can't get configuration for kernel subimage + 102 common/cmd_bootm.c Kernel unit name specified + -103 common/cmd_bootm.c Can't get kernel subimage node offset + 103 common/cmd_bootm.c Found configuration node + 104 common/cmd_bootm.c Got kernel subimage node offset + -104 common/cmd_bootm.c Kernel subimage hash verification failed + 105 common/cmd_bootm.c Kernel subimage hash verification OK + -105 common/cmd_bootm.c Kernel subimage is for unsupported architecture + 106 common/cmd_bootm.c Architecture check OK + -106 common/cmd_bootm.c Kernel subimage has wrong type + 107 common/cmd_bootm.c Kernel subimage type OK + -107 common/cmd_bootm.c Can't get kernel subimage data/size + 108 common/cmd_bootm.c Got kernel subimage data/size + -108 common/cmd_bootm.c Wrong image type (not legacy, FIT) + -109 common/cmd_bootm.c Can't get kernel subimage type + -110 common/cmd_bootm.c Can't get kernel subimage comp + -111 common/cmd_bootm.c Can't get kernel subimage os + -112 common/cmd_bootm.c Can't get kernel subimage load address + -113 common/cmd_bootm.c Image uncompress/copy overwrite error + + 120 common/image.c Start initial ramdisk verification + -120 common/image.c Ramdisk FIT image has incorrect format + 121 common/image.c Ramdisk FIT image has correct format + 122 common/image.c No ramdisk subimage unit name, using configuration + -122 common/image.c Can't get configuration for ramdisk subimage + 123 common/image.c Ramdisk unit name specified + -124 common/image.c Can't get ramdisk subimage node offset + 125 common/image.c Got ramdisk subimage node offset + -125 common/image.c Ramdisk subimage hash verification failed + 126 common/image.c Ramdisk subimage hash verification OK + -126 common/image.c Ramdisk subimage for unsupported architecture + 127 common/image.c Architecture check OK + -127 common/image.c Can't get ramdisk subimage data/size + 128 common/image.c Got ramdisk subimage data/size + 129 common/image.c Can't get ramdisk load address + -129 common/image.c Got ramdisk load address + + -130 common/cmd_doc.c Incorrect FIT image format + 131 common/cmd_doc.c FIT image format OK + + -140 common/cmd_ide.c Incorrect FIT image format + 141 common/cmd_ide.c FIT image format OK + + -150 common/cmd_nand.c Incorrect FIT image format + 151 common/cmd_nand.c FIT image format OK + endmenu menu "Boot media" diff --git a/common/autoboot.c b/common/autoboot.c index 94133eaeda7..42fbd7614a8 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -10,6 +10,7 @@ #include <cli.h> #include <console.h> #include <fdtdec.h> +#include <hash.h> #include <menu.h> #include <post.h> #include <u-boot/sha256.h> @@ -27,9 +28,19 @@ DECLARE_GLOBAL_DATA_PTR; /* Stored value of bootdelay, used by autoboot_command() */ static int stored_bootdelay; +static int menukey; + +#ifdef CONFIG_AUTOBOOT_ENCRYPTION +#define AUTOBOOT_STOP_STR_SHA256 CONFIG_AUTOBOOT_STOP_STR_SHA256 +#else +#define AUTOBOOT_STOP_STR_SHA256 "" +#endif -#if defined(CONFIG_AUTOBOOT_KEYED) -#if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256) +#ifdef CONFIG_USE_AUTOBOOT_MENUKEY +#define AUTOBOOT_MENUKEY CONFIG_USE_AUTOBOOT_MENUKEY +#else +#define AUTOBOOT_MENUKEY 0 +#endif /* * Use a "constant-length" time compare function for this @@ -48,7 +59,15 @@ static int slow_equals(u8 *a, u8 *b, int len) return diff == 0; } -static int passwd_abort(uint64_t etime) +/** + * passwd_abort_sha256() - check for a hashed key sequence to abort booting + * + * This checks for the user entering a SHA256 hash within a given time. + * + * @etime: Timeout value ticks (stop when get_ticks() reachs this) + * @return 0 if autoboot should continue, 1 if it should stop + */ +static int passwd_abort_sha256(uint64_t etime) { const char *sha_env_str = env_get("bootstopkeysha256"); u8 sha_env[SHA256_SUM_LEN]; @@ -61,7 +80,7 @@ static int passwd_abort(uint64_t etime) int ret; if (sha_env_str == NULL) - sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256; + sha_env_str = AUTOBOOT_STOP_STR_SHA256; /* * Generate the binary value from the environment hash value @@ -99,8 +118,16 @@ static int passwd_abort(uint64_t etime) return abort; } -#else -static int passwd_abort(uint64_t etime) + +/** + * passwd_abort_key() - check for a key sequence to aborted booting + * + * This checks for the user entering a string within a given time. + * + * @etime: Timeout value ticks (stop when get_ticks() reachs this) + * @return 0 if autoboot should continue, 1 if it should stop + */ +static int passwd_abort_key(uint64_t etime) { int abort = 0; struct { @@ -176,13 +203,12 @@ static int passwd_abort(uint64_t etime) return abort; } -#endif /*************************************************************************** * Watch for 'delay' seconds for autoboot stop or autoboot delay string. * returns: 0 - no key string, allow autoboot 1 - got key string, abort */ -static int __abortboot(int bootdelay) +static int abortboot_key_sequence(int bootdelay) { int abort; uint64_t etime = endtick(bootdelay); @@ -195,29 +221,22 @@ static int __abortboot(int bootdelay) printf(CONFIG_AUTOBOOT_PROMPT, bootdelay); # endif - abort = passwd_abort(etime); + if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION)) + abort = passwd_abort_sha256(etime); + else + abort = passwd_abort_key(etime); if (!abort) debug_bootkeys("key timeout\n"); return abort; } -# else /* !defined(CONFIG_AUTOBOOT_KEYED) */ - -#ifdef CONFIG_MENUKEY -static int menukey; -#endif - -static int __abortboot(int bootdelay) +static int abortboot_single_key(int bootdelay) { int abort = 0; unsigned long ts; -#ifdef CONFIG_MENUPROMPT - printf(CONFIG_MENUPROMPT); -#else printf("Hit any key to stop autoboot: %2d ", bootdelay); -#endif /* * Check if key already pressed @@ -234,13 +253,13 @@ static int __abortboot(int bootdelay) ts = get_timer(0); do { if (tstc()) { /* we got a key press */ + int key; + abort = 1; /* don't auto boot */ bootdelay = 0; /* no more delay */ -# ifdef CONFIG_MENUKEY - menukey = getc(); -# else - (void) getc(); /* consume input */ -# endif + key = getc(); /* consume input */ + if (IS_ENABLED(CONFIG_USE_AUTOBOOT_MENUKEY)) + menukey = key; break; } udelay(10000); @@ -253,26 +272,27 @@ static int __abortboot(int bootdelay) return abort; } -# endif /* CONFIG_AUTOBOOT_KEYED */ static int abortboot(int bootdelay) { int abort = 0; - if (bootdelay >= 0) - abort = __abortboot(bootdelay); + if (bootdelay >= 0) { + if (IS_ENABLED(CONFIG_AUTOBOOT_KEYED)) + abort = abortboot_key_sequence(bootdelay); + else + abort = abortboot_single_key(bootdelay); + } -#ifdef CONFIG_SILENT_CONSOLE - if (abort) + if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && abort) gd->flags &= ~GD_FLG_SILENT; -#endif return abort; } static void process_fdt_options(const void *blob) { -#if defined(CONFIG_OF_CONTROL) && defined(CONFIG_SYS_TEXT_BASE) +#ifdef CONFIG_SYS_TEXT_BASE ulong addr; /* Add an env variable to point to a kernel payload, if available */ @@ -284,7 +304,7 @@ static void process_fdt_options(const void *blob) addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0); if (addr) env_set_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); -#endif /* CONFIG_OF_CONTROL && CONFIG_SYS_TEXT_BASE */ +#endif /* CONFIG_SYS_TEXT_BASE */ } const char *bootdelay_process(void) @@ -297,16 +317,14 @@ const char *bootdelay_process(void) s = env_get("bootdelay"); bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; -#ifdef CONFIG_OF_CONTROL - bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", - bootdelay); -#endif + if (IS_ENABLED(CONFIG_OF_CONTROL)) + bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", + bootdelay); debug("### main_loop entered: bootdelay=%d\n\n", bootdelay); -#if defined(CONFIG_MENU_SHOW) - bootdelay = menu_show(bootdelay); -#endif + if (IS_ENABLED(CONFIG_AUTOBOOT_MENU_SHOW)) + bootdelay = menu_show(bootdelay); bootretry_init_cmd_timeout(); #ifdef CONFIG_POST @@ -319,7 +337,8 @@ const char *bootdelay_process(void) else s = env_get("bootcmd"); - process_fdt_options(gd->fdt_blob); + if (IS_ENABLED(CONFIG_OF_CONTROL)) + process_fdt_options(gd->fdt_blob); stored_bootdelay = bootdelay; return s; @@ -330,22 +349,24 @@ void autoboot_command(const char *s) debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) { -#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) - int prev = disable_ctrlc(1); /* disable Control C checking */ -#endif + bool lock; + int prev; + + lock = IS_ENABLED(CONFIG_AUTOBOOT_KEYED) && + !IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC); + if (lock) + prev = disable_ctrlc(1); /* disable Ctrl-C checking */ run_command_list(s, -1, 0); -#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) - disable_ctrlc(prev); /* restore Control C checking */ -#endif + if (lock) + disable_ctrlc(prev); /* restore Ctrl-C checking */ } -#ifdef CONFIG_MENUKEY - if (menukey == CONFIG_MENUKEY) { + if (IS_ENABLED(CONFIG_USE_AUTOBOOT_MENUKEY) && + menukey == AUTOBOOT_MENUKEY) { s = env_get("menucmd"); if (s) run_command_list(s, -1, 0); } -#endif /* CONFIG_MENUKEY */ } diff --git a/common/board_r.c b/common/board_r.c index ee4dcedd5fa..84aec7fc71c 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -49,7 +49,7 @@ #include <linux/err.h> #include <efi_loader.h> #include <wdt.h> -#if defined(CONFIG_DM_GPIO_HOG) +#if defined(CONFIG_GPIO_HOG) #include <asm/gpio.h> #endif @@ -799,7 +799,7 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_CMD_NET initr_ethaddr, #endif -#if defined(CONFIG_DM_GPIO_HOG) +#if defined(CONFIG_GPIO_HOG) gpio_hog_probe_all, #endif #ifdef CONFIG_BOARD_LATE_INIT diff --git a/common/bootm.c b/common/bootm.c index bea516025fd..4629cdd82d4 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -7,17 +7,12 @@ #ifndef USE_HOSTCC #include <common.h> #include <bootstage.h> -#include <bzlib.h> #include <errno.h> #include <fdt_support.h> #include <lmb.h> #include <malloc.h> #include <mapmem.h> #include <asm/io.h> -#include <linux/lzo.h> -#include <lzma/LzmaTypes.h> -#include <lzma/LzmaDec.h> -#include <lzma/LzmaTools.h> #if defined(CONFIG_CMD_USB) #include <usb.h> #endif @@ -299,23 +294,7 @@ static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc, } #endif /* USE_HOSTC */ -/** - * 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) -{ - 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); -} - +#if !defined(USE_HOSTCC) || defined(CONFIG_FIT_SIGNATURE) /** * handle_decomp_error() - display a decompression error * @@ -325,16 +304,18 @@ static void print_decomp_msg(int comp_type, int type, bool is_xip) * * @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 + * @ret: errno error code received from compression library + * @return Appropriate BOOTM_ERR_ error code */ -static int handle_decomp_error(int comp_type, size_t uncomp_size, - size_t unc_len, int ret) +static int handle_decomp_error(int comp_type, size_t uncomp_size, int ret) { const char *name = genimg_get_comp_name(comp_type); - if (uncomp_size >= unc_len) + /* ENOSYS means unimplemented compression type, don't reset. */ + if (ret == -ENOSYS) + return BOOTM_ERR_UNIMPLEMENTED; + + if (uncomp_size >= CONFIG_SYS_BOOTM_LEN) printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n"); else printf("%s: uncompress error %d\n", name, ret); @@ -351,93 +332,7 @@ static int handle_decomp_error(int comp_type, size_t uncomp_size, return BOOTM_ERR_RESET; } - -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) -{ - int ret = 0; - - *load_end = load; - print_decomp_msg(comp, type, load == image_start); - - /* - * 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. - */ - switch (comp) { - case IH_COMP_NONE: - if (load == image_start) - break; - if (image_len <= unc_len) - memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); - else - ret = 1; - break; -#ifdef CONFIG_GZIP - case IH_COMP_GZIP: { - ret = gunzip(load_buf, unc_len, image_buf, &image_len); - break; - } -#endif /* CONFIG_GZIP */ -#ifdef CONFIG_BZIP2 - case IH_COMP_BZIP2: { - uint size = unc_len; - - /* - * If we've got less than 4 MB of malloc() space, - * use slower decompression algorithm which requires - * at most 2300 KB of memory. - */ - ret = BZ2_bzBuffToBuffDecompress(load_buf, &size, - image_buf, image_len, - CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); - image_len = size; - break; - } -#endif /* CONFIG_BZIP2 */ -#ifdef CONFIG_LZMA - case IH_COMP_LZMA: { - SizeT lzma_len = unc_len; - - ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, - image_buf, image_len); - image_len = lzma_len; - break; - } -#endif /* CONFIG_LZMA */ -#ifdef CONFIG_LZO - case IH_COMP_LZO: { - size_t size = unc_len; - - ret = lzop_decompress(image_buf, image_len, load_buf, &size); - image_len = size; - break; - } -#endif /* CONFIG_LZO */ -#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 */ - default: - printf("Unimplemented compression type %d\n", comp); - return BOOTM_ERR_UNIMPLEMENTED; - } - - if (ret) - return handle_decomp_error(comp, image_len, unc_len, ret); - *load_end = load + image_len; - - puts("OK\n"); - - return 0; -} +#endif #ifndef USE_HOSTCC static int bootm_load_os(bootm_headers_t *images, int boot_progress) @@ -456,10 +351,11 @@ static int bootm_load_os(bootm_headers_t *images, int boot_progress) load_buf = map_sysmem(load, 0); image_buf = map_sysmem(os.image_start, image_len); - err = bootm_decomp_image(os.comp, load, os.image_start, os.type, - load_buf, image_buf, image_len, - CONFIG_SYS_BOOTM_LEN, &load_end); + err = image_decomp(os.comp, load, os.image_start, os.type, + load_buf, image_buf, image_len, + CONFIG_SYS_BOOTM_LEN, &load_end); if (err) { + err = handle_decomp_error(os.comp, load_end - load, err); bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); return err; } @@ -919,11 +815,6 @@ void __weak switch_to_non_secure_mode(void) #else /* USE_HOSTCC */ -void memmove_wd(void *to, void *from, size_t len, ulong chunksz) -{ - memmove(to, from, len); -} - #if defined(CONFIG_FIT_SIGNATURE) static int bootm_host_load_image(const void *fit, int req_image_type) { @@ -957,13 +848,16 @@ static int bootm_host_load_image(const void *fit, int req_image_type) /* Allow the image to expand by a factor of 4, should be safe */ load_buf = malloc((1 << 20) + len * 4); - ret = bootm_decomp_image(imape_comp, 0, data, image_type, load_buf, - (void *)data, len, CONFIG_SYS_BOOTM_LEN, - &load_end); + ret = image_decomp(imape_comp, 0, data, image_type, load_buf, + (void *)data, len, CONFIG_SYS_BOOTM_LEN, + &load_end); free(load_buf); - if (ret && ret != BOOTM_ERR_UNIMPLEMENTED) - return ret; + if (ret) { + ret = handle_decomp_error(imape_comp, load_end - 0, ret); + if (ret != BOOTM_ERR_UNIMPLEMENTED) + return ret; + } return 0; } diff --git a/common/edid.c b/common/edid.c index 90d1167f6ee..f99f42dc406 100644 --- a/common/edid.c +++ b/common/edid.c @@ -168,8 +168,12 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info) return false; } -int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, - int *panel_bits_per_colourp) +int edid_get_timing_validate(u8 *buf, int buf_size, + struct display_timing *timing, + int *panel_bits_per_colourp, + bool (*mode_valid)(void *priv, + const struct display_timing *timing), + void *mode_valid_priv) { struct edid1_info *edid = (struct edid1_info *)buf; bool timing_done; @@ -193,8 +197,14 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, desc = &edid->monitor_details.descriptor[i]; if (desc->zero_flag_1 != 0) { decode_timing((u8 *)desc, timing); - timing_done = true; - break; + if (mode_valid) + timing_done = mode_valid(mode_valid_priv, + timing); + else + timing_done = true; + + if (timing_done) + break; } } if (!timing_done) @@ -225,6 +235,14 @@ int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, return 0; } +int edid_get_timing(u8 *buf, int buf_size, struct display_timing *timing, + int *panel_bits_per_colourp) +{ + return edid_get_timing_validate(buf, buf_size, timing, + panel_bits_per_colourp, NULL, NULL); +} + + /** * Snip the tailing whitespace/return of a string. * diff --git a/common/image-fit.c b/common/image-fit.c index a74b44f2982..e346fed550e 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -22,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ +#include <bootm.h> #include <image.h> #include <bootstage.h> #include <u-boot/crc.h> @@ -1521,6 +1522,10 @@ int fit_check_format(const void *fit) * compatible list, "foo,bar", matches a compatible string in the root of fdt1. * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1. * + * As an optimization, the compatible property from the FDT's root node can be + * copied into the configuration node in the FIT image. This is required to + * match configurations with compressed FDTs. + * * returns: * offset to the configuration to use if one was found * -1 otherwise @@ -1553,48 +1558,62 @@ int fit_conf_find_compat(const void *fit, const void *fdt) for (noffset = fdt_next_node(fit, confs_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { - const void *kfdt; + const void *fdt; const char *kfdt_name; - int kfdt_noffset; + int kfdt_noffset, compat_noffset; const char *cur_fdt_compat; int len; - size_t size; + size_t sz; int i; if (ndepth > 1) continue; - kfdt_name = fdt_getprop(fit, noffset, "fdt", &len); - if (!kfdt_name) { - debug("No fdt property found.\n"); - continue; - } - kfdt_noffset = fdt_subnode_offset(fit, images_noffset, - kfdt_name); - if (kfdt_noffset < 0) { - debug("No image node named \"%s\" found.\n", - kfdt_name); - continue; - } - /* - * Get a pointer to this configuration's fdt. - */ - if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) { - debug("Failed to get fdt \"%s\".\n", kfdt_name); - continue; + /* If there's a compat property in the config node, use that. */ + if (fdt_getprop(fit, noffset, "compatible", NULL)) { + fdt = fit; /* search in FIT image */ + compat_noffset = noffset; /* search under config node */ + } else { /* Otherwise extract it from the kernel FDT. */ + kfdt_name = fdt_getprop(fit, noffset, "fdt", &len); + if (!kfdt_name) { + debug("No fdt property found.\n"); + continue; + } + kfdt_noffset = fdt_subnode_offset(fit, images_noffset, + kfdt_name); + if (kfdt_noffset < 0) { + debug("No image node named \"%s\" found.\n", + kfdt_name); + continue; + } + + if (!fit_image_check_comp(fit, kfdt_noffset, + IH_COMP_NONE)) { + debug("Can't extract compat from \"%s\" " + "(compressed)\n", kfdt_name); + continue; + } + + /* search in this config's kernel FDT */ + if (fit_image_get_data(fit, kfdt_noffset, &fdt, &sz)) { + debug("Failed to get fdt \"%s\".\n", kfdt_name); + continue; + } + + compat_noffset = 0; /* search kFDT under root node */ } len = fdt_compat_len; cur_fdt_compat = fdt_compat; /* * Look for a match for each U-Boot compatibility string in - * turn in this configuration's fdt. + * turn in the compat string property. */ for (i = 0; len > 0 && (!best_match_offset || best_match_pos > i); i++) { int cur_len = strlen(cur_fdt_compat) + 1; - if (!fdt_node_check_compatible(kfdt, 0, + if (!fdt_node_check_compatible(fdt, compat_noffset, cur_fdt_compat)) { best_match_offset = noffset; best_match_pos = i; @@ -1795,11 +1814,12 @@ int fit_image_load(bootm_headers_t *images, ulong addr, const char *fit_uname_config; const char *fit_base_uname_config; const void *fit; - const void *buf; + void *buf; + void *loadbuf; size_t size; int type_ok, os_ok; - ulong load, data, len; - uint8_t os; + ulong load, load_end, data, len; + uint8_t os, comp; #ifndef USE_HOSTCC uint8_t os_arch; #endif @@ -1895,12 +1915,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr, images->os.arch = os_arch; #endif - if (image_type == IH_TYPE_FLATDT && - !fit_image_check_comp(fit, noffset, IH_COMP_NONE)) { - puts("FDT image is compressed"); - return -EPROTONOSUPPORT; - } - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL); type_ok = fit_image_check_type(fit, noffset, image_type) || fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE) || @@ -1931,7 +1945,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, bootstage_mark(bootstage_id + BOOTSTAGE_SUB_CHECK_ALL_OK); /* get image data address and length */ - if (fit_image_get_data_and_size(fit, noffset, &buf, &size)) { + if (fit_image_get_data_and_size(fit, noffset, + (const void **)&buf, &size)) { printf("Could not find %s subimage data!\n", prop_name); bootstage_error(bootstage_id + BOOTSTAGE_SUB_GET_DATA); return -ENOENT; @@ -1939,30 +1954,15 @@ int fit_image_load(bootm_headers_t *images, ulong addr, #if !defined(USE_HOSTCC) && defined(CONFIG_FIT_IMAGE_POST_PROCESS) /* perform any post-processing on the image data */ - board_fit_image_post_process((void **)&buf, &size); + board_fit_image_post_process(&buf, &size); #endif len = (ulong)size; - /* verify that image data is a proper FDT blob */ - if (image_type == IH_TYPE_FLATDT && fdt_check_header(buf)) { - puts("Subimage data is not a FDT"); - return -ENOEXEC; - } - bootstage_mark(bootstage_id + BOOTSTAGE_SUB_GET_DATA_OK); - /* - * Work-around for eldk-4.2 which gives this warning if we try to - * cast in the unmap_sysmem() call: - * warning: initialization discards qualifiers from pointer target type - */ - { - void *vbuf = (void *)buf; - - data = map_to_sysmem(vbuf); - } - + data = map_to_sysmem(buf); + load = data; if (load_op == FIT_LOAD_IGNORED) { /* Don't load */ } else if (fit_image_get_load(fit, noffset, &load)) { @@ -1974,8 +1974,6 @@ int fit_image_load(bootm_headers_t *images, ulong addr, } } else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) { ulong image_start, image_end; - ulong load_end; - void *dst; /* * move image data to the load address, @@ -1993,14 +1991,45 @@ int fit_image_load(bootm_headers_t *images, ulong addr, printf(" Loading %s from 0x%08lx to 0x%08lx\n", prop_name, data, load); + } else { + load = data; /* No load address specified */ + } + + comp = IH_COMP_NONE; + loadbuf = buf; + /* Kernel images get decompressed later in bootm_load_os(). */ + if (!(image_type == IH_TYPE_KERNEL || + image_type == IH_TYPE_KERNEL_NOLOAD) && + !fit_image_get_comp(fit, noffset, &comp) && + comp != IH_COMP_NONE) { + ulong max_decomp_len = len * 20; + if (load == data) { + loadbuf = malloc(max_decomp_len); + load = map_to_sysmem(loadbuf); + } else { + loadbuf = map_sysmem(load, max_decomp_len); + } + if (image_decomp(comp, load, data, image_type, + loadbuf, buf, len, max_decomp_len, &load_end)) { + printf("Error decompressing %s\n", prop_name); - dst = map_sysmem(load, len); - memmove(dst, buf, len); - data = load; + return -ENOEXEC; + } + len = load_end - load; + } else if (load != data) { + loadbuf = map_sysmem(load, len); + memcpy(loadbuf, buf, len); } + + /* verify that image data is a proper FDT blob */ + if (image_type == IH_TYPE_FLATDT && fdt_check_header(loadbuf)) { + puts("Subimage data is not a FDT"); + return -ENOEXEC; + } + bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD); - *datap = data; + *datap = load; *lenp = len; if (fit_unamep) *fit_unamep = (char *)fit_uname; diff --git a/common/image.c b/common/image.c index 9f9538fac2f..495883185d4 100644 --- a/common/image.c +++ b/common/image.c @@ -32,6 +32,12 @@ #include <linux/errno.h> #include <asm/io.h> +#include <bzlib.h> +#include <linux/lzo.h> +#include <lzma/LzmaTypes.h> +#include <lzma/LzmaDec.h> +#include <lzma/LzmaTools.h> + #ifdef CONFIG_CMD_BDI extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif @@ -375,6 +381,106 @@ void image_print_contents(const void *ptr) } } +/** + * 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) +{ + const char *name = genimg_get_type_name(type); + + if (comp_type == IH_COMP_NONE) + printf(" %s %s\n", is_xip ? "XIP" : "Loading", name); + else + printf(" Uncompressing %s\n", name); +} + +int image_decomp(int comp, ulong load, ulong image_start, int type, + void *load_buf, void *image_buf, ulong image_len, + uint unc_len, ulong *load_end) +{ + int ret = 0; + + *load_end = load; + print_decomp_msg(comp, type, load == image_start); + + /* + * 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. + */ + switch (comp) { + case IH_COMP_NONE: + if (load == image_start) + break; + if (image_len <= unc_len) + memmove_wd(load_buf, image_buf, image_len, CHUNKSZ); + else + ret = -ENOSPC; + break; +#ifdef CONFIG_GZIP + case IH_COMP_GZIP: { + ret = gunzip(load_buf, unc_len, image_buf, &image_len); + break; + } +#endif /* CONFIG_GZIP */ +#ifdef CONFIG_BZIP2 + case IH_COMP_BZIP2: { + uint size = unc_len; + + /* + * If we've got less than 4 MB of malloc() space, + * use slower decompression algorithm which requires + * at most 2300 KB of memory. + */ + ret = BZ2_bzBuffToBuffDecompress(load_buf, &size, + image_buf, image_len, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); + image_len = size; + break; + } +#endif /* CONFIG_BZIP2 */ +#ifdef CONFIG_LZMA + case IH_COMP_LZMA: { + SizeT lzma_len = unc_len; + + ret = lzmaBuffToBuffDecompress(load_buf, &lzma_len, + image_buf, image_len); + image_len = lzma_len; + break; + } +#endif /* CONFIG_LZMA */ +#ifdef CONFIG_LZO + case IH_COMP_LZO: { + size_t size = unc_len; + + ret = lzop_decompress(image_buf, image_len, load_buf, &size); + image_len = size; + break; + } +#endif /* CONFIG_LZO */ +#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 */ + default: + printf("Unimplemented compression type %d\n", comp); + return -ENOSYS; + } + + *load_end = load + image_len; + + return ret; +} + #ifndef USE_HOSTCC #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) @@ -551,6 +657,11 @@ void memmove_wd(void *to, void *from, size_t len, ulong chunksz) memmove(to, from, len); #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ } +#else /* USE_HOSTCC */ +void memmove_wd(void *to, void *from, size_t len, ulong chunksz) +{ + memmove(to, from, len); +} #endif /* !USE_HOSTCC */ void genimg_print_size(uint32_t size) diff --git a/common/main.c b/common/main.c index 07b34bf2b05..ce39c8d1899 100644 --- a/common/main.c +++ b/common/main.c @@ -19,7 +19,6 @@ __weak void show_boot_progress(int val) {} static void run_preboot_environment_command(void) { -#ifdef CONFIG_PREBOOT char *p; p = env_get("preboot"); @@ -34,7 +33,6 @@ static void run_preboot_environment_command(void) if (IS_ENABLED(CONFIG_AUTOBOOT_KEYED)) disable_ctrlc(prev); /* restore Ctrl-C checking */ } -#endif /* CONFIG_PREBOOT */ } /* We come here after U-Boot is initialised and ready to process commands */ @@ -49,7 +47,8 @@ void main_loop(void) cli_init(); - run_preboot_environment_command(); + if (IS_ENABLED(CONFIG_USE_PREBOOT)) + run_preboot_environment_command(); if (IS_ENABLED(CONFIG_UPDATE_TFTP)) update_tftp(0UL, NULL, NULL); |