uboot/common/spl/spl_fit.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2016 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <errno.h>
   9#include <fpga.h>
  10#include <gzip.h>
  11#include <image.h>
  12#include <log.h>
  13#include <malloc.h>
  14#include <spl.h>
  15#include <sysinfo.h>
  16#include <asm/cache.h>
  17#include <linux/libfdt.h>
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20
  21#ifndef CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
  22#define CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ (64 * 1024)
  23#endif
  24
  25#ifndef CONFIG_SYS_BOOTM_LEN
  26#define CONFIG_SYS_BOOTM_LEN    (64 << 20)
  27#endif
  28
  29__weak void board_spl_fit_post_load(ulong load_addr, size_t length)
  30{
  31}
  32
  33__weak ulong board_spl_fit_size_align(ulong size)
  34{
  35        return size;
  36}
  37
  38static int find_node_from_desc(const void *fit, int node, const char *str)
  39{
  40        int child;
  41
  42        if (node < 0)
  43                return -EINVAL;
  44
  45        /* iterate the FIT nodes and find a matching description */
  46        for (child = fdt_first_subnode(fit, node); child >= 0;
  47             child = fdt_next_subnode(fit, child)) {
  48                int len;
  49                const char *desc = fdt_getprop(fit, child, "description", &len);
  50
  51                if (!desc)
  52                        continue;
  53
  54                if (!strcmp(desc, str))
  55                        return child;
  56        }
  57
  58        return -ENOENT;
  59}
  60
  61/**
  62 * spl_fit_get_image_name(): By using the matching configuration subnode,
  63 * retrieve the name of an image, specified by a property name and an index
  64 * into that.
  65 * @fit:        Pointer to the FDT blob.
  66 * @images:     Offset of the /images subnode.
  67 * @type:       Name of the property within the configuration subnode.
  68 * @index:      Index into the list of strings in this property.
  69 * @outname:    Name of the image
  70 *
  71 * Return:      0 on success, or a negative error number
  72 */
  73static int spl_fit_get_image_name(const void *fit, int images,
  74                                  const char *type, int index,
  75                                  const char **outname)
  76{
  77        struct udevice *sysinfo;
  78        const char *name, *str;
  79        __maybe_unused int node;
  80        int conf_node;
  81        int len, i;
  82        bool found = true;
  83
  84        conf_node = fit_find_config_node(fit);
  85        if (conf_node < 0) {
  86#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
  87                printf("No matching DT out of these options:\n");
  88                for (node = fdt_first_subnode(fit, conf_node);
  89                     node >= 0;
  90                     node = fdt_next_subnode(fit, node)) {
  91                        name = fdt_getprop(fit, node, "description", &len);
  92                        printf("   %s\n", name);
  93                }
  94#endif
  95                return conf_node;
  96        }
  97
  98        name = fdt_getprop(fit, conf_node, type, &len);
  99        if (!name) {
 100                debug("cannot find property '%s': %d\n", type, len);
 101                return -EINVAL;
 102        }
 103
 104        str = name;
 105        for (i = 0; i < index; i++) {
 106                str = strchr(str, '\0') + 1;
 107                if (!str || (str - name >= len)) {
 108                        found = false;
 109                        break;
 110                }
 111        }
 112
 113        if (!found && CONFIG_IS_ENABLED(SYSINFO) && !sysinfo_get(&sysinfo)) {
 114                int rc;
 115                /*
 116                 * no string in the property for this index. Check if the
 117                 * sysinfo-level code can supply one.
 118                 */
 119                rc = sysinfo_get_fit_loadable(sysinfo, index - i - 1, type,
 120                                              &str);
 121                if (rc && rc != -ENOENT)
 122                        return rc;
 123
 124                if (!rc) {
 125                        /*
 126                         * The sysinfo provided a name for a loadable.
 127                         * Try to match it against the description properties
 128                         * first. If no matching node is found, use it as a
 129                         * node name.
 130                         */
 131                        int node;
 132                        int images = fdt_path_offset(fit, FIT_IMAGES_PATH);
 133
 134                        node = find_node_from_desc(fit, images, str);
 135                        if (node > 0)
 136                                str = fdt_get_name(fit, node, NULL);
 137
 138                        found = true;
 139                }
 140        }
 141
 142        if (!found) {
 143                debug("no string for index %d\n", index);
 144                return -E2BIG;
 145        }
 146
 147        *outname = str;
 148        return 0;
 149}
 150
 151/**
 152 * spl_fit_get_image_node(): By using the matching configuration subnode,
 153 * retrieve the name of an image, specified by a property name and an index
 154 * into that.
 155 * @fit:        Pointer to the FDT blob.
 156 * @images:     Offset of the /images subnode.
 157 * @type:       Name of the property within the configuration subnode.
 158 * @index:      Index into the list of strings in this property.
 159 *
 160 * Return:      the node offset of the respective image node or a negative
 161 *              error number.
 162 */
 163static int spl_fit_get_image_node(const void *fit, int images,
 164                                  const char *type, int index)
 165{
 166        const char *str;
 167        int err;
 168        int node;
 169
 170        err = spl_fit_get_image_name(fit, images, type, index, &str);
 171        if (err)
 172                return err;
 173
 174        debug("%s: '%s'\n", type, str);
 175
 176        node = fdt_subnode_offset(fit, images, str);
 177        if (node < 0) {
 178                pr_err("cannot find image node '%s': %d\n", str, node);
 179                return -EINVAL;
 180        }
 181
 182        return node;
 183}
 184
 185static int get_aligned_image_offset(struct spl_load_info *info, int offset)
 186{
 187        /*
 188         * If it is a FS read, get the first address before offset which is
 189         * aligned to ARCH_DMA_MINALIGN. If it is raw read return the
 190         * block number to which offset belongs.
 191         */
 192        if (info->filename)
 193                return offset & ~(ARCH_DMA_MINALIGN - 1);
 194
 195        return offset / info->bl_len;
 196}
 197
 198static int get_aligned_image_overhead(struct spl_load_info *info, int offset)
 199{
 200        /*
 201         * If it is a FS read, get the difference between the offset and
 202         * the first address before offset which is aligned to
 203         * ARCH_DMA_MINALIGN. If it is raw read return the offset within the
 204         * block.
 205         */
 206        if (info->filename)
 207                return offset & (ARCH_DMA_MINALIGN - 1);
 208
 209        return offset % info->bl_len;
 210}
 211
 212static int get_aligned_image_size(struct spl_load_info *info, int data_size,
 213                                  int offset)
 214{
 215        data_size = data_size + get_aligned_image_overhead(info, offset);
 216
 217        if (info->filename)
 218                return data_size;
 219
 220        return (data_size + info->bl_len - 1) / info->bl_len;
 221}
 222
 223/**
 224 * spl_load_fit_image(): load the image described in a certain FIT node
 225 * @info:       points to information about the device to load data from
 226 * @sector:     the start sector of the FIT image on the device
 227 * @fit:        points to the flattened device tree blob describing the FIT
 228 *              image
 229 * @base_offset: the beginning of the data area containing the actual
 230 *              image data, relative to the beginning of the FIT
 231 * @node:       offset of the DT node describing the image to load (relative
 232 *              to @fit)
 233 * @image_info: will be filled with information about the loaded image
 234 *              If the FIT node does not contain a "load" (address) property,
 235 *              the image gets loaded to the address pointed to by the
 236 *              load_addr member in this struct.
 237 *
 238 * Return:      0 on success or a negative error number.
 239 */
 240static int spl_load_fit_image(struct spl_load_info *info, ulong sector,
 241                              void *fit, ulong base_offset, int node,
 242                              struct spl_image_info *image_info)
 243{
 244        int offset;
 245        size_t length;
 246        int len;
 247        ulong size;
 248        ulong load_addr, load_ptr;
 249        void *src;
 250        ulong overhead;
 251        int nr_sectors;
 252        int align_len = ARCH_DMA_MINALIGN - 1;
 253        uint8_t image_comp = -1, type = -1;
 254        const void *data;
 255        bool external_data = false;
 256
 257        if (IS_ENABLED(CONFIG_SPL_FPGA) ||
 258            (IS_ENABLED(CONFIG_SPL_OS_BOOT) && IS_ENABLED(CONFIG_SPL_GZIP))) {
 259                if (fit_image_get_type(fit, node, &type))
 260                        puts("Cannot get image type.\n");
 261                else
 262                        debug("%s ", genimg_get_type_name(type));
 263        }
 264
 265        if (IS_ENABLED(CONFIG_SPL_GZIP)) {
 266                fit_image_get_comp(fit, node, &image_comp);
 267                debug("%s ", genimg_get_comp_name(image_comp));
 268        }
 269
 270        if (fit_image_get_load(fit, node, &load_addr))
 271                load_addr = image_info->load_addr;
 272
 273        if (!fit_image_get_data_position(fit, node, &offset)) {
 274                external_data = true;
 275        } else if (!fit_image_get_data_offset(fit, node, &offset)) {
 276                offset += base_offset;
 277                external_data = true;
 278        }
 279
 280        if (external_data) {
 281                /* External data */
 282                if (fit_image_get_data_size(fit, node, &len))
 283                        return -ENOENT;
 284
 285                load_ptr = (load_addr + align_len) & ~align_len;
 286                length = len;
 287
 288                overhead = get_aligned_image_overhead(info, offset);
 289                nr_sectors = get_aligned_image_size(info, length, offset);
 290
 291                if (info->read(info,
 292                               sector + get_aligned_image_offset(info, offset),
 293                               nr_sectors, (void *)load_ptr) != nr_sectors)
 294                        return -EIO;
 295
 296                debug("External data: dst=%lx, offset=%x, size=%lx\n",
 297                      load_ptr, offset, (unsigned long)length);
 298                src = (void *)load_ptr + overhead;
 299        } else {
 300                /* Embedded data */
 301                if (fit_image_get_data(fit, node, &data, &length)) {
 302                        puts("Cannot get image data/size\n");
 303                        return -ENOENT;
 304                }
 305                debug("Embedded data: dst=%lx, size=%lx\n", load_addr,
 306                      (unsigned long)length);
 307                src = (void *)data;
 308        }
 309
 310#ifdef CONFIG_SPL_FIT_SIGNATURE
 311        printf("## Checking hash(es) for Image %s ... ",
 312               fit_get_name(fit, node, NULL));
 313        if (!fit_image_verify_with_data(fit, node,
 314                                         src, length))
 315                return -EPERM;
 316        puts("OK\n");
 317#endif
 318
 319#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS
 320        board_fit_image_post_process(&src, &length);
 321#endif
 322
 323        if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
 324                size = length;
 325                if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN,
 326                           src, &size)) {
 327                        puts("Uncompressing error\n");
 328                        return -EIO;
 329                }
 330                length = size;
 331        } else {
 332                memcpy((void *)load_addr, src, length);
 333        }
 334
 335        if (image_info) {
 336                ulong entry_point;
 337
 338                image_info->load_addr = load_addr;
 339                image_info->size = length;
 340
 341                if (!fit_image_get_entry(fit, node, &entry_point))
 342                        image_info->entry_point = entry_point;
 343                else
 344                        image_info->entry_point = FDT_ERROR;
 345        }
 346
 347        return 0;
 348}
 349
 350static int spl_fit_append_fdt(struct spl_image_info *spl_image,
 351                              struct spl_load_info *info, ulong sector,
 352                              void *fit, int images, ulong base_offset)
 353{
 354        struct spl_image_info image_info;
 355        int node, ret = 0, index = 0;
 356
 357        /*
 358         * Use the address following the image as target address for the
 359         * device tree.
 360         */
 361        image_info.load_addr = spl_image->load_addr + spl_image->size;
 362
 363        /* Figure out which device tree the board wants to use */
 364        node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP, index++);
 365        if (node < 0) {
 366                debug("%s: cannot find FDT node\n", __func__);
 367
 368                /*
 369                 * U-Boot did not find a device tree inside the FIT image. Use
 370                 * the U-Boot device tree instead.
 371                 */
 372                if (gd->fdt_blob)
 373                        memcpy((void *)image_info.load_addr, gd->fdt_blob,
 374                               fdt_totalsize(gd->fdt_blob));
 375                else
 376                        return node;
 377        } else {
 378                ret = spl_load_fit_image(info, sector, fit, base_offset, node,
 379                                         &image_info);
 380                if (ret < 0)
 381                        return ret;
 382        }
 383
 384        /* Make the load-address of the FDT available for the SPL framework */
 385        spl_image->fdt_addr = (void *)image_info.load_addr;
 386#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
 387        if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) {
 388                void *tmpbuffer = NULL;
 389
 390                for (; ; index++) {
 391                        node = spl_fit_get_image_node(fit, images, FIT_FDT_PROP,
 392                                                      index);
 393                        if (node == -E2BIG) {
 394                                debug("%s: No additional FDT node\n", __func__);
 395                                break;
 396                        } else if (node < 0) {
 397                                debug("%s: unable to find FDT node %d\n",
 398                                      __func__, index);
 399                                continue;
 400                        }
 401
 402                        if (!tmpbuffer) {
 403                                /*
 404                                 * allocate memory to store the DT overlay
 405                                 * before it is applied. It may not be used
 406                                 * depending on how the overlay is stored, so
 407                                 * don't fail yet if the allocation failed.
 408                                 */
 409                                tmpbuffer = malloc(CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ);
 410                                if (!tmpbuffer)
 411                                        debug("%s: unable to allocate space for overlays\n",
 412                                              __func__);
 413                        }
 414                        image_info.load_addr = (ulong)tmpbuffer;
 415                        ret = spl_load_fit_image(info, sector, fit, base_offset,
 416                                                 node, &image_info);
 417                        if (ret < 0)
 418                                break;
 419
 420                        /* Make room in FDT for changes from the overlay */
 421                        ret = fdt_increase_size(spl_image->fdt_addr,
 422                                                image_info.size);
 423                        if (ret < 0)
 424                                break;
 425
 426                        ret = fdt_overlay_apply_verbose(spl_image->fdt_addr,
 427                                                        (void *)image_info.load_addr);
 428                        if (ret) {
 429                                pr_err("failed to apply DT overlay %s\n",
 430                                       fit_get_name(fit, node, NULL));
 431                                break;
 432                        }
 433
 434                        debug("%s: DT overlay %s applied\n", __func__,
 435                              fit_get_name(fit, node, NULL));
 436                }
 437                free(tmpbuffer);
 438                if (ret)
 439                        return ret;
 440        }
 441        /* Try to make space, so we can inject details on the loadables */
 442        ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
 443        if (ret < 0)
 444                return ret;
 445#endif
 446
 447        return ret;
 448}
 449
 450static int spl_fit_record_loadable(const void *fit, int images, int index,
 451                                   void *blob, struct spl_image_info *image)
 452{
 453        int ret = 0;
 454#if !CONFIG_IS_ENABLED(FIT_IMAGE_TINY)
 455        const char *name;
 456        int node;
 457
 458        ret = spl_fit_get_image_name(fit, images, "loadables",
 459                                     index, &name);
 460        if (ret < 0)
 461                return ret;
 462
 463        node = spl_fit_get_image_node(fit, images, "loadables", index);
 464
 465        ret = fdt_record_loadable(blob, index, name, image->load_addr,
 466                                  image->size, image->entry_point,
 467                                  fdt_getprop(fit, node, "type", NULL),
 468                                  fdt_getprop(fit, node, "os", NULL));
 469#endif
 470        return ret;
 471}
 472
 473static int spl_fit_image_get_os(const void *fit, int noffset, uint8_t *os)
 474{
 475#if CONFIG_IS_ENABLED(FIT_IMAGE_TINY) && !defined(CONFIG_SPL_OS_BOOT)
 476        const char *name = fdt_getprop(fit, noffset, FIT_OS_PROP, NULL);
 477
 478        if (!name)
 479                return -ENOENT;
 480
 481        /*
 482         * We don't care what the type of the image actually is,
 483         * only whether or not it is U-Boot. This saves some
 484         * space by omitting the large table of OS types.
 485         */
 486        if (!strcmp(name, "u-boot"))
 487                *os = IH_OS_U_BOOT;
 488        else
 489                *os = IH_OS_INVALID;
 490
 491        return 0;
 492#else
 493        return fit_image_get_os(fit, noffset, os);
 494#endif
 495}
 496
 497/*
 498 * Weak default function to allow customizing SPL fit loading for load-only
 499 * use cases by allowing to skip the parsing/processing of the FIT contents
 500 * (so that this can be done separately in a more customized fashion)
 501 */
 502__weak bool spl_load_simple_fit_skip_processing(void)
 503{
 504        return false;
 505}
 506
 507int spl_load_simple_fit(struct spl_image_info *spl_image,
 508                        struct spl_load_info *info, ulong sector, void *fit)
 509{
 510        int sectors;
 511        ulong size;
 512        unsigned long count;
 513        struct spl_image_info image_info;
 514        int node = -1;
 515        int images, ret;
 516        int base_offset, hsize, align_len = ARCH_DMA_MINALIGN - 1;
 517        int index = 0;
 518        int firmware_node;
 519
 520        /*
 521         * For FIT with external data, figure out where the external images
 522         * start. This is the base for the data-offset properties in each
 523         * image.
 524         */
 525        size = fdt_totalsize(fit);
 526        size = (size + 3) & ~3;
 527        size = board_spl_fit_size_align(size);
 528        base_offset = (size + 3) & ~3;
 529
 530        /*
 531         * So far we only have one block of data from the FIT. Read the entire
 532         * thing, including that first block, placing it so it finishes before
 533         * where we will load the image.
 534         *
 535         * Note that we will load the image such that its first byte will be
 536         * at the load address. Since that byte may be part-way through a
 537         * block, we may load the image up to one block before the load
 538         * address. So take account of that here by subtracting an addition
 539         * block length from the FIT start position.
 540         *
 541         * In fact the FIT has its own load address, but we assume it cannot
 542         * be before CONFIG_SYS_TEXT_BASE.
 543         *
 544         * For FIT with data embedded, data is loaded as part of FIT image.
 545         * For FIT with external data, data is not loaded in this step.
 546         */
 547        hsize = (size + info->bl_len + align_len) & ~align_len;
 548        fit = spl_get_load_buffer(-hsize, hsize);
 549        sectors = get_aligned_image_size(info, size, 0);
 550        count = info->read(info, sector, sectors, fit);
 551        debug("fit read sector %lx, sectors=%d, dst=%p, count=%lu, size=0x%lx\n",
 552              sector, sectors, fit, count, size);
 553
 554        if (count == 0)
 555                return -EIO;
 556
 557        /* skip further processing if requested to enable load-only use cases */
 558        if (spl_load_simple_fit_skip_processing())
 559                return 0;
 560
 561        /* find the node holding the images information */
 562        images = fdt_path_offset(fit, FIT_IMAGES_PATH);
 563        if (images < 0) {
 564                debug("%s: Cannot find /images node: %d\n", __func__, images);
 565                return -1;
 566        }
 567
 568#ifdef CONFIG_SPL_FPGA
 569        node = spl_fit_get_image_node(fit, images, "fpga", 0);
 570        if (node >= 0) {
 571                /* Load the image and set up the spl_image structure */
 572                ret = spl_load_fit_image(info, sector, fit, base_offset, node,
 573                                         spl_image);
 574                if (ret) {
 575                        printf("%s: Cannot load the FPGA: %i\n", __func__, ret);
 576                        return ret;
 577                }
 578
 579                debug("FPGA bitstream at: %x, size: %x\n",
 580                      (u32)spl_image->load_addr, spl_image->size);
 581
 582                ret = fpga_load(0, (const void *)spl_image->load_addr,
 583                                spl_image->size, BIT_FULL);
 584                if (ret) {
 585                        printf("%s: Cannot load the image to the FPGA\n",
 586                               __func__);
 587                        return ret;
 588                }
 589
 590                puts("FPGA image loaded from FIT\n");
 591                node = -1;
 592        }
 593#endif
 594
 595        /*
 596         * Find the U-Boot image using the following search order:
 597         *   - start at 'firmware' (e.g. an ARM Trusted Firmware)
 598         *   - fall back 'kernel' (e.g. a Falcon-mode OS boot
 599         *   - fall back to using the first 'loadables' entry
 600         */
 601        if (node < 0)
 602                node = spl_fit_get_image_node(fit, images, FIT_FIRMWARE_PROP,
 603                                              0);
 604#ifdef CONFIG_SPL_OS_BOOT
 605        if (node < 0)
 606                node = spl_fit_get_image_node(fit, images, FIT_KERNEL_PROP, 0);
 607#endif
 608        if (node < 0) {
 609                debug("could not find firmware image, trying loadables...\n");
 610                node = spl_fit_get_image_node(fit, images, "loadables", 0);
 611                /*
 612                 * If we pick the U-Boot image from "loadables", start at
 613                 * the second image when later loading additional images.
 614                 */
 615                index = 1;
 616        }
 617        if (node < 0) {
 618                debug("%s: Cannot find u-boot image node: %d\n",
 619                      __func__, node);
 620                return -1;
 621        }
 622
 623        /* Load the image and set up the spl_image structure */
 624        ret = spl_load_fit_image(info, sector, fit, base_offset, node,
 625                                 spl_image);
 626        if (ret)
 627                return ret;
 628
 629        /*
 630         * For backward compatibility, we treat the first node that is
 631         * as a U-Boot image, if no OS-type has been declared.
 632         */
 633        if (!spl_fit_image_get_os(fit, node, &spl_image->os))
 634                debug("Image OS is %s\n", genimg_get_os_name(spl_image->os));
 635#if !defined(CONFIG_SPL_OS_BOOT)
 636        else
 637                spl_image->os = IH_OS_U_BOOT;
 638#endif
 639
 640        /*
 641         * Booting a next-stage U-Boot may require us to append the FDT.
 642         * We allow this to fail, as the U-Boot image might embed its FDT.
 643         */
 644        if (spl_image->os == IH_OS_U_BOOT) {
 645                ret = spl_fit_append_fdt(spl_image, info, sector, fit,
 646                                         images, base_offset);
 647                if (!IS_ENABLED(CONFIG_OF_EMBED) && ret < 0)
 648                        return ret;
 649        }
 650
 651        firmware_node = node;
 652        /* Now check if there are more images for us to load */
 653        for (; ; index++) {
 654                uint8_t os_type = IH_OS_INVALID;
 655
 656                node = spl_fit_get_image_node(fit, images, "loadables", index);
 657                if (node < 0)
 658                        break;
 659
 660                /*
 661                 * if the firmware is also a loadable, skip it because
 662                 * it already has been loaded. This is typically the case with
 663                 * u-boot.img generated by mkimage.
 664                 */
 665                if (firmware_node == node)
 666                        continue;
 667
 668                ret = spl_load_fit_image(info, sector, fit, base_offset, node,
 669                                         &image_info);
 670                if (ret < 0)
 671                        continue;
 672
 673                if (!spl_fit_image_get_os(fit, node, &os_type))
 674                        debug("Loadable is %s\n", genimg_get_os_name(os_type));
 675
 676                if (os_type == IH_OS_U_BOOT) {
 677                        spl_fit_append_fdt(&image_info, info, sector,
 678                                           fit, images, base_offset);
 679                        spl_image->fdt_addr = image_info.fdt_addr;
 680                }
 681
 682                /*
 683                 * If the "firmware" image did not provide an entry point,
 684                 * use the first valid entry point from the loadables.
 685                 */
 686                if (spl_image->entry_point == FDT_ERROR &&
 687                    image_info.entry_point != FDT_ERROR)
 688                        spl_image->entry_point = image_info.entry_point;
 689
 690                /* Record our loadables into the FDT */
 691                if (spl_image->fdt_addr)
 692                        spl_fit_record_loadable(fit, images, index,
 693                                                spl_image->fdt_addr,
 694                                                &image_info);
 695        }
 696
 697        /*
 698         * If a platform does not provide CONFIG_SYS_UBOOT_START, U-Boot's
 699         * Makefile will set it to 0 and it will end up as the entry point
 700         * here. What it actually means is: use the load address.
 701         */
 702        if (spl_image->entry_point == FDT_ERROR || spl_image->entry_point == 0)
 703                spl_image->entry_point = spl_image->load_addr;
 704
 705        spl_image->flags |= SPL_FIT_FOUND;
 706
 707#ifdef CONFIG_IMX_HAB
 708        board_spl_fit_post_load((ulong)fit, size);
 709#endif
 710
 711        return 0;
 712}
 713