1 /* $NetBSD: bootxx.c,v 1.5 2009/02/04 15:22:13 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifdef _STANDALONE 33 #include <lib/libsa/stand.h> 34 #include <lib/libkern/libkern.h> 35 #endif 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include "bootxx.h" 40 41 #include <sys/exec_ecoff.h> 42 #include <sys/exec_elf.h> 43 44 #include <machine/sector.h> 45 #include <machine/sbd.h> 46 47 #include "common.h" 48 49 #define FILHSZ (sizeof(struct ecoff_filehdr)) 50 #define SCNHSZ (sizeof(struct ecoff_scnhdr)) 51 #define N_TXTOFF(f, a) \ 52 ((a)->vstamp < 23 ? \ 53 ((FILHSZ +(f)->f_opthdr +(f)->f_nscns * SCNHSZ + 7) & ~7) : \ 54 ((FILHSZ +(f)->f_opthdr +(f)->f_nscns * SCNHSZ + 15) & ~15)) 55 56 int main(void); 57 int loader(const char *, uint32_t *); 58 int load_elf(uint8_t *, uint32_t *); 59 int load_coff(uint8_t *, uint32_t *); 60 int dk_read(int, int, void *); 61 62 const char *errmsg[] = { 63 [BERR_PDINFO] = "No PDINFO", 64 [BERR_RDVTOC] = "VTOC read error", 65 [BERR_VTOC] = "VTOC bad magic", 66 [BERR_NOBFS] = "No BFS partition", 67 [BERR_RDINODE] = "I-node read error", 68 [BERR_NOROOT] = "No root", 69 [BERR_RDDIRENT] = "Dirent read error", 70 [BERR_NOFILE] = "No such a file", 71 [BERR_RDFILE] = "File read error", 72 [BERR_FILEMAGIC] = "Bad file magic", 73 [BERR_AOUTHDR] = "Not a OMAGIC", 74 [BERR_ELFHDR] = "Not a ELF", 75 [BERR_TARHDR] = "Read tar file", 76 [BERR_TARMAGIC] = "Bad tar magic", 77 }; 78 79 const char *boottab[] = { 80 "boot", /* NetBSD (bfs,ustarfs) */ 81 "iopboot", /* EWS-UX (bfs) */ 82 0 /* terminate */ 83 }; 84 85 int __dk_unit, __dk_type, __spb; 86 bool (*fd_position)(uint32_t, uint32_t *, int *); 87 88 int 89 main(void) 90 { 91 char msg[] = "[+++] NetBSD/ews4800mips >> "; 92 const char *p; 93 const char **boot; 94 uint32_t entry; 95 int err; 96 97 #ifdef _STANDALONE 98 int i, fd_format; 99 100 boot_device(&__dk_type, &__dk_unit, &fd_format); 101 msg[1] = __dk_type + '0'; 102 msg[2] = __dk_unit + '0'; 103 msg[3] = FS_SIGNATURE; 104 for (i = 0; msg[i] != 0; i++) 105 ROM_PUTC(32 + i * 12, 536, msg[i]); 106 107 if (__dk_type == NVSRAM_BOOTDEV_FLOPPYDISK) { 108 fd_position = blk_to_2d_position; 109 if (fd_format == FD_FORMAT_2D) { 110 fd_position = blk_to_2d_position; 111 __spb = 2; /* 256bytes/sector */ 112 } else { 113 fd_position = blk_to_2hd_position; 114 __dk_unit |= 0x1000000; /* | 2HD flag */ 115 __spb = 1; 116 } 117 } 118 #else 119 printf("%s\n", msg); 120 sector_init("/dev/rsd1p", DEV_BSIZE); 121 sector_read(SDBOOT_PDINFOADDR, PDINFO_SECTOR); 122 #endif 123 124 for (boot = boottab; *boot; boot++) { 125 if ((err = loader(*boot, &entry)) == 0) { 126 #ifdef _STANDALONE 127 ROM_PUTC(0, 0, '\n'); 128 ROM_PUTC(0, 0, '\r'); 129 return entry; 130 #else 131 printf("entry=%p\n", (void *)entry); 132 sector_fini(); 133 return 0; 134 #endif 135 } 136 p = errmsg[err]; 137 #ifdef _STANDALONE 138 for (i = 0; p[i] != 0; i++) 139 ROM_PUTC(600 + i * 12, 536, p[i]); 140 #else 141 DPRINTF("***ERROR *** %s\n", p); 142 #endif 143 } 144 145 #ifdef _STANDALONE 146 while (/*CONSTCOND*/1) 147 ; 148 /* NOTREACHED */ 149 #else 150 sector_fini(); 151 #endif 152 return 0; 153 } 154 155 int 156 loader(const char *fname, uint32_t *entry) 157 { 158 int err; 159 uint16_t mag; 160 size_t sz; 161 #ifdef _STANDALONE 162 int i; 163 164 for (i = 0; fname[i] != 0; i++) 165 ROM_PUTC(380 + i * 12, 536, fname[i]); 166 #else 167 printf("%s\n", fname); 168 #endif 169 170 if ((err = fileread(fname, &sz)) != 0) 171 return err; 172 173 DPRINTF("%s found. %d bytes.\n", fname, sz); 174 175 mag = *(uint16_t *)SDBOOT_SCRATCHADDR; 176 if (mag == 0x7f45) 177 return load_elf((uint8_t *)SDBOOT_SCRATCHADDR, entry); 178 else if (mag == ECOFF_MAGIC_MIPSEB) 179 return load_coff((uint8_t *)SDBOOT_SCRATCHADDR, entry); 180 181 return BERR_FILEMAGIC; 182 } 183 184 int 185 load_elf(uint8_t *buf, uint32_t *entry) 186 { 187 Elf32_Ehdr *e = (void *)buf; 188 Elf32_Phdr *p; 189 190 if (e->e_ident[EI_MAG2] != 'L' || e->e_ident[EI_MAG3] != 'F' || 191 e->e_ident[EI_CLASS] != ELFCLASS32 || 192 e->e_ident[EI_DATA] != ELFDATA2MSB || 193 e->e_type != ET_EXEC || 194 e->e_machine != EM_MIPS) 195 return BERR_ELFHDR; 196 197 BASSERT(e->e_phentsize == sizeof(Elf32_Phdr)); 198 p = (void *)(buf + e->e_phoff); 199 #ifdef _STANDALONE 200 memcpy((void *)p->p_vaddr, buf + p->p_offset, p->p_filesz); 201 p++; 202 memcpy((void *)p->p_vaddr, buf + p->p_offset, p->p_filesz); 203 #else 204 DPRINTF("ELF entry point 0x%08x\n", e->e_entry); 205 DPRINTF("[text] 0x%08x 0x%x %dbyte.\n", p->p_vaddr, p->p_offset, 206 p->p_filesz); 207 p++; 208 DPRINTF("[data] 0x%08x 0x%x %dbyte.\n", p->p_vaddr, p->p_offset, 209 p->p_filesz); 210 #endif 211 *entry = e->e_entry; 212 213 return 0; 214 } 215 216 int 217 load_coff(uint8_t *p, uint32_t *entry) 218 { 219 struct ecoff_exechdr *eh = (void *)p; 220 struct ecoff_aouthdr *a = &eh->a; 221 struct ecoff_filehdr *f = &eh->f; 222 223 if (a->magic != ECOFF_OMAGIC) 224 return BERR_AOUTHDR; 225 226 p += N_TXTOFF(f, a); 227 DPRINTF("file offset = 0x%x\n", N_TXTOFF(f, a)); 228 #ifdef _STANDALONE 229 memcpy((void *)a->text_start, p, a->tsize); 230 memcpy((void *)a->data_start, p + a->tsize, a->dsize); 231 #else 232 DPRINTF("COFF entry point 0x%08lx\n", a->entry); 233 DPRINTF("[text] 0x%08lx %ld byte.\n", a->text_start, a->tsize); 234 DPRINTF("[data] 0x%08lx %ld byte.\n", a->data_start, a->dsize); 235 #endif 236 237 *entry = a->entry; 238 239 return 0; 240 } 241 242 int 243 dk_read(int sector, int count, void *buf) 244 { 245 #ifdef _STANDALONE 246 int cnt; 247 uint32_t pos; 248 uint8_t *p = buf; 249 250 if (__dk_type == NVSRAM_BOOTDEV_HARDDISK) { /* DISK */ 251 if ((ROM_DK_READ(__dk_unit, sector, count, p) & 0x7f) != 0) 252 return 1; 253 } else { /* FD */ 254 while (count > 0) { 255 fd_position(sector, &pos, &cnt); 256 if (cnt > count) 257 cnt = count; 258 if ((ROM_FD_READ(__dk_unit, pos, cnt * __spb, p) 259 & 0x7f) != 0) 260 return 1; 261 count -= cnt; 262 sector += cnt; 263 p += 512 * cnt; 264 } 265 } 266 #else 267 sector_read_n(buf, sector, count); 268 #endif 269 return 0; 270 } 271