X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=common%2Fimage.c;h=60c21270398e649c7bb77a8bd04445769e22d127;hb=664277203c028d2e8fede5a3c30658fb75e6adef;hp=aacae5ac51aab01d3e10499c4e843971f1129000;hpb=7708d8b352e9e595f6f08afd3206af6495c7dc09;p=karo-tx-uboot.git diff --git a/common/image.c b/common/image.c index aacae5ac51..60c2127039 100644 --- a/common/image.c +++ b/common/image.c @@ -43,10 +43,10 @@ #include #endif +#include #include #if defined(CONFIG_FIT) || defined(CONFIG_OF_LIBFDT) -#include #include #include #endif @@ -74,6 +74,8 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, #include #endif /* !USE_HOSTCC*/ +#include + static const table_entry_t uimage_arch[] = { { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, { IH_ARCH_ALPHA, "alpha", "Alpha", }, @@ -94,6 +96,7 @@ static const table_entry_t uimage_arch[] = { { IH_ARCH_BLACKFIN, "blackfin", "Blackfin", }, { IH_ARCH_AVR32, "avr32", "AVR32", }, { IH_ARCH_NDS32, "nds32", "NDS32", }, + { IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",}, { -1, "", "", }, }; @@ -105,6 +108,7 @@ static const table_entry_t uimage_os[] = { #endif { IH_OS_NETBSD, "netbsd", "NetBSD", }, { IH_OS_OSE, "ose", "Enea OSE", }, + { IH_OS_PLAN9, "plan9", "Plan 9", }, { IH_OS_RTEMS, "rtems", "RTEMS", }, { IH_OS_U_BOOT, "u-boot", "U-Boot", }, #if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC) @@ -142,6 +146,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_INVALID, NULL, "Invalid Image", }, { IH_TYPE_MULTI, "multi", "Multi-File Image", }, { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, + { IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, { IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", }, { IH_TYPE_SCRIPT, "script", "Script", }, { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, @@ -158,8 +163,6 @@ static const table_entry_t uimage_comp[] = { { -1, "", "", }, }; -uint32_t crc32(uint32_t, const unsigned char *, uint); -uint32_t crc32_wd(uint32_t, const unsigned char *, uint, uint); #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) static void genimg_print_time(time_t timestamp); #endif @@ -372,37 +375,37 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, if (!image_check_magic(rd_hdr)) { puts("Bad Magic Number\n"); - show_boot_progress(-10); + bootstage_error(BOOTSTAGE_ID_RD_MAGIC); return NULL; } if (!image_check_hcrc(rd_hdr)) { puts("Bad Header Checksum\n"); - show_boot_progress(-11); + bootstage_error(BOOTSTAGE_ID_RD_HDR_CHECKSUM); return NULL; } - show_boot_progress(10); + bootstage_mark(BOOTSTAGE_ID_RD_MAGIC); image_print_contents(rd_hdr); if (verify) { puts(" Verifying Checksum ... "); if (!image_check_dcrc(rd_hdr)) { puts("Bad Data CRC\n"); - show_boot_progress(-12); + bootstage_error(BOOTSTAGE_ID_RD_CHECKSUM); return NULL; } puts("OK\n"); } - show_boot_progress(11); + bootstage_mark(BOOTSTAGE_ID_RD_HDR_CHECKSUM); if (!image_check_os(rd_hdr, IH_OS_LINUX) || !image_check_arch(rd_hdr, arch) || !image_check_type(rd_hdr, IH_TYPE_RAMDISK)) { printf("No Linux %s Ramdisk Image\n", genimg_get_arch_name(arch)); - show_boot_progress(-13); + bootstage_error(BOOTSTAGE_ID_RAMDISK); return NULL; } @@ -414,11 +417,25 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, /* Shared dual-format routines */ /*****************************************************************************/ #ifndef USE_HOSTCC -int getenv_yesno(char *var) +ulong load_addr = CONFIG_SYS_LOAD_ADDR; /* Default Load Address */ +ulong save_addr; /* Default Save Address */ +ulong save_size; /* Default Save Size (in bytes) */ + +static int on_loadaddr(const char *name, const char *value, enum env_op op, + int flags) { - char *s = getenv(var); - return (s && (*s == 'n')) ? 0 : 1; + switch (op) { + case env_op_create: + case env_op_overwrite: + load_addr = simple_strtoul(value, NULL, 16); + break; + default: + break; + } + + return 0; } +U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr); ulong getenv_bootm_low(void) { @@ -796,6 +813,9 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, ulong rd_addr, rd_load; ulong rd_data, rd_len; const image_header_t *rd_hdr; +#ifdef CONFIG_SUPPORT_RAW_INITRD + char *end; +#endif #if defined(CONFIG_FIT) void *fit_hdr; const char *fit_uname_config = NULL; @@ -894,7 +914,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, printf("## Loading init Ramdisk from Legacy " "Image at %08lx ...\n", rd_addr); - show_boot_progress(9); + bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK); rd_hdr = image_get_ramdisk(rd_addr, arch, images->verify); @@ -911,13 +931,14 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, printf("## Loading init Ramdisk from FIT " "Image at %08lx ...\n", rd_addr); - show_boot_progress(120); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT); if (!fit_check_format(fit_hdr)) { puts("Bad FIT ramdisk image format!\n"); - show_boot_progress(-120); + bootstage_error( + BOOTSTAGE_ID_FIT_RD_FORMAT); return 1; } - show_boot_progress(121); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_FORMAT_OK); if (!fit_uname_ramdisk) { /* @@ -925,13 +946,15 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, * node first. If config unit node name is NULL * fit_conf_get_node() will try to find default config node */ - show_boot_progress(122); + bootstage_mark( + BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); cfg_noffset = fit_conf_get_node(fit_hdr, fit_uname_config); if (cfg_noffset < 0) { puts("Could not find configuration " "node\n"); - show_boot_progress(-122); + bootstage_error( + BOOTSTAGE_ID_FIT_RD_NO_UNIT_NAME); return 1; } fit_uname_config = fdt_get_name(fit_hdr, @@ -945,20 +968,21 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, rd_noffset, NULL); } else { /* get ramdisk component image node offset */ - show_boot_progress(123); + bootstage_mark( + BOOTSTAGE_ID_FIT_RD_UNIT_NAME); rd_noffset = fit_image_get_node(fit_hdr, fit_uname_ramdisk); } if (rd_noffset < 0) { puts("Could not find subimage node\n"); - show_boot_progress(-124); + bootstage_error(BOOTSTAGE_ID_FIT_RD_SUBNODE); return 1; } printf(" Trying '%s' ramdisk subimage\n", fit_uname_ramdisk); - show_boot_progress(125); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK); if (!fit_check_ramdisk(fit_hdr, rd_noffset, arch, images->verify)) return 1; @@ -967,10 +991,10 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, if (fit_image_get_data(fit_hdr, rd_noffset, &data, &size)) { puts("Could not find ramdisk subimage data!\n"); - show_boot_progress(-127); + bootstage_error(BOOTSTAGE_ID_FIT_RD_GET_DATA); return 1; } - show_boot_progress(128); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_GET_DATA_OK); rd_data = (ulong)data; rd_len = size; @@ -978,10 +1002,10 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, if (fit_image_get_load(fit_hdr, rd_noffset, &rd_load)) { puts("Can't get ramdisk subimage load " "address!\n"); - show_boot_progress(-129); + bootstage_error(BOOTSTAGE_ID_FIT_RD_LOAD); return 1; } - show_boot_progress(129); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_LOAD); images->fit_hdr_rd = fit_hdr; images->fit_uname_rd = fit_uname_ramdisk; @@ -989,9 +1013,17 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, break; #endif default: - puts("Wrong Ramdisk Image Format\n"); - rd_data = rd_len = rd_load = 0; - return 1; +#ifdef CONFIG_SUPPORT_RAW_INITRD + if (argc >= 3 && (end = strchr(argv[2], ':'))) { + rd_len = simple_strtoul(++end, NULL, 16); + rd_data = rd_addr; + } else +#endif + { + puts("Wrong Ramdisk Image Format\n"); + rd_data = rd_len = rd_load = 0; + return 1; + } } } else if (images->legacy_hdr_valid && image_check_type(&images->legacy_hdr_os_copy, @@ -1001,7 +1033,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, * Now check if we have a legacy mult-component image, * get second entry data start address and len. */ - show_boot_progress(13); + bootstage_mark(BOOTSTAGE_ID_RAMDISK); printf("## Loading init Ramdisk from multi component " "Legacy Image at %08lx ...\n", (ulong)images->legacy_hdr_os); @@ -1011,7 +1043,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images, /* * no initrd image */ - show_boot_progress(14); + bootstage_mark(BOOTSTAGE_ID_NO_RAMDISK); rd_len = rd_data = 0; } @@ -1095,7 +1127,7 @@ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, puts("ramdisk - allocation error\n"); goto error; } - show_boot_progress(12); + bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK); *initrd_end = *initrd_start + rd_len; printf(" Loading Ramdisk to %08lx, end %08lx ... ", @@ -1104,6 +1136,14 @@ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, memmove_wd((void *)*initrd_start, (void *)rd_data, rd_len, CHUNKSZ); +#ifdef CONFIG_MP + /* + * Ensure the image is flushed to memory to handle + * AMP boot scenarios in which we might not be + * HW cache coherent + */ + flush_cache((unsigned long)*initrd_start, rd_len); +#endif puts("OK\n"); } } else { @@ -1254,7 +1294,7 @@ void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob) int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) { void *fdt_blob = *of_flat_tree; - void *of_start = 0; + void *of_start = NULL; char *fdt_high; ulong of_len = 0; int err; @@ -1280,16 +1320,14 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) if (((ulong) desired_addr) == ~0UL) { /* All ones means use fdt in place */ - desired_addr = fdt_blob; + of_start = fdt_blob; + lmb_reserve(lmb, (ulong)of_start, of_len); disable_relocation = 1; - } - if (desired_addr) { + } else if (desired_addr) { of_start = (void *)(ulong) lmb_alloc_base(lmb, of_len, 0x1000, - ((ulong) - desired_addr) - + of_len); - if (desired_addr && of_start != desired_addr) { + (ulong)desired_addr); + if (of_start == NULL) { puts("Failed using fdt_high value for Device Tree"); goto error; } @@ -1304,7 +1342,7 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) + getenv_bootm_low()); } - if (of_start == 0) { + if (of_start == NULL) { puts("device tree - allocation error\n"); goto error; } @@ -1367,7 +1405,7 @@ int boot_get_fdt(int flag, int argc, char * const argv[], const image_header_t *fdt_hdr; ulong fdt_addr; char *fdt_blob = NULL; - ulong image_start, image_end; + ulong image_start, image_data, image_end; ulong load_start, load_end; #if defined(CONFIG_FIT) void *fit_hdr; @@ -1475,21 +1513,28 @@ int boot_get_fdt(int flag, int argc, char * const argv[], * make sure we don't overwrite initial image */ image_start = (ulong)fdt_hdr; + image_data = (ulong)image_get_data(fdt_hdr); image_end = image_get_image_end(fdt_hdr); load_start = image_get_load(fdt_hdr); load_end = load_start + image_get_data_size(fdt_hdr); + if (load_start == image_start || + load_start == image_data) { + fdt_blob = (char *)image_data; + break; + } + if ((load_start < image_end) && (load_end > image_start)) { fdt_error("fdt overwritten"); goto error; } debug(" Loading FDT from 0x%08lx to 0x%08lx\n", - image_get_data(fdt_hdr), load_start); + image_data, load_start); memmove((void *)load_start, - (void *)image_get_data(fdt_hdr), + (void *)image_data, image_get_data_size(fdt_hdr)); fdt_blob = (char *)load_start; @@ -1673,7 +1718,7 @@ int boot_get_fdt(int flag, int argc, char * const argv[], return 0; error: - *of_flat_tree = 0; + *of_flat_tree = NULL; *of_size = 0; return 1; } @@ -1800,7 +1845,7 @@ static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr, * addr and conf_name are set accordingly * 0 otherwise */ -inline int fit_parse_conf(const char *spec, ulong addr_curr, +int fit_parse_conf(const char *spec, ulong addr_curr, ulong *addr, const char **conf_name) { return fit_parse_spec(spec, '#', addr_curr, addr, conf_name); @@ -1826,7 +1871,7 @@ inline int fit_parse_conf(const char *spec, ulong addr_curr, * addr and image_name are set accordingly * 0 otherwise */ -inline int fit_parse_subimage(const char *spec, ulong addr_curr, +int fit_parse_subimage(const char *spec, ulong addr_curr, ulong *addr, const char **image_name) { return fit_parse_spec(spec, ':', addr_curr, addr, image_name); @@ -2013,13 +2058,13 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } - if (type == IH_TYPE_KERNEL) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) { fit_image_get_os(fit, image_noffset, &os); printf("%s OS: %s\n", p, genimg_get_os_name(os)); } if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || - (type == IH_TYPE_FIRMWARE)) { + (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) @@ -2028,7 +2073,8 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); } - if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE)) { + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || + (type == IH_TYPE_RAMDISK)) { fit_image_get_entry(fit, image_noffset, &entry); printf("%s Entry Point: ", p); if (ret) @@ -2465,6 +2511,36 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, return 0; } +#ifndef USE_HOSTCC +/** + * fit_image_hash_get_ignore - get hash ignore flag + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @ignore: pointer to an int, will hold hash ignore flag + * + * fit_image_hash_get_ignore() finds hash ignore property in a given hash node. + * If the property is found and non-zero, the hash algorithm is not verified by + * u-boot automatically. + * + * returns: + * 0, on ignore not found + * value, on ignore found + */ +int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) +{ + int len; + int *value; + + value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len); + if (value == NULL || len != sizeof(int)) + *ignore = 0; + else + *ignore = *value; + + return 0; +} +#endif + /** * fit_set_timestamp - set node timestamp property * @fit: pointer to the FIT format image header @@ -2728,6 +2804,9 @@ int fit_image_check_hashes(const void *fit, int image_noffset) char *algo; uint8_t *fit_value; int fit_value_len; +#ifndef USE_HOSTCC + int ignore; +#endif uint8_t value[FIT_MAX_HASH_LEN]; int value_len; int noffset; @@ -2764,6 +2843,14 @@ int fit_image_check_hashes(const void *fit, int image_noffset) } printf("%s", algo); +#ifndef USE_HOSTCC + fit_image_hash_get_ignore(fit, noffset, &ignore); + if (ignore) { + printf("-skipped "); + continue; + } +#endif + if (fit_image_hash_get_value(fit, noffset, &fit_value, &fit_value_len)) { err_msg = " error!\nCan't get hash value " @@ -2789,6 +2876,11 @@ int fit_image_check_hashes(const void *fit, int image_noffset) } } + if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { + err_msg = " error!\nCorrupted or truncated tree"; + goto error; + } + return 1; error: @@ -2972,6 +3064,133 @@ int fit_check_format(const void *fit) return 1; } + +/** + * fit_conf_find_compat + * @fit: pointer to the FIT format image header + * @fdt: pointer to the device tree to compare against + * + * fit_conf_find_compat() attempts to find the configuration whose fdt is the + * most compatible with the passed in device tree. + * + * Example: + * + * / o image-tree + * |-o images + * | |-o fdt@1 + * | |-o fdt@2 + * | + * |-o configurations + * |-o config@1 + * | |-fdt = fdt@1 + * | + * |-o config@2 + * |-fdt = fdt@2 + * + * / o U-Boot fdt + * |-compatible = "foo,bar", "bim,bam" + * + * / o kernel fdt1 + * |-compatible = "foo,bar", + * + * / o kernel fdt2 + * |-compatible = "bim,bam", "baz,biz" + * + * Configuration 1 would be picked because the first string in U-Boot's + * 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. + * + * returns: + * offset to the configuration to use if one was found + * -1 otherwise + */ +int fit_conf_find_compat(const void *fit, const void *fdt) +{ + int ndepth = 0; + int noffset, confs_noffset, images_noffset; + const void *fdt_compat; + int fdt_compat_len; + int best_match_offset = 0; + int best_match_pos = 0; + + confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); + images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); + if (confs_noffset < 0 || images_noffset < 0) { + debug("Can't find configurations or images nodes.\n"); + return -1; + } + + fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len); + if (!fdt_compat) { + debug("Fdt for comparison has no \"compatible\" property.\n"); + return -1; + } + + /* + * Loop over the configurations in the FIT image. + */ + for (noffset = fdt_next_node(fit, confs_noffset, &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node(fit, noffset, &ndepth)) { + const void *kfdt; + const char *kfdt_name; + int kfdt_noffset; + const char *cur_fdt_compat; + int len; + size_t size; + 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; + } + + 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. + */ + 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, + cur_fdt_compat)) { + best_match_offset = noffset; + best_match_pos = i; + break; + } + len -= cur_len; + cur_fdt_compat += cur_len; + } + } + if (!best_match_offset) { + debug("No match found.\n"); + return -1; + } + + return best_match_offset; +} + /** * fit_conf_get_node - get node offset for configuration of a given unit name * @fit: pointer to the FIT format image header @@ -3162,23 +3381,23 @@ static int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch, puts(" Verifying Hash Integrity ... "); if (!fit_image_check_hashes(fit, rd_noffset)) { puts("Bad Data Hash\n"); - show_boot_progress(-125); + bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH); return 0; } puts("OK\n"); } - show_boot_progress(126); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) || !fit_image_check_arch(fit, rd_noffset, arch) || !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) { printf("No Linux %s Ramdisk Image\n", genimg_get_arch_name(arch)); - show_boot_progress(-126); + bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL); return 0; } - show_boot_progress(127); + bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK); return 1; } #endif /* USE_HOSTCC */