uboot/arch/microblaze/lib/bootm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2007 Michal Simek
   4 * (C) Copyright 2004 Atmark Techno, Inc.
   5 *
   6 * Michal  SIMEK <monstr@monstr.eu>
   7 * Yasushi SHOJI <yashi@atmark-techno.com>
   8 */
   9
  10#include <common.h>
  11#include <bootstage.h>
  12#include <command.h>
  13#include <cpu_func.h>
  14#include <env.h>
  15#include <fdt_support.h>
  16#include <hang.h>
  17#include <image.h>
  18#include <lmb.h>
  19#include <log.h>
  20#include <asm/cache.h>
  21#include <asm/global_data.h>
  22#include <u-boot/zlib.h>
  23#include <asm/byteorder.h>
  24
  25DECLARE_GLOBAL_DATA_PTR;
  26
  27static ulong get_sp(void)
  28{
  29        ulong ret;
  30
  31        asm("addik %0, r1, 0" : "=r"(ret) : );
  32        return ret;
  33}
  34
  35void arch_lmb_reserve(struct lmb *lmb)
  36{
  37        ulong sp, bank_end;
  38        int bank;
  39
  40        /*
  41         * Booting a (Linux) kernel image
  42         *
  43         * Allocate space for command line and board info - the
  44         * address should be as high as possible within the reach of
  45         * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
  46         * memory, which means far enough below the current stack
  47         * pointer.
  48         */
  49        sp = get_sp();
  50        debug("## Current stack ends at 0x%08lx ", sp);
  51
  52        /* adjust sp by 4K to be safe */
  53        sp -= 4096;
  54        for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
  55                if (sp < gd->bd->bi_dram[bank].start)
  56                        continue;
  57                bank_end = gd->bd->bi_dram[bank].start +
  58                        gd->bd->bi_dram[bank].size;
  59                if (sp >= bank_end)
  60                        continue;
  61                lmb_reserve(lmb, sp, bank_end - sp);
  62                break;
  63        }
  64}
  65
  66static void boot_jump_linux(bootm_headers_t *images, int flag)
  67{
  68        void (*thekernel)(char *cmdline, ulong rd, ulong dt);
  69        ulong dt = (ulong)images->ft_addr;
  70        ulong rd_start = images->initrd_start;
  71        ulong cmdline = images->cmdline_start;
  72        int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
  73
  74        thekernel = (void (*)(char *, ulong, ulong))images->ep;
  75
  76        debug("## Transferring control to Linux (at address 0x%08lx) ",
  77              (ulong)thekernel);
  78        debug("cmdline 0x%08lx, ramdisk 0x%08lx, FDT 0x%08lx...\n",
  79              cmdline, rd_start, dt);
  80        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
  81
  82        printf("\nStarting kernel ...%s\n\n", fake ?
  83               "(fake run for tracing)" : "");
  84        bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
  85
  86#ifdef XILINX_USE_DCACHE
  87        flush_cache(0, XILINX_DCACHE_BYTE_SIZE);
  88#endif
  89
  90        if (!fake) {
  91                /*
  92                 * Linux Kernel Parameters (passing device tree):
  93                 * r5: pointer to command line
  94                 * r6: pointer to ramdisk
  95                 * r7: pointer to the fdt, followed by the board info data
  96                 */
  97                thekernel((char *)cmdline, rd_start, dt);
  98                /* does not return */
  99        }
 100}
 101
 102static void boot_prep_linux(bootm_headers_t *images)
 103{
 104        if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
 105                debug("using: FDT\n");
 106                if (image_setup_linux(images)) {
 107                        printf("FDT creation failed! hanging...");
 108                        hang();
 109                }
 110        }
 111}
 112
 113int do_bootm_linux(int flag, int argc, char *const argv[],
 114                   bootm_headers_t *images)
 115{
 116        images->cmdline_start = (ulong)env_get("bootargs");
 117
 118        /* cmdline init is the part of 'prep' and nothing to do for 'bdt' */
 119        if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
 120                return -1;
 121
 122        if (flag & BOOTM_STATE_OS_PREP) {
 123                boot_prep_linux(images);
 124                return 0;
 125        }
 126
 127        if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
 128                boot_jump_linux(images, flag);
 129                return 0;
 130        }
 131
 132        boot_prep_linux(images);
 133        boot_jump_linux(images, flag);
 134        return 1;
 135}
 136