uboot/arch/arc/lib/bootm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
   4 */
   5
   6#include <common.h>
   7#include <bootstage.h>
   8#include <env.h>
   9#include <image.h>
  10#include <irq_func.h>
  11#include <lmb.h>
  12#include <log.h>
  13#include <asm/cache.h>
  14#include <asm/global_data.h>
  15
  16DECLARE_GLOBAL_DATA_PTR;
  17
  18static ulong get_sp(void)
  19{
  20        ulong ret;
  21
  22        asm("mov %0, sp" : "=r"(ret) : );
  23        return ret;
  24}
  25
  26void arch_lmb_reserve(struct lmb *lmb)
  27{
  28        ulong sp;
  29
  30        /*
  31         * Booting a (Linux) kernel image
  32         *
  33         * Allocate space for command line and board info - the
  34         * address should be as high as possible within the reach of
  35         * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
  36         * memory, which means far enough below the current stack
  37         * pointer.
  38         */
  39        sp = get_sp();
  40        debug("## Current stack ends at 0x%08lx ", sp);
  41
  42        /* adjust sp by 4K to be safe */
  43        sp -= 4096;
  44        lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp));
  45}
  46
  47static int cleanup_before_linux(void)
  48{
  49        disable_interrupts();
  50        sync_n_cleanup_cache_all();
  51
  52        return 0;
  53}
  54
  55__weak int board_prep_linux(bootm_headers_t *images) { return 0; }
  56
  57/* Subcommand: PREP */
  58static int boot_prep_linux(bootm_headers_t *images)
  59{
  60        int ret;
  61
  62        ret = image_setup_linux(images);
  63        if (ret)
  64                return ret;
  65
  66        return board_prep_linux(images);
  67}
  68
  69/* Generic implementation for single core CPU */
  70__weak void board_jump_and_run(ulong entry, int zero, int arch, uint params)
  71{
  72        void (*kernel_entry)(int zero, int arch, uint params);
  73
  74        kernel_entry = (void (*)(int, int, uint))entry;
  75
  76        kernel_entry(zero, arch, params);
  77}
  78
  79/* Subcommand: GO */
  80static void boot_jump_linux(bootm_headers_t *images, int flag)
  81{
  82        ulong kernel_entry;
  83        unsigned int r0, r2;
  84        int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
  85
  86        kernel_entry = images->ep;
  87
  88        debug("## Transferring control to Linux (at address %08lx)...\n",
  89              kernel_entry);
  90        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
  91
  92        printf("\nStarting kernel ...%s\n\n", fake ?
  93               "(fake run for tracing)" : "");
  94        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
  95
  96        if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
  97                r0 = 2;
  98                r2 = (unsigned int)images->ft_addr;
  99        } else {
 100                r0 = 1;
 101                r2 = (unsigned int)env_get("bootargs");
 102        }
 103
 104        cleanup_before_linux();
 105
 106        if (!fake)
 107                board_jump_and_run(kernel_entry, r0, 0, r2);
 108}
 109
 110int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
 111{
 112        /* No need for those on ARC */
 113        if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE))
 114                return -1;
 115
 116        if (flag & BOOTM_STATE_OS_PREP)
 117                return boot_prep_linux(images);
 118
 119        if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
 120                boot_jump_linux(images, flag);
 121                return 0;
 122        }
 123
 124        return -1;
 125}
 126