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