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