uboot/lib_sparc/bootm.c
<<
>>
Prefs
   1/* SPARC code for booting linux 2.6
   2 *
   3 * (C) Copyright 2007
   4 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25#include <common.h>
  26#include <command.h>
  27#include <asm/byteorder.h>
  28#include <asm/prom.h>
  29#include <asm/cache.h>
  30
  31#define PRINT_KERNEL_HEADER
  32
  33extern image_header_t header;
  34extern void srmmu_init_cpu(unsigned int entry);
  35extern void prepare_bootargs(char *bootargs);
  36extern int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
  37
  38#ifdef CONFIG_USB_UHCI
  39extern int usb_lowlevel_stop(void);
  40#endif
  41
  42/* sparc kernel argument (the ROM vector) */
  43struct linux_romvec *kernel_arg_promvec;
  44
  45/* page szie is 4k */
  46#define PAGE_SIZE 0x1000
  47#define RAMDISK_IMAGE_START_MASK        0x07FF
  48#define RAMDISK_PROMPT_FLAG             0x8000
  49#define RAMDISK_LOAD_FLAG               0x4000
  50struct __attribute__ ((packed)) {
  51        char traptable[PAGE_SIZE];
  52        char swapper_pg_dir[PAGE_SIZE];
  53        char pg0[PAGE_SIZE];
  54        char pg1[PAGE_SIZE];
  55        char pg2[PAGE_SIZE];
  56        char pg3[PAGE_SIZE];
  57        char empty_bad_page[PAGE_SIZE];
  58        char empty_bad_page_table[PAGE_SIZE];
  59        char empty_zero_page[PAGE_SIZE];
  60        unsigned char hdr[4];   /* ascii "HdrS" */
  61        /* 00.02.06.0b is for Linux kernel 2.6.11 */
  62        unsigned char linuxver_mega_major;
  63        unsigned char linuxver_major;
  64        unsigned char linuxver_minor;
  65        unsigned char linuxver_revision;
  66        /* header version 0x0203 */
  67        unsigned short hdr_ver;
  68        union __attribute__ ((packed)) {
  69                struct __attribute__ ((packed)) {
  70                        unsigned short root_flags;
  71                        unsigned short root_dev;
  72                        unsigned short ram_flags;
  73                        unsigned int sparc_ramdisk_image;
  74                        unsigned int sparc_ramdisk_size;
  75                        unsigned int reboot_command;
  76                        unsigned int resv[3];
  77                        unsigned int end;
  78                } ver_0203;
  79        } hdr_input;
  80} *linux_hdr;
  81
  82/* temporary initrd image holder */
  83image_header_t ihdr;
  84
  85/* boot the linux kernel */
  86void do_bootm_linux(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[],
  87                    bootm_headers_t * images)
  88{
  89        char *bootargs;
  90        ulong ep, load;
  91        ulong initrd_start, initrd_end;
  92        ulong rd_data_start, rd_data_end, rd_len;
  93        unsigned int data, len, checksum;
  94        unsigned int initrd_addr, kernend;
  95        void (*kernel) (struct linux_romvec *, void *);
  96        struct lmb *lmb = images->lmb;
  97        int ret;
  98
  99        if (images->legacy_hdr_valid) {
 100                ep = image_get_ep(images->legacy_hdr_os);
 101                load = image_get_load(images->legacy_hdr_os);
 102#if defined(CONFIG_FIT)
 103        } else if (images->fit_uname_os) {
 104                int ret = fit_image_get_entry(images->fit_hdr_os,
 105                                              images->fit_noffset_os, &ep);
 106                if (ret) {
 107                        puts("Can't get entry point property!\n");
 108                        goto error;
 109                }
 110
 111                ret = fit_image_get_load(images->fit_hdr_os,
 112                                         images->fit_noffset_os, &load);
 113                if (ret) {
 114                        puts("Can't get load address property!\n");
 115                        goto error;
 116                }
 117#endif
 118        } else {
 119                puts("Could not find kernel entry point!\n");
 120                goto error;
 121        }
 122
 123        /* Get virtual address of kernel start */
 124        linux_hdr = (void *)load;
 125
 126        /* */
 127        kernel = (void (*)(struct linux_romvec *, void *))ep;
 128
 129        /* check for a SPARC kernel */
 130        if ((linux_hdr->hdr[0] != 'H') ||
 131            (linux_hdr->hdr[1] != 'd') ||
 132            (linux_hdr->hdr[2] != 'r') || (linux_hdr->hdr[3] != 'S')) {
 133                puts("Error reading header of SPARC Linux kernel, aborting\n");
 134                goto error;
 135        }
 136#ifdef PRINT_KERNEL_HEADER
 137        printf("## Found SPARC Linux kernel %d.%d.%d ...\n",
 138               linux_hdr->linuxver_major,
 139               linux_hdr->linuxver_minor, linux_hdr->linuxver_revision);
 140#endif
 141
 142#ifdef CONFIG_USB_UHCI
 143        usb_lowlevel_stop();
 144#endif
 145
 146        /* set basic boot params in kernel header now that it has been
 147         * extracted and is writeable.
 148         */
 149
 150        /*
 151         * Are we going to use an initrd image?
 152         */
 153        ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_SPARC,
 154                               &rd_data_start, &rd_data_end);
 155        if (ret) {
 156                /* RAM disk found but was corrupt */
 157                puts("RAM Disk corrupt\n");
 158                goto error;
 159        }
 160
 161        /* Calc length of RAM disk, if zero no ramdisk available */
 162        rd_len = rd_data_end - rd_data_start;
 163
 164        if (rd_len) {
 165
 166                /* Reserve the space used by PROM and stack. This is done
 167                 * to avoid that the RAM image is copied over stack or
 168                 * PROM.
 169                 */
 170                lmb_reserve(lmb, CFG_RELOC_MONITOR_BASE, CFG_RAM_END);
 171
 172                ret = boot_ramdisk_high(lmb, rd_data_start, rd_len,
 173                                        &initrd_start, &initrd_end);
 174                if (ret) {
 175                        puts("### Failed to relocate RAM disk\n");
 176                        goto error;
 177                }
 178
 179                /* Update SPARC kernel header so that Linux knows
 180                 * what is going on and where to find RAM disk.
 181                 *
 182                 * Set INITRD Image address relative to RAM Start
 183                 */
 184                linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image =
 185                    initrd_start - CFG_RAM_BASE;
 186                linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = rd_len;
 187                /* Clear READ ONLY flag if set to non-zero */
 188                linux_hdr->hdr_input.ver_0203.root_flags = 1;
 189                /* Set root device to: Root_RAM0 */
 190                linux_hdr->hdr_input.ver_0203.root_dev = 0x100;
 191                linux_hdr->hdr_input.ver_0203.ram_flags = 0;
 192        } else {
 193                /* NOT using RAMDISK image, overwriting kernel defaults */
 194                linux_hdr->hdr_input.ver_0203.sparc_ramdisk_image = 0;
 195                linux_hdr->hdr_input.ver_0203.sparc_ramdisk_size = 0;
 196                /* Leave to kernel defaults
 197                   linux_hdr->hdr_input.ver_0203.root_flags = 1;
 198                   linux_hdr->hdr_input.ver_0203.root_dev = 0;
 199                   linux_hdr->hdr_input.ver_0203.ram_flags = 0;
 200                 */
 201        }
 202
 203        /* Copy bootargs from bootargs variable to kernel readable area */
 204        bootargs = getenv("bootargs");
 205        prepare_bootargs(bootargs);
 206
 207        /* turn on mmu & setup context table & page table for process 0 (kernel) */
 208        srmmu_init_cpu((unsigned int)kernel);
 209
 210        /* Enter SPARC Linux kernel
 211         * From now on the only code in u-boot that will be
 212         * executed is the PROM code.
 213         */
 214        kernel(kernel_arg_promvec, (void *)ep);
 215
 216        /* It will never come to this... */
 217        while (1) ;
 218
 219      error:
 220        do_reset(cmdtp, flag, argc, argv);
 221        return;
 222}
 223