static void image_print_type(const image_header_t *hdr) { const char *os, *arch, *type, *comp; os = genimg_get_os_name(image_get_os(hdr)); arch = genimg_get_arch_name(image_get_arch(hdr)); type = genimg_get_type_name(image_get_type(hdr)); comp = genimg_get_comp_name(image_get_comp(hdr)); printf("%s %s %s (%s)\n", arch, os, type, comp); }
/** * run_bootm_test() - Run tests on the bootm decopmression function * * @comp_type: Compression type to test * @compress: Our function to compress data * @return 0 if OK, non-zero on failure */ static int run_bootm_test(int comp_type, mutate_func compress) { ulong compress_size = 1024; void *compress_buff; int unc_len; int err = 0; const ulong image_start = 0; const ulong load_addr = 0x1000; ulong load_end; printf("Testing: %s\n", genimg_get_comp_name(comp_type)); compress_buff = map_sysmem(image_start, 0); unc_len = strlen(plain); compress((void *)plain, unc_len, compress_buff, compress_size, &compress_size); err = bootm_decomp_image(comp_type, load_addr, image_start, IH_TYPE_KERNEL, map_sysmem(load_addr, 0), compress_buff, compress_size, unc_len, &load_end); if (err) return err; err = bootm_decomp_image(comp_type, load_addr, image_start, IH_TYPE_KERNEL, map_sysmem(load_addr, 0), compress_buff, compress_size, unc_len - 1, &load_end); if (!err) return -EINVAL; /* We can't detect corruption when not decompressing */ if (comp_type == IH_COMP_NONE) return 0; memset(compress_buff + compress_size / 2, '\x49', compress_size / 2); err = bootm_decomp_image(comp_type, load_addr, image_start, IH_TYPE_KERNEL, map_sysmem(load_addr, 0), compress_buff, compress_size, 0x10000, &load_end); if (!err) return -EINVAL; return 0; }
/** * 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) { const char *name = genimg_get_comp_name(comp_type); if (uncomp_size >= unc_len) printf("Image too large: increase CONFIG_SYS_BOOTM_LEN\n"); else printf("%s: uncompress error %d\n", 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\n"); #ifndef USE_HOSTCC bootstage_error(BOOTSTAGE_ID_DECOMP_IMAGE); #endif return BOOTM_ERR_RESET; }
/** * fit_image_print - prints out the FIT component image details * @fit: pointer to the FIT format image header * @image_noffset: offset of the component image node * @p: pointer to prefix string * * fit_image_print() lists all mandatory properies for the processed component * image. If present, hash nodes are printed out as well. Load * address for images of type firmware is also printed out. Since the load * address is not mandatory for firmware images, it will be output as * "unavailable" when not present. * * returns: * no returned results */ void fit_image_print(const void *fit, int image_noffset, const char *p) { char *desc; uint8_t type, arch, os, comp; size_t size; ulong load, entry; const void *data; int noffset; int ndepth; int ret; /* Mandatory properties */ ret = fit_get_desc(fit, image_noffset, &desc); printf("%s Description: ", p); if (ret) printf("unavailable\n"); else printf("%s\n", desc); fit_image_get_type(fit, image_noffset, &type); printf("%s Type: %s\n", p, genimg_get_type_name(type)); fit_image_get_comp(fit, image_noffset, &comp); printf("%s Compression: %s\n", p, genimg_get_comp_name(comp)); ret = fit_image_get_data(fit, image_noffset, &data, &size); #ifndef USE_HOSTCC printf("%s Data Start: ", p); if (ret) { printf("unavailable\n"); } else { void *vdata = (void *)data; printf("0x%08lx\n", (ulong)map_to_sysmem(vdata)); } #endif printf("%s Data Size: ", p); if (ret) printf("unavailable\n"); else genimg_print_size(size); /* Remaining, type dependent properties */ if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_FLATDT)) { fit_image_get_arch(fit, image_noffset, &arch); printf("%s Architecture: %s\n", p, genimg_get_arch_name(arch)); } 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_RAMDISK)) { ret = fit_image_get_load(fit, image_noffset, &load); printf("%s Load Address: ", p); if (ret) printf("unavailable\n"); else printf("0x%08lx\n", load); } 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) printf("unavailable\n"); else printf("0x%08lx\n", entry); } /* Process all hash subnodes of the component image node */ for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth); (noffset >= 0) && (ndepth > 0); noffset = fdt_next_node(fit, noffset, &ndepth)) { if (ndepth == 1) { /* Direct child node of the component image node */ fit_image_print_verification_data(fit, noffset, p); } } }
/** * spl_load_fit_image(): load the image described in a certain FIT node * @info: points to information about the device to load data from * @sector: the start sector of the FIT image on the device * @fit: points to the flattened device tree blob describing the FIT * image * @base_offset: the beginning of the data area containing the actual * image data, relative to the beginning of the FIT * @node: offset of the DT node describing the image to load (relative * to @fit) * @image_info: will be filled with information about the loaded image * If the FIT node does not contain a "load" (address) property, * the image gets loaded to the address pointed to by the * load_addr member in this struct. * * Return: 0 on success or a negative error number. */ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, void *fit, ulong base_offset, int node, struct spl_image_info *image_info) { int offset; size_t length; int len; ulong size; ulong load_addr, load_ptr; void *src; ulong overhead; int nr_sectors; int align_len = ARCH_DMA_MINALIGN - 1; uint8_t image_comp = -1, type = -1; const void *data; if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP)) { if (fit_image_get_comp(fit, node, &image_comp)) puts("Cannot get image compression format.\n"); else debug("%s ", genimg_get_comp_name(image_comp)); if (fit_image_get_type(fit, node, &type)) puts("Cannot get image type.\n"); else debug("%s ", genimg_get_type_name(type)); } if (fit_image_get_load(fit, node, &load_addr)) load_addr = image_info->load_addr; if (!fit_image_get_data_offset(fit, node, &offset)) { /* External data */ offset += base_offset; if (fit_image_get_data_size(fit, node, &len)) return -ENOENT; load_ptr = (load_addr + align_len) & ~align_len; length = len; overhead = get_aligned_image_overhead(info, offset); nr_sectors = get_aligned_image_size(info, length, offset); if (info->read(info, sector + get_aligned_image_offset(info, offset), nr_sectors, (void *)load_ptr) != nr_sectors) return -EIO; debug("External data: dst=%lx, offset=%x, size=%lx\n", load_ptr, offset, (unsigned long)length); src = (void *)load_ptr + overhead; } else { /* Embedded data */ if (fit_image_get_data(fit, node, &data, &length)) { puts("Cannot get image data/size\n"); return -ENOENT; } debug("Embedded data: dst=%lx, size=%lx\n", load_addr, (unsigned long)length); src = (void *)data; } #ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS board_fit_image_post_process(&src, &length); #endif if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP && type == IH_TYPE_KERNEL) { size = length; if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN, src, &size)) { puts("Uncompressing error\n"); return -EIO; } length = size; } else { memcpy((void *)load_addr, src, length); } if (image_info) { image_info->load_addr = load_addr; image_info->size = length; image_info->entry_point = fdt_getprop_u32(fit, node, "entry"); } return 0; }