1 /* $NetBSD: bootxx.c,v 1.6 2020/06/07 03:00:53 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 IS_TEXT(p) (p.p_flags & PF_X) 50 #define IS_DATA(p) ((p.p_flags & PF_X) == 0) 51 #define IS_BSS(p) (p.p_filesz < p.p_memsz) 52 53 #define FILHSZ (sizeof(struct ecoff_filehdr)) 54 #define SCNHSZ (sizeof(struct ecoff_scnhdr)) 55 #define N_TXTOFF(f, a) \ 56 ((a)->vstamp < 23 ? \ 57 ((FILHSZ +(f)->f_opthdr +(f)->f_nscns * SCNHSZ + 7) & ~7) : \ 58 ((FILHSZ +(f)->f_opthdr +(f)->f_nscns * SCNHSZ + 15) & ~15)) 59 60 int main(void); 61 int loader(const char *, uint32_t *); 62 int load_elf(uint8_t *, uint32_t *); 63 int load_coff(uint8_t *, uint32_t *); 64 int dk_read(int, int, void *); 65 66 const char *errmsg[] = { 67 [BERR_PDINFO] = "No PDINFO", 68 [BERR_RDVTOC] = "VTOC read error", 69 [BERR_VTOC] = "VTOC bad magic", 70 [BERR_NOBFS] = "No BFS partition", 71 [BERR_RDINODE] = "I-node read error", 72 [BERR_NOROOT] = "No root", 73 [BERR_RDDIRENT] = "Dirent read error", 74 [BERR_NOFILE] = "No such a file", 75 [BERR_RDFILE] = "File read error", 76 [BERR_FILEMAGIC] = "Bad file magic", 77 [BERR_AOUTHDR] = "Not a OMAGIC", 78 [BERR_ELFHDR] = "Not a ELF", 79 [BERR_TARHDR] = "Read tar file", 80 [BERR_TARMAGIC] = "Bad tar magic", 81 }; 82 83 const char *boottab[] = { 84 "boot", /* NetBSD (bfs,ustarfs) */ 85 "iopboot", /* EWS-UX (bfs) */ 86 0 /* terminate */ 87 }; 88 89 int __dk_unit, __dk_type, __spb; 90 bool (*fd_position)(uint32_t, uint32_t *, int *); 91 92 int 93 main(void) 94 { 95 char msg[] = "[+++] NetBSD/ews4800mips >> "; 96 const char *p; 97 const char **boot; 98 uint32_t entry; 99 int err; 100 101 #ifdef _STANDALONE 102 int i, fd_format; 103 104 boot_device(&__dk_type, &__dk_unit, &fd_format); 105 msg[1] = __dk_type + '0'; 106 msg[2] = __dk_unit + '0'; 107 msg[3] = FS_SIGNATURE; 108 for (i = 0; msg[i] != 0; i++) 109 ROM_PUTC(32 + i * 12, 536, msg[i]); 110 111 if (__dk_type == NVSRAM_BOOTDEV_FLOPPYDISK) { 112 fd_position = blk_to_2d_position; 113 if (fd_format == FD_FORMAT_2D) { 114 fd_position = blk_to_2d_position; 115 __spb = 2; /* 256bytes/sector */ 116 } else { 117 fd_position = blk_to_2hd_position; 118 __dk_unit |= 0x1000000; /* | 2HD flag */ 119 __spb = 1; 120 } 121 } 122 #else 123 printf("%s\n", msg); 124 sector_init("/dev/rsd1p", DEV_BSIZE); 125 sector_read(SDBOOT_PDINFOADDR, PDINFO_SECTOR); 126 #endif 127 128 for (boot = boottab; *boot; boot++) { 129 if ((err = loader(*boot, &entry)) == 0) { 130 #ifdef _STANDALONE 131 ROM_PUTC(0, 0, '\n'); 132 ROM_PUTC(0, 0, '\r'); 133 return entry; 134 #else 135 printf("entry=%p\n", (void *)entry); 136 sector_fini(); 137 return 0; 138 #endif 139 } 140 p = errmsg[err]; 141 #ifdef _STANDALONE 142 for (i = 0; p[i] != 0; i++) 143 ROM_PUTC(600 + i * 12, 536, p[i]); 144 #else 145 DPRINTF("***ERROR *** %s\n", p); 146 #endif 147 } 148 149 #ifdef _STANDALONE 150 while (/*CONSTCOND*/1) 151 ; 152 /* NOTREACHED */ 153 #else 154 sector_fini(); 155 #endif 156 return 0; 157 } 158 159 int 160 loader(const char *fname, uint32_t *entry) 161 { 162 int err; 163 uint16_t mag; 164 size_t sz; 165 #ifdef _STANDALONE 166 int i; 167 168 for (i = 0; fname[i] != 0; i++) 169 ROM_PUTC(380 + i * 12, 536, fname[i]); 170 #else 171 printf("%s\n", fname); 172 #endif 173 174 if ((err = fileread(fname, &sz)) != 0) 175 return err; 176 177 DPRINTF("%s found. %d bytes.\n", fname, sz); 178 179 mag = *(uint16_t *)SDBOOT_SCRATCHADDR; 180 if (mag == 0x7f45) 181 return load_elf((uint8_t *)SDBOOT_SCRATCHADDR, entry); 182 else if (mag == ECOFF_MAGIC_MIPSEB) 183 return load_coff((uint8_t *)SDBOOT_SCRATCHADDR, entry); 184 185 return BERR_FILEMAGIC; 186 } 187 188 int 189 load_elf(uint8_t *buf, uint32_t *entry) 190 { 191 Elf32_Ehdr *e = (void *)buf; 192 Elf32_Phdr *p; 193 int i; 194 195 if (e->e_ident[EI_MAG2] != 'L' || e->e_ident[EI_MAG3] != 'F' || 196 e->e_ident[EI_CLASS] != ELFCLASS32 || 197 e->e_ident[EI_DATA] != ELFDATA2MSB || 198 e->e_type != ET_EXEC || 199 e->e_machine != EM_MIPS) 200 return BERR_ELFHDR; 201 202 BASSERT(e->e_phentsize == sizeof(Elf32_Phdr)); 203 p = (void *)(buf + e->e_phoff); 204 #ifdef _STANDALONE 205 for (i = 0; i < e->e_phnum; i++) { 206 if (p[i].p_type != PT_LOAD || 207 (p[i].p_flags & (PF_W|PF_R|PF_X)) == 0) 208 continue; 209 if (IS_TEXT(p[i]) || IS_DATA(p[i])) { 210 memcpy((void *)p[i].p_vaddr, 211 buf + p[i].p_offset, p[i].p_filesz); 212 } 213 if (IS_BSS(p[i])) { 214 memset((void *)(p[i].p_vaddr + p[i].p_filesz), 0, 215 p[i].p_memsz - p[i].p_filesz); 216 } 217 } 218 #else 219 DPRINTF("ELF entry point 0x%08x\n", e->e_entry); 220 for (i = 0; i < e->e_phnum; i++) { 221 if (p[i].p_type != PT_LOAD || 222 (p[i].p_flags & (PF_W|PF_R|PF_X)) == 0) 223 continue; 224 if (IS_TEXT(p[i]) || IS_DATA(p[i])) { 225 DPRINTF("[text/data] 0x%08x 0x%x %dbyte.\n", 226 p[i].p_vaddr, p[i].p_offset, p[i].p_filesz); 227 } 228 if (IS_BSS(p[i])) { 229 DPRINTF("[bss] 0x%08x %dbyte.\n", 230 p[i].p_vaddr + p[i].p_filesz, 231 p[i].p_memsz - p[i].p_filesz); 232 } 233 } 234 #endif 235 *entry = e->e_entry; 236 237 return 0; 238 } 239 240 int 241 load_coff(uint8_t *p, uint32_t *entry) 242 { 243 struct ecoff_exechdr *eh = (void *)p; 244 struct ecoff_aouthdr *a = &eh->a; 245 struct ecoff_filehdr *f = &eh->f; 246 247 if (a->magic != ECOFF_OMAGIC) 248 return BERR_AOUTHDR; 249 250 p += N_TXTOFF(f, a); 251 DPRINTF("file offset = 0x%x\n", N_TXTOFF(f, a)); 252 #ifdef _STANDALONE 253 memcpy((void *)a->text_start, p, a->tsize); 254 memcpy((void *)a->data_start, p + a->tsize, a->dsize); 255 #else 256 DPRINTF("COFF entry point 0x%08lx\n", a->entry); 257 DPRINTF("[text] 0x%08lx %ld byte.\n", a->text_start, a->tsize); 258 DPRINTF("[data] 0x%08lx %ld byte.\n", a->data_start, a->dsize); 259 #endif 260 261 *entry = a->entry; 262 263 return 0; 264 } 265 266 int 267 dk_read(int sector, int count, void *buf) 268 { 269 #ifdef _STANDALONE 270 int cnt; 271 uint32_t pos; 272 uint8_t *p = buf; 273 274 if (__dk_type == NVSRAM_BOOTDEV_HARDDISK) { /* DISK */ 275 if ((ROM_DK_READ(__dk_unit, sector, count, p) & 0x7f) != 0) 276 return 1; 277 } else { /* FD */ 278 while (count > 0) { 279 fd_position(sector, &pos, &cnt); 280 if (cnt > count) 281 cnt = count; 282 if ((ROM_FD_READ(__dk_unit, pos, cnt * __spb, p) 283 & 0x7f) != 0) 284 return 1; 285 count -= cnt; 286 sector += cnt; 287 p += 512 * cnt; 288 } 289 } 290 #else 291 sector_read_n(buf, sector, count); 292 #endif 293 return 0; 294 } 295