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