uboot/arch/xtensa/lib/bootm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2008 - 2013 Tensilica Inc.
   4 * (C) Copyright 2014 Cadence Design Systems Inc.
   5 */
   6
   7#include <common.h>
   8#include <bootstage.h>
   9#include <command.h>
  10#include <cpu_func.h>
  11#include <env.h>
  12#include <asm/global_data.h>
  13#include <u-boot/zlib.h>
  14#include <asm/byteorder.h>
  15#include <asm/addrspace.h>
  16#include <asm/bootparam.h>
  17#include <asm/cache.h>
  18#include <image.h>
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22/*
  23 * Setup boot-parameters.
  24 */
  25
  26static struct bp_tag *setup_first_tag(struct bp_tag *params)
  27{
  28        params->id = BP_TAG_FIRST;
  29        params->size = sizeof(long);
  30        *(unsigned long *)&params->data = BP_VERSION;
  31
  32        return bp_tag_next(params);
  33}
  34
  35static struct bp_tag *setup_last_tag(struct bp_tag *params)
  36{
  37        params->id = BP_TAG_LAST;
  38        params->size = 0;
  39
  40        return bp_tag_next(params);
  41}
  42
  43static struct bp_tag *setup_memory_tag(struct bp_tag *params)
  44{
  45        struct meminfo *mem;
  46
  47        params->id = BP_TAG_MEMORY;
  48        params->size = sizeof(struct meminfo);
  49        mem = (struct meminfo *)params->data;
  50        mem->type = MEMORY_TYPE_CONVENTIONAL;
  51        mem->start = PHYSADDR(gd->ram_base);
  52        mem->end = PHYSADDR(gd->ram_base + gd->ram_size);
  53
  54        printf("   MEMORY:          tag:0x%04x, type:0X%lx, start:0X%lx, end:0X%lx\n",
  55               BP_TAG_MEMORY, mem->type, mem->start, mem->end);
  56
  57        return bp_tag_next(params);
  58}
  59
  60static struct bp_tag *setup_commandline_tag(struct bp_tag *params,
  61                                            char *cmdline)
  62{
  63        int len;
  64
  65        if (!cmdline)
  66                return params;
  67
  68        len = strlen(cmdline);
  69
  70        params->id = BP_TAG_COMMAND_LINE;
  71        params->size = (len + 3) & -4;
  72        strcpy((char *)params->data, cmdline);
  73
  74        printf("   COMMAND_LINE:    tag:0x%04x, size:%u, data:'%s'\n",
  75               BP_TAG_COMMAND_LINE, params->size, cmdline);
  76
  77        return bp_tag_next(params);
  78}
  79
  80static struct bp_tag *setup_ramdisk_tag(struct bp_tag *params,
  81                                        unsigned long rd_start,
  82                                        unsigned long rd_end)
  83{
  84        struct meminfo *mem;
  85
  86        if (rd_start == rd_end)
  87                return params;
  88
  89        /* Add a single banked memory */
  90
  91        params->id = BP_TAG_INITRD;
  92        params->size = sizeof(struct meminfo);
  93
  94        mem = (struct meminfo *)params->data;
  95        mem->type =  MEMORY_TYPE_CONVENTIONAL;
  96        mem->start = PHYSADDR(rd_start);
  97        mem->end = PHYSADDR(rd_end);
  98
  99        printf("   INITRD:          tag:0x%x, type:0X%04lx, start:0X%lx, end:0X%lx\n",
 100               BP_TAG_INITRD, mem->type, mem->start, mem->end);
 101
 102        return bp_tag_next(params);
 103}
 104
 105static struct bp_tag *setup_serial_tag(struct bp_tag *params)
 106{
 107        params->id = BP_TAG_SERIAL_BAUDRATE;
 108        params->size = sizeof(unsigned long);
 109        params->data[0] = gd->baudrate;
 110
 111        printf("   SERIAL_BAUDRATE: tag:0x%04x, size:%u, baudrate:%lu\n",
 112               BP_TAG_SERIAL_BAUDRATE, params->size, params->data[0]);
 113
 114        return bp_tag_next(params);
 115}
 116
 117#ifdef CONFIG_OF_LIBFDT
 118
 119static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start)
 120{
 121        params->id = BP_TAG_FDT;
 122        params->size = sizeof(unsigned long);
 123        params->data[0] = (unsigned long)fdt_start;
 124
 125        printf("   FDT:             tag:0x%04x, size:%u, start:0x%lx\n",
 126               BP_TAG_FDT, params->size, params->data[0]);
 127
 128        return bp_tag_next(params);
 129}
 130
 131#endif
 132
 133/*
 134 * Boot Linux.
 135 */
 136
 137int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
 138{
 139        struct bp_tag *params, *params_start;
 140        ulong initrd_start, initrd_end;
 141        char *commandline = env_get("bootargs");
 142
 143        if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)))
 144                return 0;
 145
 146        show_boot_progress(15);
 147
 148        if (images->rd_start) {
 149                initrd_start = images->rd_start;
 150                initrd_end = images->rd_end;
 151        } else {
 152                initrd_start = 0;
 153                initrd_end = 0;
 154        }
 155
 156        params_start = (struct bp_tag *)gd->bd->bi_boot_params;
 157        params = params_start;
 158        params = setup_first_tag(params);
 159        params = setup_memory_tag(params);
 160        params = setup_commandline_tag(params, commandline);
 161        params = setup_serial_tag(params);
 162
 163        if (initrd_start)
 164                params = setup_ramdisk_tag(params, initrd_start, initrd_end);
 165
 166#ifdef CONFIG_OF_LIBFDT
 167        if (images->ft_addr)
 168                params = setup_fdt_tag(params, images->ft_addr);
 169#endif
 170
 171        printf("\n");
 172
 173        params = setup_last_tag(params);
 174
 175        show_boot_progress(15);
 176
 177        printf("Transferring Control to Linux @0x%08lx ...\n\n",
 178               (ulong)images->ep);
 179
 180        flush_dcache_range((unsigned long)params_start, (unsigned long)params);
 181
 182        if (flag & BOOTM_STATE_OS_FAKE_GO)
 183                return 0;
 184
 185        /*
 186         * _start() in vmlinux expects boot params in register a2.
 187         * NOTE:
 188         *    Disable/delete your u-boot breakpoints before stepping into linux.
 189         */
 190        asm volatile ("mov      a2, %0\n\t"
 191                      "jx       %1\n\t"
 192                      : : "a" (params_start), "a" (images->ep)
 193                      : "a2");
 194
 195        /* Does not return */
 196
 197        return 1;
 198}
 199
 200static ulong get_sp(void)
 201{
 202        ulong ret;
 203
 204        asm("mov %0, a1" : "=r"(ret) : );
 205        return ret;
 206}
 207
 208void arch_lmb_reserve(struct lmb *lmb)
 209{
 210        arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096);
 211}
 212