+#ifdef CONFIG_SPL_FPGA_SUPPORT
+__weak int spl_load_fpga_image(struct spl_load_info *info, size_t length,
+ int nr_sectors, int sector_offset)
+{
+ return 0;
+}
+#endif
+
+/**
+ * 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, sector_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;
+ bool external_data = false;
+#ifdef CONFIG_SPL_FIT_SIGNATURE
+ int ret;
+#endif
+
+ if (IS_ENABLED(CONFIG_SPL_FPGA_SUPPORT) ||
+ (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) {
+ if (fit_image_get_type(fit, node, &type))
+ puts("Cannot get image type.\n");
+ else
+ debug("%s ", genimg_get_type_name(type));
+ }
+
+ 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_load(fit, node, &load_addr))
+ load_addr = image_info->load_addr;
+
+ if (!fit_image_get_data_position(fit, node, &offset)) {
+ external_data = true;
+ } else if (!fit_image_get_data_offset(fit, node, &offset)) {
+ offset += base_offset;
+ external_data = true;
+ }
+
+ if (external_data) {
+ /* External data */
+ 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);
+ sector_offset = sector + get_aligned_image_offset(info, offset);
+
+#ifdef CONFIG_SPL_FPGA_SUPPORT
+ if (type == IH_TYPE_FPGA) {
+ return spl_load_fpga_image(info, length, nr_sectors,
+ sector_offset);
+ }
+#endif
+
+ if (info->read(info, sector_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");
+ }
+
+#ifdef CONFIG_SPL_FIT_SIGNATURE
+ printf("## Checking hash(es) for Image %s ...\n",
+ fit_get_name(fit, node, NULL));
+ ret = fit_image_verify_with_data(fit, node,
+ (const void *)load_addr, length);
+ printf("\n");
+ return !ret;
+#else
+ return 0;
+#endif
+}
+
+static int spl_fit_append_fdt(struct spl_image_info *spl_image,
+ struct spl_load_info *info, ulong sector,
+ void *fit, int images, ulong base_offset)
+{
+ struct spl_image_info image_info;
+ int node, ret;
+
+ /* Figure out which device tree the board wants to use */
+ node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
+ if (node < 0) {
+ debug("%s: cannot find FDT node\n", __func__);
+ return node;
+ }
+
+ /*
+ * Read the device tree and place it after the image.
+ * Align the destination address to ARCH_DMA_MINALIGN.
+ */
+ image_info.load_addr = spl_image->load_addr + spl_image->size;
+ ret = spl_load_fit_image(info, sector, fit, base_offset, node,
+ &image_info);
+
+ if (ret < 0)
+ return ret;
+
+ /* Make the load-address of the FDT available for the SPL framework */
+ spl_image->fdt_addr = (void *)image_info.load_addr;
+#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
+ /* Try to make space, so we can inject details on the loadables */
+ ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
+#endif
+
+ return ret;
+}
+
+static int spl_fit_record_loadable(const void *fit, int images, int index,
+ void *blob, struct spl_image_info *image)
+{
+ int ret = 0;
+#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
+ char *name;
+ int node;
+
+ ret = spl_fit_get_image_name(fit, images, "loadables",
+ index, &name);
+ if (ret < 0)
+ return ret;
+
+ node = spl_fit_get_image_node(fit, images, "loadables", index);
+
+ ret = fdt_record_loadable(blob, index, name, image->load_addr,
+ image->size, image->entry_point,
+ fdt_getprop(fit, node, "type", NULL),
+ fdt_getprop(fit, node, "os", NULL));
+#endif
+ return ret;
+}
+
+static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
+{
+#if CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
+ return -ENOTSUPP;
+#else
+ return fit_image_get_os(fit, noffset, os);
+#endif
+}
+
+int spl_load_simple_fit(struct spl_image_info *spl_image,
+ struct spl_load_info *info, ulong sector, void *fit)