uboot/common/spl/spl.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2010
   3 * Texas Instruments, <www.ti.com>
   4 *
   5 * Aneesh V <aneesh@ti.com>
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9#include <common.h>
  10#include <dm.h>
  11#include <spl.h>
  12#include <asm/u-boot.h>
  13#include <nand.h>
  14#include <fat.h>
  15#include <version.h>
  16#include <image.h>
  17#include <malloc.h>
  18#include <dm/root.h>
  19#include <linux/compiler.h>
  20
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23#ifndef CONFIG_SYS_UBOOT_START
  24#define CONFIG_SYS_UBOOT_START  CONFIG_SYS_TEXT_BASE
  25#endif
  26#ifndef CONFIG_SYS_MONITOR_LEN
  27/* Unknown U-Boot size, let's assume it will not be more than 200 KB */
  28#define CONFIG_SYS_MONITOR_LEN  (200 * 1024)
  29#endif
  30
  31u32 *boot_params_ptr = NULL;
  32
  33/* Define board data structure */
  34static bd_t bdata __attribute__ ((section(".data")));
  35
  36/*
  37 * Board-specific Platform code can reimplement show_boot_progress () if needed
  38 */
  39__weak void show_boot_progress(int val) {}
  40
  41/*
  42 * Default function to determine if u-boot or the OS should
  43 * be started. This implementation always returns 1.
  44 *
  45 * Please implement your own board specific funcion to do this.
  46 *
  47 * RETURN
  48 * 0 to not start u-boot
  49 * positive if u-boot should start
  50 */
  51#ifdef CONFIG_SPL_OS_BOOT
  52__weak int spl_start_uboot(void)
  53{
  54        puts("SPL: Please implement spl_start_uboot() for your board\n");
  55        puts("SPL: Direct Linux boot not active!\n");
  56        return 1;
  57}
  58
  59/*
  60 * Weak default function for arch specific zImage check. Return zero
  61 * and fill start and end address if image is recognized.
  62 */
  63int __weak bootz_setup(ulong image, ulong *start, ulong *end)
  64{
  65         return 1;
  66}
  67#endif
  68
  69/*
  70 * Weak default function for board specific cleanup/preparation before
  71 * Linux boot. Some boards/platforms might not need it, so just provide
  72 * an empty stub here.
  73 */
  74__weak void spl_board_prepare_for_linux(void)
  75{
  76        /* Nothing to do! */
  77}
  78
  79__weak void spl_board_prepare_for_boot(void)
  80{
  81        /* Nothing to do! */
  82}
  83
  84void spl_set_header_raw_uboot(struct spl_image_info *spl_image)
  85{
  86        spl_image->size = CONFIG_SYS_MONITOR_LEN;
  87        spl_image->entry_point = CONFIG_SYS_UBOOT_START;
  88        spl_image->load_addr = CONFIG_SYS_TEXT_BASE;
  89        spl_image->os = IH_OS_U_BOOT;
  90        spl_image->name = "U-Boot";
  91}
  92
  93int spl_parse_image_header(struct spl_image_info *spl_image,
  94                           const struct image_header *header)
  95{
  96        u32 header_size = sizeof(struct image_header);
  97
  98        if (image_get_magic(header) == IH_MAGIC) {
  99                if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) {
 100                        /*
 101                         * On some system (e.g. powerpc), the load-address and
 102                         * entry-point is located at address 0. We can't load
 103                         * to 0-0x40. So skip header in this case.
 104                         */
 105                        spl_image->load_addr = image_get_load(header);
 106                        spl_image->entry_point = image_get_ep(header);
 107                        spl_image->size = image_get_data_size(header);
 108                } else {
 109                        spl_image->entry_point = image_get_load(header);
 110                        /* Load including the header */
 111                        spl_image->load_addr = spl_image->entry_point -
 112                                header_size;
 113                        spl_image->size = image_get_data_size(header) +
 114                                header_size;
 115                }
 116                spl_image->os = image_get_os(header);
 117                spl_image->name = image_get_name(header);
 118                debug("spl: payload image: %.*s load addr: 0x%x size: %d\n",
 119                        (int)sizeof(spl_image->name), spl_image->name,
 120                        spl_image->load_addr, spl_image->size);
 121        } else {
 122#ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE
 123                /*
 124                 * CONFIG_SPL_PANIC_ON_RAW_IMAGE is defined when the
 125                 * code which loads images in SPL cannot guarantee that
 126                 * absolutely all read errors will be reported.
 127                 * An example is the LPC32XX MLC NAND driver, which
 128                 * will consider that a completely unreadable NAND block
 129                 * is bad, and thus should be skipped silently.
 130                 */
 131                panic("** no mkimage signature but raw image not supported");
 132#endif
 133
 134#ifdef CONFIG_SPL_OS_BOOT
 135                ulong start, end;
 136
 137                if (!bootz_setup((ulong)header, &start, &end)) {
 138                        spl_image->name = "Linux";
 139                        spl_image->os = IH_OS_LINUX;
 140                        spl_image->load_addr = CONFIG_SYS_LOAD_ADDR;
 141                        spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
 142                        spl_image->size = end - start;
 143                        debug("spl: payload zImage, load addr: 0x%x size: %d\n",
 144                              spl_image->load_addr, spl_image->size);
 145                        return 0;
 146                }
 147#endif
 148
 149#ifdef CONFIG_SPL_ABORT_ON_RAW_IMAGE
 150                /* Signature not found, proceed to other boot methods. */
 151                return -EINVAL;
 152#else
 153                /* Signature not found - assume u-boot.bin */
 154                debug("mkimage signature not found - ih_magic = %x\n",
 155                        header->ih_magic);
 156                spl_set_header_raw_uboot(spl_image);
 157#endif
 158        }
 159        return 0;
 160}
 161
 162__weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
 163{
 164        typedef void __noreturn (*image_entry_noargs_t)(void);
 165
 166        image_entry_noargs_t image_entry =
 167                (image_entry_noargs_t)(unsigned long)spl_image->entry_point;
 168
 169        debug("image entry point: 0x%X\n", spl_image->entry_point);
 170        image_entry();
 171}
 172
 173#ifndef CONFIG_SPL_LOAD_FIT_ADDRESS
 174# define CONFIG_SPL_LOAD_FIT_ADDRESS    0
 175#endif
 176
 177#if defined(CONFIG_SPL_RAM_DEVICE) || defined(CONFIG_SPL_DFU_SUPPORT)
 178static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
 179                               ulong count, void *buf)
 180{
 181        debug("%s: sector %lx, count %lx, buf %lx\n",
 182              __func__, sector, count, (ulong)buf);
 183        memcpy(buf, (void *)(CONFIG_SPL_LOAD_FIT_ADDRESS + sector), count);
 184        return count;
 185}
 186
 187static int spl_ram_load_image(struct spl_image_info *spl_image,
 188                              struct spl_boot_device *bootdev)
 189{
 190        struct image_header *header;
 191
 192        header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS;
 193
 194#if defined(CONFIG_SPL_DFU_SUPPORT)
 195        if (bootdev->boot_device == BOOT_DEVICE_DFU)
 196                spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0");
 197#endif
 198
 199        if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
 200            image_get_magic(header) == FDT_MAGIC) {
 201                struct spl_load_info load;
 202
 203                debug("Found FIT\n");
 204                load.bl_len = 1;
 205                load.read = spl_ram_load_read;
 206                spl_load_simple_fit(spl_image, &load, 0, header);
 207        } else {
 208                debug("Legacy image\n");
 209                /*
 210                 * Get the header.  It will point to an address defined by
 211                 * handoff which will tell where the image located inside
 212                 * the flash. For now, it will temporary fixed to address
 213                 * pointed by U-Boot.
 214                 */
 215                header = (struct image_header *)
 216                        (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header));
 217
 218                spl_parse_image_header(spl_image, header);
 219        }
 220
 221        return 0;
 222}
 223#if defined(CONFIG_SPL_RAM_DEVICE)
 224SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image);
 225#endif
 226#if defined(CONFIG_SPL_DFU_SUPPORT)
 227SPL_LOAD_IMAGE_METHOD("USB DFU", 0, BOOT_DEVICE_DFU, spl_ram_load_image);
 228#endif
 229#endif
 230
 231int spl_init(void)
 232{
 233        int ret;
 234
 235        debug("spl_init()\n");
 236#if defined(CONFIG_SYS_MALLOC_F_LEN)
 237#ifdef CONFIG_MALLOC_F_ADDR
 238        gd->malloc_base = CONFIG_MALLOC_F_ADDR;
 239#endif
 240        gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN;
 241        gd->malloc_ptr = 0;
 242#endif
 243        if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
 244                ret = fdtdec_setup();
 245                if (ret) {
 246                        debug("fdtdec_setup() returned error %d\n", ret);
 247                        return ret;
 248                }
 249        }
 250        if (IS_ENABLED(CONFIG_SPL_DM)) {
 251                /* With CONFIG_OF_PLATDATA, bring in all devices */
 252                ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA));
 253                if (ret) {
 254                        debug("dm_init_and_scan() returned error %d\n", ret);
 255                        return ret;
 256                }
 257        }
 258        gd->flags |= GD_FLG_SPL_INIT;
 259
 260        return 0;
 261}
 262
 263#ifndef BOOT_DEVICE_NONE
 264#define BOOT_DEVICE_NONE 0xdeadbeef
 265#endif
 266
 267__weak void board_boot_order(u32 *spl_boot_list)
 268{
 269        spl_boot_list[0] = spl_boot_device();
 270}
 271
 272static struct spl_image_loader *spl_ll_find_loader(uint boot_device)
 273{
 274        struct spl_image_loader *drv =
 275                ll_entry_start(struct spl_image_loader, spl_image_loader);
 276        const int n_ents =
 277                ll_entry_count(struct spl_image_loader, spl_image_loader);
 278        struct spl_image_loader *entry;
 279
 280        for (entry = drv; entry != drv + n_ents; entry++) {
 281                if (boot_device == entry->boot_device)
 282                        return entry;
 283        }
 284
 285        /* Not found */
 286        return NULL;
 287}
 288
 289static int spl_load_image(struct spl_image_info *spl_image,
 290                          struct spl_image_loader *loader)
 291{
 292        struct spl_boot_device bootdev;
 293
 294        bootdev.boot_device = loader->boot_device;
 295        bootdev.boot_device_name = NULL;
 296
 297        return loader->load_image(spl_image, &bootdev);
 298}
 299
 300/**
 301 * boot_from_devices() - Try loading an booting U-Boot from a list of devices
 302 *
 303 * @spl_image: Place to put the image details if successful
 304 * @spl_boot_list: List of boot devices to try
 305 * @count: Number of elements in spl_boot_list
 306 * @return 0 if OK, -ve on error
 307 */
 308static int boot_from_devices(struct spl_image_info *spl_image,
 309                             u32 spl_boot_list[], int count)
 310{
 311        int i;
 312
 313        for (i = 0; i < count && spl_boot_list[i] != BOOT_DEVICE_NONE; i++) {
 314                struct spl_image_loader *loader;
 315
 316                loader = spl_ll_find_loader(spl_boot_list[i]);
 317#if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
 318                if (loader)
 319                        printf("Trying to boot from %s\n", loader->name);
 320                else
 321                        puts("SPL: Unsupported Boot Device!\n");
 322#endif
 323                if (loader && !spl_load_image(spl_image, loader))
 324                        return 0;
 325        }
 326
 327        return -ENODEV;
 328}
 329
 330void board_init_r(gd_t *dummy1, ulong dummy2)
 331{
 332        u32 spl_boot_list[] = {
 333                BOOT_DEVICE_NONE,
 334                BOOT_DEVICE_NONE,
 335                BOOT_DEVICE_NONE,
 336                BOOT_DEVICE_NONE,
 337                BOOT_DEVICE_NONE,
 338        };
 339        struct spl_image_info spl_image;
 340
 341        debug(">>spl:board_init_r()\n");
 342
 343#if defined(CONFIG_SYS_SPL_MALLOC_START)
 344        mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
 345                        CONFIG_SYS_SPL_MALLOC_SIZE);
 346        gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 347#endif
 348        if (!(gd->flags & GD_FLG_SPL_INIT)) {
 349                if (spl_init())
 350                        hang();
 351        }
 352#ifndef CONFIG_PPC
 353        /*
 354         * timer_init() does not exist on PPC systems. The timer is initialized
 355         * and enabled (decrementer) in interrupt_init() here.
 356         */
 357        timer_init();
 358#endif
 359
 360#ifdef CONFIG_SPL_BOARD_INIT
 361        spl_board_init();
 362#endif
 363
 364        memset(&spl_image, '\0', sizeof(spl_image));
 365        board_boot_order(spl_boot_list);
 366
 367        if (boot_from_devices(&spl_image, spl_boot_list,
 368                              ARRAY_SIZE(spl_boot_list))) {
 369                puts("SPL: failed to boot from all boot devices\n");
 370                hang();
 371        }
 372
 373        switch (spl_image.os) {
 374        case IH_OS_U_BOOT:
 375                debug("Jumping to U-Boot\n");
 376                break;
 377#ifdef CONFIG_SPL_OS_BOOT
 378        case IH_OS_LINUX:
 379                debug("Jumping to Linux\n");
 380                spl_board_prepare_for_linux();
 381                jump_to_image_linux(&spl_image,
 382                                    (void *)CONFIG_SYS_SPL_ARGS_ADDR);
 383#endif
 384        default:
 385                debug("Unsupported OS image.. Jumping nevertheless..\n");
 386        }
 387#if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SYS_SPL_MALLOC_SIZE)
 388        debug("SPL malloc() used %#lx bytes (%ld KB)\n", gd->malloc_ptr,
 389              gd->malloc_ptr / 1024);
 390#endif
 391
 392        debug("loaded - jumping to U-Boot...");
 393        spl_board_prepare_for_boot();
 394        jump_to_image_no_args(&spl_image);
 395}
 396
 397/*
 398 * This requires UART clocks to be enabled.  In order for this to work the
 399 * caller must ensure that the gd pointer is valid.
 400 */
 401void preloader_console_init(void)
 402{
 403        gd->bd = &bdata;
 404        gd->baudrate = CONFIG_BAUDRATE;
 405
 406        serial_init();          /* serial communications setup */
 407
 408        gd->have_console = 1;
 409
 410        puts("\nU-Boot SPL " PLAIN_VERSION " (" U_BOOT_DATE " - " \
 411                        U_BOOT_TIME ")\n");
 412#ifdef CONFIG_SPL_DISPLAY_PRINT
 413        spl_display_print();
 414#endif
 415}
 416
 417/**
 418 * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
 419 *
 420 * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
 421 * for the main board_init_r() execution. This is typically because we need
 422 * more stack space for things like the MMC sub-system.
 423 *
 424 * This function calculates the stack position, copies the global_data into
 425 * place, sets the new gd (except for ARM, for which setting GD within a C
 426 * function may not always work) and returns the new stack position. The
 427 * caller is responsible for setting up the sp register and, in the case
 428 * of ARM, setting up gd.
 429 *
 430 * All of this is done using the same layout and alignments as done in
 431 * board_init_f_init_reserve() / board_init_f_alloc_reserve().
 432 *
 433 * @return new stack location, or 0 to use the same stack
 434 */
 435ulong spl_relocate_stack_gd(void)
 436{
 437#ifdef CONFIG_SPL_STACK_R
 438        gd_t *new_gd;
 439        ulong ptr = CONFIG_SPL_STACK_R_ADDR;
 440
 441#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
 442        if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
 443                ptr -= CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN;
 444                gd->malloc_base = ptr;
 445                gd->malloc_limit = CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN;
 446                gd->malloc_ptr = 0;
 447        }
 448#endif
 449        /* Get stack position: use 8-byte alignment for ABI compliance */
 450        ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16);
 451        new_gd = (gd_t *)ptr;
 452        memcpy(new_gd, (void *)gd, sizeof(gd_t));
 453#if CONFIG_IS_ENABLED(DM)
 454        dm_fixup_for_gd_move(new_gd);
 455#endif
 456#if !defined(CONFIG_ARM)
 457        gd = new_gd;
 458#endif
 459        return ptr;
 460#else
 461        return 0;
 462#endif
 463}
 464