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