/** * 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; }
static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) { int res; int node_offset; int splash_offset; int splash_size; struct image_header *img_header; const u32 *fit_header; u32 fit_size; const size_t header_size = sizeof(struct image_header); /* Read in image header */ res = splash_storage_read_raw(location, bmp_load_addr, header_size); if (res < 0) return res; img_header = (struct image_header *)bmp_load_addr; fit_size = fdt_totalsize(img_header); /* Read in entire FIT */ fit_header = (const u32 *)(bmp_load_addr + header_size); res = splash_storage_read_raw(location, (u32)fit_header, fit_size); if (res < 0) return res; res = fit_check_format(fit_header); if (!res) { debug("Could not find valid FIT image\n"); return -EINVAL; } node_offset = fit_image_get_node(fit_header, location->name); if (node_offset < 0) { debug("Could not find splash image '%s' in FIT\n", location->name); return -ENOENT; } res = fit_image_get_data_offset(fit_header, node_offset, &splash_offset); if (res < 0) { printf("Failed to load splash image (err=%d)\n", res); return res; } res = fit_image_get_data_size(fit_header, node_offset, &splash_size); if (res < 0) { printf("Failed to load splash image (err=%d)\n", res); return res; } /* Align data offset to 4-byte boundrary */ fit_size = fdt_totalsize(fit_header); fit_size = (fit_size + 3) & ~3; /* Read in the splash data */ location->offset = (location->offset + fit_size + splash_offset); res = splash_storage_read_raw(location, bmp_load_addr , splash_size); if (res < 0) return res; return 0; }