uboot/arch/nds32/lib/bootm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2011 Andes Technology Corporation
   4 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
   5 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
   6 */
   7
   8#include <common.h>
   9#include <bootstage.h>
  10#include <command.h>
  11#include <env.h>
  12#include <hang.h>
  13#include <image.h>
  14#include <log.h>
  15#include <asm/global_data.h>
  16#include <u-boot/zlib.h>
  17#include <asm/byteorder.h>
  18#include <asm/bootm.h>
  19
  20DECLARE_GLOBAL_DATA_PTR;
  21
  22#ifdef CONFIG_SUPPORT_PASSING_ATAGS
  23static void setup_start_tag(struct bd_info *bd);
  24
  25# ifdef CONFIG_SETUP_MEMORY_TAGS
  26static void setup_memory_tags(struct bd_info *bd);
  27# endif
  28static void setup_commandline_tag(struct bd_info *bd, char *commandline);
  29
  30# ifdef CONFIG_INITRD_TAG
  31static void setup_initrd_tag(struct bd_info *bd, ulong initrd_start,
  32                             ulong initrd_end);
  33# endif
  34static void setup_end_tag(struct bd_info *bd);
  35
  36static struct tag *params;
  37#endif /* CONFIG_SUPPORT_PASSING_ATAGS */
  38
  39int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
  40{
  41        struct bd_info  *bd = gd->bd;
  42        char    *s;
  43        int     machid = bd->bi_arch_number;
  44        void    (*theKernel)(int zero, int arch, uint params);
  45
  46#ifdef CONFIG_CMDLINE_TAG
  47        char *commandline = env_get("bootargs");
  48#endif
  49
  50        /*
  51         * allow the PREP bootm subcommand, it is required for bootm to work
  52         */
  53        if (flag & BOOTM_STATE_OS_PREP)
  54                return 0;
  55
  56        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
  57                return 1;
  58
  59        theKernel = (void (*)(int, int, uint))images->ep;
  60
  61        s = env_get("machid");
  62        if (s) {
  63                machid = hextoul(s, NULL);
  64                printf("Using machid 0x%x from environment\n", machid);
  65        }
  66
  67        bootstage_mark(BOOTSTAGE_ID_RUN_OS);
  68
  69        debug("## Transferring control to Linux (at address %08lx) ...\n",
  70               (ulong)theKernel);
  71
  72        if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) {
  73#ifdef CONFIG_OF_LIBFDT
  74                debug("using: FDT\n");
  75                if (image_setup_linux(images)) {
  76                        printf("FDT creation failed! hanging...");
  77                        hang();
  78                }
  79#endif
  80        } else if (BOOTM_ENABLE_TAGS) {
  81#ifdef CONFIG_SUPPORT_PASSING_ATAGS
  82        setup_start_tag(bd);
  83#ifdef CONFIG_SERIAL_TAG
  84        setup_serial_tag(&params);
  85#endif
  86#ifdef CONFIG_REVISION_TAG
  87        setup_revision_tag(&params);
  88#endif
  89#ifdef CONFIG_SETUP_MEMORY_TAGS
  90        setup_memory_tags(bd);
  91#endif
  92#ifdef CONFIG_CMDLINE_TAG
  93        setup_commandline_tag(bd, commandline);
  94#endif
  95#ifdef CONFIG_INITRD_TAG
  96        if (images->rd_start && images->rd_end)
  97                setup_initrd_tag(bd, images->rd_start, images->rd_end);
  98#endif
  99        setup_end_tag(bd);
 100#endif
 101
 102        /* we assume that the kernel is in place */
 103        printf("\nStarting kernel ...\n\n");
 104
 105#ifdef CONFIG_USB_DEVICE
 106        {
 107                extern void udc_disconnect(void);
 108                udc_disconnect();
 109        }
 110#endif
 111        }
 112        cleanup_before_linux();
 113        if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len)
 114                theKernel(0, machid, (unsigned long)images->ft_addr);
 115        else
 116                theKernel(0, machid, bd->bi_boot_params);
 117        /* does not return */
 118
 119        return 1;
 120}
 121
 122#ifdef CONFIG_SUPPORT_PASSING_ATAGS
 123static void setup_start_tag(struct bd_info *bd)
 124{
 125        params = (struct tag *)bd->bi_boot_params;
 126
 127        params->hdr.tag = ATAG_CORE;
 128        params->hdr.size = tag_size(tag_core);
 129
 130        params->u.core.flags = 0;
 131        params->u.core.pagesize = 0;
 132        params->u.core.rootdev = 0;
 133
 134        params = tag_next(params);
 135}
 136
 137#ifdef CONFIG_SETUP_MEMORY_TAGS
 138static void setup_memory_tags(struct bd_info *bd)
 139{
 140        int i;
 141
 142        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 143                params->hdr.tag = ATAG_MEM;
 144                params->hdr.size = tag_size(tag_mem32);
 145
 146                params->u.mem.start = bd->bi_dram[i].start;
 147                params->u.mem.size = bd->bi_dram[i].size;
 148
 149                params = tag_next(params);
 150        }
 151}
 152#endif /* CONFIG_SETUP_MEMORY_TAGS */
 153
 154static void setup_commandline_tag(struct bd_info *bd, char *commandline)
 155{
 156        char *p;
 157
 158        if (!commandline)
 159                return;
 160
 161        /* eat leading white space */
 162        for (p = commandline; *p == ' '; p++)
 163                ;
 164
 165        /* skip non-existent command lines so the kernel will still
 166         * use its default command line.
 167         */
 168        if (*p == '\0')
 169                return;
 170
 171        params->hdr.tag = ATAG_CMDLINE;
 172        params->hdr.size =
 173                (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2;
 174
 175        strcpy(params->u.cmdline.cmdline, p)
 176                ;
 177
 178        params = tag_next(params);
 179}
 180
 181#ifdef CONFIG_INITRD_TAG
 182static void setup_initrd_tag(struct bd_info *bd, ulong initrd_start,
 183                             ulong initrd_end)
 184{
 185        /* an ATAG_INITRD node tells the kernel where the compressed
 186         * ramdisk can be found. ATAG_RDIMG is a better name, actually.
 187         */
 188        params->hdr.tag = ATAG_INITRD2;
 189        params->hdr.size = tag_size(tag_initrd);
 190
 191        params->u.initrd.start = initrd_start;
 192        params->u.initrd.size = initrd_end - initrd_start;
 193
 194        params = tag_next(params);
 195}
 196#endif /* CONFIG_INITRD_TAG */
 197
 198#ifdef CONFIG_SERIAL_TAG
 199void setup_serial_tag(struct tag **tmp)
 200{
 201        struct tag *params = *tmp;
 202        struct tag_serialnr serialnr;
 203        void get_board_serial(struct tag_serialnr *serialnr);
 204
 205        get_board_serial(&serialnr);
 206        params->hdr.tag = ATAG_SERIAL;
 207        params->hdr.size = tag_size(tag_serialnr);
 208        params->u.serialnr.low = serialnr.low;
 209        params->u.serialnr.high = serialnr.high;
 210        params = tag_next(params);
 211        *tmp = params;
 212}
 213#endif
 214
 215#ifdef CONFIG_REVISION_TAG
 216void setup_revision_tag(struct tag **in_params)
 217{
 218        u32 rev = 0;
 219        u32 get_board_rev(void);
 220
 221        rev = get_board_rev();
 222        params->hdr.tag = ATAG_REVISION;
 223        params->hdr.size = tag_size(tag_revision);
 224        params->u.revision.rev = rev;
 225        params = tag_next(params);
 226}
 227#endif  /* CONFIG_REVISION_TAG */
 228
 229static void setup_end_tag(struct bd_info *bd)
 230{
 231        params->hdr.tag = ATAG_NONE;
 232        params->hdr.size = 0;
 233}
 234
 235#endif /* CONFIG_SUPPORT_PASSING_ATAGS */
 236
 237static ulong get_sp(void)
 238{
 239        ulong ret;
 240
 241        asm("move %0, $sp" : "=r"(ret) : );
 242        return ret;
 243}
 244
 245void arch_lmb_reserve(struct lmb *lmb)
 246{
 247        arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096);
 248}
 249