uboot/lib_arm/bootm.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Marius Groeger <mgroeger@sysgo.de>
   5 *
   6 * Copyright (C) 2001  Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 *
  22 */
  23
  24#include <common.h>
  25#include <command.h>
  26#include <image.h>
  27#include <u-boot/zlib.h>
  28#include <asm/byteorder.h>
  29
  30DECLARE_GLOBAL_DATA_PTR;
  31
  32#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
  33    defined (CONFIG_CMDLINE_TAG) || \
  34    defined (CONFIG_INITRD_TAG) || \
  35    defined (CONFIG_SERIAL_TAG) || \
  36    defined (CONFIG_REVISION_TAG) || \
  37    defined (CONFIG_VFD) || \
  38    defined (CONFIG_LCD)
  39static void setup_start_tag (bd_t *bd);
  40
  41# ifdef CONFIG_SETUP_MEMORY_TAGS
  42static void setup_memory_tags (bd_t *bd);
  43# endif
  44static void setup_commandline_tag (bd_t *bd, char *commandline);
  45
  46# ifdef CONFIG_INITRD_TAG
  47static void setup_initrd_tag (bd_t *bd, ulong initrd_start,
  48                              ulong initrd_end);
  49# endif
  50static void setup_end_tag (bd_t *bd);
  51
  52# if defined (CONFIG_VFD) || defined (CONFIG_LCD)
  53static void setup_videolfb_tag (gd_t *gd);
  54# endif
  55
  56static struct tag *params;
  57#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
  58
  59int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
  60{
  61        bd_t    *bd = gd->bd;
  62        char    *s;
  63        int     machid = bd->bi_arch_number;
  64        void    (*theKernel)(int zero, int arch, uint params);
  65
  66#ifdef CONFIG_CMDLINE_TAG
  67        char *commandline = getenv ("bootargs");
  68#endif
  69
  70        if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
  71                return 1;
  72
  73        theKernel = (void (*)(int, int, uint))images->ep;
  74
  75        s = getenv ("machid");
  76        if (s) {
  77                machid = simple_strtoul (s, NULL, 16);
  78                printf ("Using machid 0x%x from environment\n", machid);
  79        }
  80
  81        show_boot_progress (15);
  82
  83        debug ("## Transferring control to Linux (at address %08lx) ...\n",
  84               (ulong) theKernel);
  85
  86#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
  87    defined (CONFIG_CMDLINE_TAG) || \
  88    defined (CONFIG_INITRD_TAG) || \
  89    defined (CONFIG_SERIAL_TAG) || \
  90    defined (CONFIG_REVISION_TAG) || \
  91    defined (CONFIG_LCD) || \
  92    defined (CONFIG_VFD)
  93        setup_start_tag (bd);
  94#ifdef CONFIG_SERIAL_TAG
  95        setup_serial_tag (&params);
  96#endif
  97#ifdef CONFIG_REVISION_TAG
  98        setup_revision_tag (&params);
  99#endif
 100#ifdef CONFIG_SETUP_MEMORY_TAGS
 101        setup_memory_tags (bd);
 102#endif
 103#ifdef CONFIG_CMDLINE_TAG
 104        setup_commandline_tag (bd, commandline);
 105#endif
 106#ifdef CONFIG_INITRD_TAG
 107        if (images->rd_start && images->rd_end)
 108                setup_initrd_tag (bd, images->rd_start, images->rd_end);
 109#endif
 110#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
 111        setup_videolfb_tag ((gd_t *) gd);
 112#endif
 113        setup_end_tag (bd);
 114#endif
 115
 116        /* we assume that the kernel is in place */
 117        printf ("\nStarting kernel ...\n\n");
 118
 119#ifdef CONFIG_USB_DEVICE
 120        {
 121                extern void udc_disconnect (void);
 122                udc_disconnect ();
 123        }
 124#endif
 125
 126        cleanup_before_linux ();
 127
 128        theKernel (0, machid, bd->bi_boot_params);
 129        /* does not return */
 130
 131        return 1;
 132}
 133
 134
 135#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
 136    defined (CONFIG_CMDLINE_TAG) || \
 137    defined (CONFIG_INITRD_TAG) || \
 138    defined (CONFIG_SERIAL_TAG) || \
 139    defined (CONFIG_REVISION_TAG) || \
 140    defined (CONFIG_LCD) || \
 141    defined (CONFIG_VFD)
 142static void setup_start_tag (bd_t *bd)
 143{
 144        params = (struct tag *) bd->bi_boot_params;
 145
 146        params->hdr.tag = ATAG_CORE;
 147        params->hdr.size = tag_size (tag_core);
 148
 149        params->u.core.flags = 0;
 150        params->u.core.pagesize = 0;
 151        params->u.core.rootdev = 0;
 152
 153        params = tag_next (params);
 154}
 155
 156
 157#ifdef CONFIG_SETUP_MEMORY_TAGS
 158static void setup_memory_tags (bd_t *bd)
 159{
 160        int i;
 161
 162        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 163                params->hdr.tag = ATAG_MEM;
 164                params->hdr.size = tag_size (tag_mem32);
 165
 166                params->u.mem.start = bd->bi_dram[i].start;
 167                params->u.mem.size = bd->bi_dram[i].size;
 168
 169                params = tag_next (params);
 170        }
 171}
 172#endif /* CONFIG_SETUP_MEMORY_TAGS */
 173
 174
 175static void setup_commandline_tag (bd_t *bd, char *commandline)
 176{
 177        char *p;
 178
 179        if (!commandline)
 180                return;
 181
 182        /* eat leading white space */
 183        for (p = commandline; *p == ' '; p++);
 184
 185        /* skip non-existent command lines so the kernel will still
 186         * use its default command line.
 187         */
 188        if (*p == '\0')
 189                return;
 190
 191        params->hdr.tag = ATAG_CMDLINE;
 192        params->hdr.size =
 193                (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
 194
 195        strcpy (params->u.cmdline.cmdline, p);
 196
 197        params = tag_next (params);
 198}
 199
 200
 201#ifdef CONFIG_INITRD_TAG
 202static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end)
 203{
 204        /* an ATAG_INITRD node tells the kernel where the compressed
 205         * ramdisk can be found. ATAG_RDIMG is a better name, actually.
 206         */
 207        params->hdr.tag = ATAG_INITRD2;
 208        params->hdr.size = tag_size (tag_initrd);
 209
 210        params->u.initrd.start = initrd_start;
 211        params->u.initrd.size = initrd_end - initrd_start;
 212
 213        params = tag_next (params);
 214}
 215#endif /* CONFIG_INITRD_TAG */
 216
 217
 218#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
 219extern ulong calc_fbsize (void);
 220static void setup_videolfb_tag (gd_t *gd)
 221{
 222        /* An ATAG_VIDEOLFB node tells the kernel where and how large
 223         * the framebuffer for video was allocated (among other things).
 224         * Note that a _physical_ address is passed !
 225         *
 226         * We only use it to pass the address and size, the other entries
 227         * in the tag_videolfb are not of interest.
 228         */
 229        params->hdr.tag = ATAG_VIDEOLFB;
 230        params->hdr.size = tag_size (tag_videolfb);
 231
 232        params->u.videolfb.lfb_base = (u32) gd->fb_base;
 233        /* Fb size is calculated according to parameters for our panel
 234         */
 235        params->u.videolfb.lfb_size = calc_fbsize();
 236
 237        params = tag_next (params);
 238}
 239#endif /* CONFIG_VFD || CONFIG_LCD */
 240
 241#ifdef CONFIG_SERIAL_TAG
 242void setup_serial_tag (struct tag **tmp)
 243{
 244        struct tag *params = *tmp;
 245        struct tag_serialnr serialnr;
 246        void get_board_serial(struct tag_serialnr *serialnr);
 247
 248        get_board_serial(&serialnr);
 249        params->hdr.tag = ATAG_SERIAL;
 250        params->hdr.size = tag_size (tag_serialnr);
 251        params->u.serialnr.low = serialnr.low;
 252        params->u.serialnr.high= serialnr.high;
 253        params = tag_next (params);
 254        *tmp = params;
 255}
 256#endif
 257
 258#ifdef CONFIG_REVISION_TAG
 259void setup_revision_tag(struct tag **in_params)
 260{
 261        u32 rev = 0;
 262        u32 get_board_rev(void);
 263
 264        rev = get_board_rev();
 265        params->hdr.tag = ATAG_REVISION;
 266        params->hdr.size = tag_size (tag_revision);
 267        params->u.revision.rev = rev;
 268        params = tag_next (params);
 269}
 270#endif  /* CONFIG_REVISION_TAG */
 271
 272
 273static void setup_end_tag (bd_t *bd)
 274{
 275        params->hdr.tag = ATAG_NONE;
 276        params->hdr.size = 0;
 277}
 278
 279#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
 280