blob: e01b4e578d94190e3324ce3c03d53f3cf43c6c6b [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glassf1dcee52016-02-22 22:55:56 -07002/*
3 * Copyright (C) 2016 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glassf1dcee52016-02-22 22:55:56 -07005 */
6
7#include <common.h>
8#include <errno.h>
9#include <image.h>
Masahiro Yamadab08c8c42018-03-05 01:20:11 +090010#include <linux/libfdt.h>
Simon Glassf1dcee52016-02-22 22:55:56 -070011#include <spl.h>
12
York Sun7264f292017-08-15 11:14:43 -070013#ifndef CONFIG_SYS_BOOTM_LEN
14#define CONFIG_SYS_BOOTM_LEN (64 << 20)
15#endif
16
Andre Przywara736806f2017-04-26 01:32:34 +010017/**
Philipp Tomsicha616c782017-09-13 21:29:34 +020018 * spl_fit_get_image_name(): By using the matching configuration subnode,
Andre Przywara736806f2017-04-26 01:32:34 +010019 * retrieve the name of an image, specified by a property name and an index
20 * into that.
21 * @fit: Pointer to the FDT blob.
22 * @images: Offset of the /images subnode.
23 * @type: Name of the property within the configuration subnode.
24 * @index: Index into the list of strings in this property.
Philipp Tomsicha616c782017-09-13 21:29:34 +020025 * @outname: Name of the image
Andre Przywara736806f2017-04-26 01:32:34 +010026 *
Philipp Tomsicha616c782017-09-13 21:29:34 +020027 * Return: 0 on success, or a negative error number
Andre Przywara736806f2017-04-26 01:32:34 +010028 */
Philipp Tomsicha616c782017-09-13 21:29:34 +020029static int spl_fit_get_image_name(const void *fit, int images,
30 const char *type, int index,
31 char **outname)
Andre Przywara4b9340a2017-04-26 01:32:33 +010032{
33 const char *name, *str;
Philipp Tomsicha616c782017-09-13 21:29:34 +020034 __maybe_unused int node;
35 int conf_node;
Andre Przywara4b9340a2017-04-26 01:32:33 +010036 int len, i;
37
Cooper Jr., Franklin3863f842017-06-16 17:25:05 -050038 conf_node = fit_find_config_node(fit);
Andre Przywara4b9340a2017-04-26 01:32:33 +010039 if (conf_node < 0) {
40#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
41 printf("No matching DT out of these options:\n");
42 for (node = fdt_first_subnode(fit, conf_node);
43 node >= 0;
44 node = fdt_next_subnode(fit, node)) {
45 name = fdt_getprop(fit, node, "description", &len);
46 printf(" %s\n", name);
47 }
48#endif
49 return conf_node;
50 }
51
52 name = fdt_getprop(fit, conf_node, type, &len);
53 if (!name) {
54 debug("cannot find property '%s': %d\n", type, len);
55 return -EINVAL;
56 }
57
58 str = name;
59 for (i = 0; i < index; i++) {
60 str = strchr(str, '\0') + 1;
61 if (!str || (str - name >= len)) {
62 debug("no string for index %d\n", index);
63 return -E2BIG;
64 }
65 }
66
Philipp Tomsicha616c782017-09-13 21:29:34 +020067 *outname = (char *)str;
68 return 0;
69}
70
71/**
72 * spl_fit_get_image_node(): By using the matching configuration subnode,
73 * retrieve the name of an image, specified by a property name and an index
74 * into that.
75 * @fit: Pointer to the FDT blob.
76 * @images: Offset of the /images subnode.
77 * @type: Name of the property within the configuration subnode.
78 * @index: Index into the list of strings in this property.
79 *
80 * Return: the node offset of the respective image node or a negative
81 * error number.
82 */
83static int spl_fit_get_image_node(const void *fit, int images,
84 const char *type, int index)
85{
86 char *str;
87 int err;
88 int node;
89
90 err = spl_fit_get_image_name(fit, images, type, index, &str);
91 if (err)
92 return err;
93
Andre Przywara4b9340a2017-04-26 01:32:33 +010094 debug("%s: '%s'\n", type, str);
Philipp Tomsicha616c782017-09-13 21:29:34 +020095
Andre Przywara4b9340a2017-04-26 01:32:33 +010096 node = fdt_subnode_offset(fit, images, str);
97 if (node < 0) {
98 debug("cannot find image node '%s': %d\n", str, node);
99 return -EINVAL;
100 }
101
Andre Przywara736806f2017-04-26 01:32:34 +0100102 return node;
Andre Przywara4b9340a2017-04-26 01:32:33 +0100103}
104
Lokesh Vutlaeafd5412016-05-24 10:34:38 +0530105static int get_aligned_image_offset(struct spl_load_info *info, int offset)
106{
107 /*
108 * If it is a FS read, get the first address before offset which is
109 * aligned to ARCH_DMA_MINALIGN. If it is raw read return the
110 * block number to which offset belongs.
111 */
112 if (info->filename)
113 return offset & ~(ARCH_DMA_MINALIGN - 1);
114
115 return offset / info->bl_len;
116}
117
118static int get_aligned_image_overhead(struct spl_load_info *info, int offset)
119{
120 /*
121 * If it is a FS read, get the difference between the offset and
122 * the first address before offset which is aligned to
123 * ARCH_DMA_MINALIGN. If it is raw read return the offset within the
124 * block.
125 */
126 if (info->filename)
127 return offset & (ARCH_DMA_MINALIGN - 1);
128
129 return offset % info->bl_len;
130}
131
132static int get_aligned_image_size(struct spl_load_info *info, int data_size,
133 int offset)
134{
Lokesh Vutla3cc1f382016-07-19 14:56:14 +0530135 data_size = data_size + get_aligned_image_overhead(info, offset);
136
Lokesh Vutlaeafd5412016-05-24 10:34:38 +0530137 if (info->filename)
Lokesh Vutla3cc1f382016-07-19 14:56:14 +0530138 return data_size;
Lokesh Vutlaeafd5412016-05-24 10:34:38 +0530139
140 return (data_size + info->bl_len - 1) / info->bl_len;
141}
142
Marek Vasut26a64222018-05-12 22:25:28 +0200143#ifdef CONFIG_SPL_FPGA_SUPPORT
144__weak int spl_load_fpga_image(struct spl_load_info *info, size_t length,
145 int nr_sectors, int sector_offset)
146{
147 return 0;
148}
149#endif
150
Andre Przywara8baa3812017-04-26 01:32:36 +0100151/**
152 * spl_load_fit_image(): load the image described in a certain FIT node
153 * @info: points to information about the device to load data from
154 * @sector: the start sector of the FIT image on the device
155 * @fit: points to the flattened device tree blob describing the FIT
Philipp Tomsicha616c782017-09-13 21:29:34 +0200156 * image
Andre Przywara8baa3812017-04-26 01:32:36 +0100157 * @base_offset: the beginning of the data area containing the actual
158 * image data, relative to the beginning of the FIT
159 * @node: offset of the DT node describing the image to load (relative
Philipp Tomsicha616c782017-09-13 21:29:34 +0200160 * to @fit)
Andre Przywara8baa3812017-04-26 01:32:36 +0100161 * @image_info: will be filled with information about the loaded image
Philipp Tomsicha616c782017-09-13 21:29:34 +0200162 * If the FIT node does not contain a "load" (address) property,
163 * the image gets loaded to the address pointed to by the
164 * load_addr member in this struct.
Andre Przywara8baa3812017-04-26 01:32:36 +0100165 *
166 * Return: 0 on success or a negative error number.
167 */
168static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
169 void *fit, ulong base_offset, int node,
170 struct spl_image_info *image_info)
171{
Marek Vasut26a64222018-05-12 22:25:28 +0200172 int offset, sector_offset;
Andre Przywara8baa3812017-04-26 01:32:36 +0100173 size_t length;
York Sun5fd13d92017-08-15 11:14:44 -0700174 int len;
York Sun933f67a2017-09-15 08:21:13 -0700175 ulong size;
Andre Przywara8baa3812017-04-26 01:32:36 +0100176 ulong load_addr, load_ptr;
177 void *src;
178 ulong overhead;
179 int nr_sectors;
180 int align_len = ARCH_DMA_MINALIGN - 1;
York Sun7264f292017-08-15 11:14:43 -0700181 uint8_t image_comp = -1, type = -1;
York Sun5fd13d92017-08-15 11:14:44 -0700182 const void *data;
Peng Fana1be94b2017-12-05 13:20:59 +0800183 bool external_data = false;
Jun Nie5c643db2018-02-27 16:55:58 +0800184#ifdef CONFIG_SPL_FIT_SIGNATURE
185 int ret;
186#endif
York Sun7264f292017-08-15 11:14:43 -0700187
Marek Vasut56419ea2018-06-01 23:19:29 +0200188 if (IS_ENABLED(CONFIG_SPL_FPGA_SUPPORT) ||
189 (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) {
190 if (fit_image_get_type(fit, node, &type))
191 puts("Cannot get image type.\n");
192 else
193 debug("%s ", genimg_get_type_name(type));
194 }
195
York Sun7264f292017-08-15 11:14:43 -0700196 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP)) {
197 if (fit_image_get_comp(fit, node, &image_comp))
198 puts("Cannot get image compression format.\n");
199 else
200 debug("%s ", genimg_get_comp_name(image_comp));
York Sun7264f292017-08-15 11:14:43 -0700201 }
Andre Przywara8baa3812017-04-26 01:32:36 +0100202
York Sun5fd13d92017-08-15 11:14:44 -0700203 if (fit_image_get_load(fit, node, &load_addr))
Andre Przywara8baa3812017-04-26 01:32:36 +0100204 load_addr = image_info->load_addr;
Andre Przywara8baa3812017-04-26 01:32:36 +0100205
Peng Fana1be94b2017-12-05 13:20:59 +0800206 if (!fit_image_get_data_position(fit, node, &offset)) {
207 external_data = true;
208 } else if (!fit_image_get_data_offset(fit, node, &offset)) {
York Sun5fd13d92017-08-15 11:14:44 -0700209 offset += base_offset;
Peng Fana1be94b2017-12-05 13:20:59 +0800210 external_data = true;
211 }
212
213 if (external_data) {
214 /* External data */
York Sun5fd13d92017-08-15 11:14:44 -0700215 if (fit_image_get_data_size(fit, node, &len))
216 return -ENOENT;
Andre Przywara8baa3812017-04-26 01:32:36 +0100217
York Sun5fd13d92017-08-15 11:14:44 -0700218 load_ptr = (load_addr + align_len) & ~align_len;
219 length = len;
Andre Przywara8baa3812017-04-26 01:32:36 +0100220
York Sun5fd13d92017-08-15 11:14:44 -0700221 overhead = get_aligned_image_overhead(info, offset);
222 nr_sectors = get_aligned_image_size(info, length, offset);
Marek Vasut26a64222018-05-12 22:25:28 +0200223 sector_offset = sector + get_aligned_image_offset(info, offset);
York Sun5fd13d92017-08-15 11:14:44 -0700224
Marek Vasut26a64222018-05-12 22:25:28 +0200225#ifdef CONFIG_SPL_FPGA_SUPPORT
226 if (type == IH_TYPE_FPGA) {
227 return spl_load_fpga_image(info, length, nr_sectors,
228 sector_offset);
229 }
230#endif
231
232 if (info->read(info, sector_offset,
York Sun5fd13d92017-08-15 11:14:44 -0700233 nr_sectors, (void *)load_ptr) != nr_sectors)
234 return -EIO;
235
236 debug("External data: dst=%lx, offset=%x, size=%lx\n",
237 load_ptr, offset, (unsigned long)length);
238 src = (void *)load_ptr + overhead;
239 } else {
240 /* Embedded data */
241 if (fit_image_get_data(fit, node, &data, &length)) {
242 puts("Cannot get image data/size\n");
243 return -ENOENT;
244 }
245 debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
246 (unsigned long)length);
247 src = (void *)data;
248 }
249
Andre Przywara8baa3812017-04-26 01:32:36 +0100250#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
251 board_fit_image_post_process(&src, &length);
252#endif
253
York Sun7264f292017-08-15 11:14:43 -0700254 if (IS_ENABLED(CONFIG_SPL_OS_BOOT) &&
255 IS_ENABLED(CONFIG_SPL_GZIP) &&
256 image_comp == IH_COMP_GZIP &&
257 type == IH_TYPE_KERNEL) {
York Sun933f67a2017-09-15 08:21:13 -0700258 size = length;
York Sun7264f292017-08-15 11:14:43 -0700259 if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
York Sun933f67a2017-09-15 08:21:13 -0700260 src, &size)) {
York Sun7264f292017-08-15 11:14:43 -0700261 puts("Uncompressing error\n");
262 return -EIO;
263 }
York Sun933f67a2017-09-15 08:21:13 -0700264 length = size;
York Sun7264f292017-08-15 11:14:43 -0700265 } else {
266 memcpy((void *)load_addr, src, length);
267 }
Andre Przywara8baa3812017-04-26 01:32:36 +0100268
269 if (image_info) {
270 image_info->load_addr = load_addr;
271 image_info->size = length;
272 image_info->entry_point = fdt_getprop_u32(fit, node, "entry");
273 }
274
Jun Nie5c643db2018-02-27 16:55:58 +0800275#ifdef CONFIG_SPL_FIT_SIGNATURE
276 printf("## Checking hash(es) for Image %s ...\n",
277 fit_get_name(fit, node, NULL));
278 ret = fit_image_verify_with_data(fit, node,
279 (const void *)load_addr, length);
280 printf("\n");
281 return !ret;
282#else
Andre Przywara8baa3812017-04-26 01:32:36 +0100283 return 0;
Jun Nie5c643db2018-02-27 16:55:58 +0800284#endif
Andre Przywara8baa3812017-04-26 01:32:36 +0100285}
286
Philipp Tomsichd8796162017-09-13 21:29:32 +0200287static int spl_fit_append_fdt(struct spl_image_info *spl_image,
288 struct spl_load_info *info, ulong sector,
289 void *fit, int images, ulong base_offset)
290{
291 struct spl_image_info image_info;
292 int node, ret;
293
294 /* Figure out which device tree the board wants to use */
295 node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, 0);
296 if (node < 0) {
297 debug("%s: cannot find FDT node\n", __func__);
298 return node;
299 }
300
301 /*
302 * Read the device tree and place it after the image.
303 * Align the destination address to ARCH_DMA_MINALIGN.
304 */
305 image_info.load_addr = spl_image->load_addr + spl_image->size;
306 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
307 &image_info);
Philipp Tomsicha616c782017-09-13 21:29:34 +0200308
309 if (ret < 0)
310 return ret;
311
312 /* Make the load-address of the FDT available for the SPL framework */
313 spl_image->fdt_addr = (void *)image_info.load_addr;
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100314#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
Philipp Tomsicha616c782017-09-13 21:29:34 +0200315 /* Try to make space, so we can inject details on the loadables */
316 ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100317#endif
Philipp Tomsicha616c782017-09-13 21:29:34 +0200318
319 return ret;
320}
321
322static int spl_fit_record_loadable(const void *fit, int images, int index,
323 void *blob, struct spl_image_info *image)
324{
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100325 int ret = 0;
326#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
Philipp Tomsicha616c782017-09-13 21:29:34 +0200327 char *name;
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100328 int node;
Philipp Tomsicha616c782017-09-13 21:29:34 +0200329
330 ret = spl_fit_get_image_name(fit, images, "loadables",
331 index, &name);
332 if (ret < 0)
333 return ret;
334
335 node = spl_fit_get_image_node(fit, images, "loadables", index);
336
337 ret = fdt_record_loadable(blob, index, name, image->load_addr,
338 image->size, image->entry_point,
339 fdt_getprop(fit, node, "type", NULL),
340 fdt_getprop(fit, node, "os", NULL));
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100341#endif
Philipp Tomsichd8796162017-09-13 21:29:32 +0200342 return ret;
343}
344
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100345static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
346{
347#if CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
348 return -ENOTSUPP;
349#else
350 return fit_image_get_os(fit, noffset, os);
351#endif
352}
353
Simon Glassf4d7d852016-09-24 18:20:16 -0600354int spl_load_simple_fit(struct spl_image_info *spl_image,
355 struct spl_load_info *info, ulong sector, void *fit)
Simon Glassf1dcee52016-02-22 22:55:56 -0700356{
357 int sectors;
Andre Przywara8baa3812017-04-26 01:32:36 +0100358 ulong size;
Simon Glassf1dcee52016-02-22 22:55:56 -0700359 unsigned long count;
Andre Przywara8baa3812017-04-26 01:32:36 +0100360 struct spl_image_info image_info;
York Sunc8bc3c02017-08-15 11:14:45 -0700361 int node = -1;
362 int images, ret;
Lokesh Vutlaeafd5412016-05-24 10:34:38 +0530363 int base_offset, align_len = ARCH_DMA_MINALIGN - 1;
Andre Przywara411cf322017-04-26 01:32:37 +0100364 int index = 0;
Simon Glassf1dcee52016-02-22 22:55:56 -0700365
366 /*
York Sunc8bc3c02017-08-15 11:14:45 -0700367 * For FIT with external data, figure out where the external images
368 * start. This is the base for the data-offset properties in each
369 * image.
Simon Glassf1dcee52016-02-22 22:55:56 -0700370 */
371 size = fdt_totalsize(fit);
372 size = (size + 3) & ~3;
373 base_offset = (size + 3) & ~3;
374
375 /*
376 * So far we only have one block of data from the FIT. Read the entire
377 * thing, including that first block, placing it so it finishes before
378 * where we will load the image.
379 *
380 * Note that we will load the image such that its first byte will be
381 * at the load address. Since that byte may be part-way through a
382 * block, we may load the image up to one block before the load
383 * address. So take account of that here by subtracting an addition
384 * block length from the FIT start position.
385 *
386 * In fact the FIT has its own load address, but we assume it cannot
387 * be before CONFIG_SYS_TEXT_BASE.
York Sunc8bc3c02017-08-15 11:14:45 -0700388 *
389 * For FIT with data embedded, data is loaded as part of FIT image.
390 * For FIT with external data, data is not loaded in this step.
Simon Glassf1dcee52016-02-22 22:55:56 -0700391 */
Lokesh Vutla8b528702016-06-01 10:28:31 +0530392 fit = (void *)((CONFIG_SYS_TEXT_BASE - size - info->bl_len -
393 align_len) & ~align_len);
Lokesh Vutlaeafd5412016-05-24 10:34:38 +0530394 sectors = get_aligned_image_size(info, size, 0);
Simon Glassf1dcee52016-02-22 22:55:56 -0700395 count = info->read(info, sector, sectors, fit);
396 debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu\n",
397 sector, sectors, fit, count);
398 if (count == 0)
399 return -EIO;
400
Andre Przywara736806f2017-04-26 01:32:34 +0100401 /* find the node holding the images information */
Simon Glassf1dcee52016-02-22 22:55:56 -0700402 images = fdt_path_offset(fit, FIT_IMAGES_PATH);
403 if (images < 0) {
404 debug("%s: Cannot find /images node: %d\n", __func__, images);
405 return -1;
406 }
Andre Przywara736806f2017-04-26 01:32:34 +0100407
Marek Vasut26a64222018-05-12 22:25:28 +0200408#ifdef CONFIG_SPL_FPGA_SUPPORT
409 node = spl_fit_get_image_node(fit, images, "fpga", 0);
410 if (node >= 0) {
411 /* Load the image and set up the spl_image structure */
412 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
413 spl_image);
414 if (ret) {
415 printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
416 return ret;
417 }
418 node = -1;
419 }
420#endif
421
Philipp Tomsichd8796162017-09-13 21:29:32 +0200422 /*
423 * Find the U-Boot image using the following search order:
424 * - start at 'firmware' (e.g. an ARM Trusted Firmware)
425 * - fall back 'kernel' (e.g. a Falcon-mode OS boot
426 * - fall back to using the first 'loadables' entry
427 */
York Sunc8bc3c02017-08-15 11:14:45 -0700428 if (node < 0)
Michal Simek1f8e4bf2018-03-26 16:31:26 +0200429 node = spl_fit_get_image_node(fit, images, FIT_FIRMWARE_PROP,
430 0);
Philipp Tomsichd8796162017-09-13 21:29:32 +0200431#ifdef CONFIG_SPL_OS_BOOT
432 if (node < 0)
433 node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0);
434#endif
Simon Glassf1dcee52016-02-22 22:55:56 -0700435 if (node < 0) {
Andre Przywara736806f2017-04-26 01:32:34 +0100436 debug("could not find firmware image, trying loadables...\n");
437 node = spl_fit_get_image_node(fit, images, "loadables", 0);
Andre Przywara411cf322017-04-26 01:32:37 +0100438 /*
439 * If we pick the U-Boot image from "loadables", start at
440 * the second image when later loading additional images.
441 */
442 index = 1;
Andre Przywara736806f2017-04-26 01:32:34 +0100443 }
444 if (node < 0) {
445 debug("%s: Cannot find u-boot image node: %d\n",
446 __func__, node);
Simon Glassf1dcee52016-02-22 22:55:56 -0700447 return -1;
448 }
449
Andre Przywara8baa3812017-04-26 01:32:36 +0100450 /* Load the image and set up the spl_image structure */
451 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
452 spl_image);
453 if (ret)
454 return ret;
455
Philipp Tomsichd8796162017-09-13 21:29:32 +0200456 /*
457 * For backward compatibility, we treat the first node that is
458 * as a U-Boot image, if no OS-type has been declared.
459 */
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100460 if (!spl_fit_image_get_os(fit, node, &spl_image->os))
York Sunc8bc3c02017-08-15 11:14:45 -0700461 debug("Image OS is %s\n", genimg_get_os_name(spl_image->os));
Philipp Tomsichd8796162017-09-13 21:29:32 +0200462#if !defined(CONFIG_SPL_OS_BOOT)
463 else
464 spl_image->os = IH_OS_U_BOOT;
York Sunc8bc3c02017-08-15 11:14:45 -0700465#endif
Simon Glassf1dcee52016-02-22 22:55:56 -0700466
Philipp Tomsichd8796162017-09-13 21:29:32 +0200467 /*
468 * Booting a next-stage U-Boot may require us to append the FDT.
469 * We allow this to fail, as the U-Boot image might embed its FDT.
470 */
471 if (spl_image->os == IH_OS_U_BOOT)
472 spl_fit_append_fdt(spl_image, info, sector, fit,
473 images, base_offset);
Simon Glassf1dcee52016-02-22 22:55:56 -0700474
Andre Przywara411cf322017-04-26 01:32:37 +0100475 /* Now check if there are more images for us to load */
476 for (; ; index++) {
Philipp Tomsichd8796162017-09-13 21:29:32 +0200477 uint8_t os_type = IH_OS_INVALID;
478
Andre Przywara411cf322017-04-26 01:32:37 +0100479 node = spl_fit_get_image_node(fit, images, "loadables", index);
480 if (node < 0)
481 break;
482
483 ret = spl_load_fit_image(info, sector, fit, base_offset, node,
484 &image_info);
485 if (ret < 0)
486 continue;
487
Philipp Tomsich337bbb62017-11-24 13:26:03 +0100488 if (!spl_fit_image_get_os(fit, node, &os_type))
Philipp Tomsichd8796162017-09-13 21:29:32 +0200489 debug("Loadable is %s\n", genimg_get_os_name(os_type));
490
Philipp Tomsicha616c782017-09-13 21:29:34 +0200491 if (os_type == IH_OS_U_BOOT) {
492 spl_fit_append_fdt(&image_info, info, sector,
Philipp Tomsichd8796162017-09-13 21:29:32 +0200493 fit, images, base_offset);
Philipp Tomsicha616c782017-09-13 21:29:34 +0200494 spl_image->fdt_addr = image_info.fdt_addr;
495 }
Philipp Tomsichd8796162017-09-13 21:29:32 +0200496
Andre Przywara411cf322017-04-26 01:32:37 +0100497 /*
498 * If the "firmware" image did not provide an entry point,
499 * use the first valid entry point from the loadables.
500 */
501 if (spl_image->entry_point == FDT_ERROR &&
502 image_info.entry_point != FDT_ERROR)
503 spl_image->entry_point = image_info.entry_point;
Philipp Tomsicha616c782017-09-13 21:29:34 +0200504
505 /* Record our loadables into the FDT */
506 if (spl_image->fdt_addr)
507 spl_fit_record_loadable(fit, images, index,
508 spl_image->fdt_addr,
509 &image_info);
Andre Przywara411cf322017-04-26 01:32:37 +0100510 }
511
512 /*
513 * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's
514 * Makefile will set it to 0 and it will end up as the entry point
515 * here. What it actually means is: use the load address.
516 */
517 if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0)
518 spl_image->entry_point = spl_image->load_addr;
519
520 return 0;
Simon Glassf1dcee52016-02-22 22:55:56 -0700521}