1 /* $NetBSD: bootxx.c,v 1.5 2001/09/08 16:57:09 thomas Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Waldi Ravens. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Waldi Ravens. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #define boot_BSD bsd_startup 34 35 #include <stand.h> 36 #include <atari_stand.h> 37 #include <string.h> 38 #include <libkern.h> 39 #include <kparamb.h> 40 #include <sys/boot_flag.h> 41 #ifndef __ELF__ 42 #include <sys/exec.h> 43 #else 44 #include <sys/exec_elf.h> 45 #endif 46 #include <sys/reboot.h> 47 #include <machine/cpu.h> 48 49 #include "bootxx.h" 50 51 void boot_BSD __P((kparb *)__attribute__((noreturn))); 52 int load_BSD __P((osdsc *)); 53 int sys_info __P((osdsc *)); 54 int usr_info __P((osdsc *)); 55 56 int 57 bootxx(readsector, disklabel, autoboot) 58 void *readsector, 59 *disklabel; 60 int autoboot; 61 { 62 static osdsc os_desc; 63 extern char end[], edata[]; 64 osdsc *od = &os_desc; 65 66 bzero(edata, end - edata); 67 68 printf("\033v\nNetBSD/Atari boot loader ($Revision: 1.5 $)\n\n"); 69 70 if (init_dskio(readsector, disklabel, -1)) 71 return(-1); 72 73 if (sys_info(od)) 74 return(-2); 75 76 for (;;) { 77 od->rootfs = 0; /* partition a */ 78 od->osname = "/netbsd"; 79 od->ostype = &od->osname[1]; 80 od->boothowto = (RB_RDONLY); 81 82 if (!autoboot) { 83 int pref; 84 85 od->boothowto = (RB_RDONLY|RB_SINGLE); 86 pref = usr_info(od); 87 if (pref < 0) 88 continue; 89 if (pref > 0) 90 return(pref); 91 } 92 autoboot = 0; /* in case auto boot fails */ 93 94 if (init_dskio(readsector, disklabel, od->rootfs)) 95 continue; 96 97 if (load_BSD(od)) 98 continue; 99 100 boot_BSD(&od->kp); 101 } 102 /* NOTREACHED */ 103 } 104 105 int 106 sys_info(od) 107 osdsc *od; 108 { 109 long *jar; 110 int tos; 111 112 od->stmem_size = *ADDR_PHYSTOP; 113 114 if (*ADDR_CHKRAMTOP == RAMTOP_MAGIC) { 115 od->ttmem_size = *ADDR_RAMTOP; 116 if (od->ttmem_size > TTRAM_BASE) { 117 od->ttmem_size -= TTRAM_BASE; 118 od->ttmem_start = TTRAM_BASE; 119 } 120 } 121 122 tos = (*ADDR_SYSBASE)->os_version; 123 if ((tos > 0x300) && (tos < 0x306)) 124 od->cputype = ATARI_CLKBROKEN; 125 126 if ((jar = *ADDR_P_COOKIE)) { 127 while (jar[0]) { 128 if ((jar[0] == 0x5f435055L) && ((jar[1] % 10) == 0)) { /* _CPU */ 129 switch(jar[1] / 10) { 130 case 0: 131 od->cputype |= ATARI_68000; 132 break; 133 case 1: 134 od->cputype |= ATARI_68010; 135 break; 136 case 2: 137 od->cputype |= ATARI_68020; 138 break; 139 case 3: 140 od->cputype |= ATARI_68030; 141 break; 142 case 4: 143 od->cputype |= ATARI_68040; 144 break; 145 case 6: 146 od->cputype |= ATARI_68060; 147 break; 148 } 149 } 150 jar += 2; 151 } 152 } 153 if (!(od->cputype & ATARI_ANYCPU)) { 154 printf("Unknown CPU-type.\n"); 155 return(-1); 156 } 157 158 return(0); 159 } 160 161 int 162 usr_info(od) 163 osdsc *od; 164 { 165 static char line[800]; 166 char c, *p = line; 167 168 printf("\nEnter os-type [.%s] root-fs [:a] kernel [%s]" 169 " options [none]:\n\033e", od->ostype, od->osname); 170 gets(p); 171 printf("\033f"); 172 173 for (;;) { 174 while (isspace(*p)) 175 *p++ = '\0'; 176 177 switch (*p++) { 178 case '\0': 179 goto done; 180 case ':': 181 if ((c = *p) >= 'a' && c <= 'z') 182 od->rootfs = c - 'a'; 183 else if (c >= 'A' && c <= 'Z') 184 od->rootfs = c - ('A' - 27); 185 else return(-1); 186 187 if (!od->rootfs) 188 break; 189 *p = 'b'; 190 /* FALLTHROUGH */ 191 case '-': 192 if ((c = *p) == 'a') 193 od->boothowto &= ~RB_SINGLE; 194 else if (c == 'b') 195 od->boothowto |= RB_ASKNAME; 196 else 197 BOOT_FLAG(c, od->boothowto); 198 break; 199 case '.': 200 od->ostype = p; 201 break; 202 case '/': 203 od->osname = --p; 204 break; 205 default: 206 return(-1); 207 } 208 209 while ((c = *p) && !isspace(c)) 210 p += 1; 211 } 212 213 done: 214 c = od->ostype[0]; 215 if (isupper(c)) 216 c = tolower(c); 217 218 switch (c) { 219 case 'n': /* NetBSD */ 220 return(0); 221 case 'l': /* Linux */ 222 return(0x10); 223 case 'a': /* ASV */ 224 return(0x40); 225 case 't': /* TOS */ 226 return(0x80); 227 default: 228 return(-1); 229 } 230 } 231 232 #ifndef __ELF__ /* a.out */ 233 int 234 load_BSD(od) 235 osdsc *od; 236 { 237 struct exec hdr; 238 int err, fd; 239 u_int textsz, strsz; 240 241 /* 242 * Read kernel's exec-header. 243 */ 244 err = 1; 245 if ((fd = open(od->osname, 0)) < 0) 246 goto error; 247 err = 2; 248 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) 249 goto error; 250 err = 3; 251 if ((N_GETMAGIC(hdr) != NMAGIC) && (N_GETMAGIC(hdr) != OMAGIC)) 252 goto error; 253 254 /* 255 * Extract sizes from kernel executable. 256 */ 257 textsz = (hdr.a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1); 258 od->ksize = textsz + hdr.a_data + hdr.a_bss; 259 od->kentry = hdr.a_entry; 260 od->kstart = NULL; 261 od->k_esym = 0; 262 263 if (hdr.a_syms) { 264 u_int x = sizeof(hdr) + hdr.a_text + hdr.a_data + hdr.a_syms; 265 err = 8; 266 if (lseek(fd, (off_t)x, SEEK_SET) != x) 267 goto error; 268 err = 9; 269 if (read(fd, &strsz, sizeof(strsz)) != sizeof(strsz)) 270 goto error; 271 err = 10; 272 if (lseek(fd, (off_t)sizeof(hdr), SEEK_SET) != sizeof(hdr)) 273 goto error; 274 od->ksize += sizeof(strsz) + hdr.a_syms + strsz; 275 } 276 277 /* 278 * Read text & data, clear bss 279 */ 280 err = 16; 281 if ((od->kstart = alloc(od->ksize)) == NULL) 282 goto error; 283 err = 17; 284 if (read(fd, od->kstart, hdr.a_text) != hdr.a_text) 285 goto error; 286 err = 18; 287 if (read(fd, od->kstart + textsz, hdr.a_data) != hdr.a_data) 288 goto error; 289 bzero(od->kstart + textsz + hdr.a_data, hdr.a_bss); 290 291 /* 292 * Read symbol and string table 293 */ 294 if (hdr.a_syms) { 295 char *p = od->kstart + textsz + hdr.a_data + hdr.a_bss; 296 *((u_int32_t *)p)++ = hdr.a_syms; 297 err = 24; 298 if (read(fd, p, hdr.a_syms) != hdr.a_syms) 299 goto error; 300 p += hdr.a_syms; 301 err = 25; 302 if (read(fd, p, strsz) != strsz) 303 goto error; 304 od->k_esym = (p - (char *)od->kstart) + strsz; 305 } 306 307 return(0); 308 309 error: 310 if (fd >= 0) { 311 if (od->kstart) 312 free(od->kstart, od->ksize); 313 close(fd); 314 } 315 printf("Error %d in load_BSD.\n", err); 316 return(-1); 317 } 318 319 #else /* __ELF__ */ 320 321 #define ELFMAGIC ((ELFMAG0 << 24) | (ELFMAG1 << 16) | (ELFMAG2 << 8) | ELFMAG3) 322 323 int 324 load_BSD(od) 325 osdsc *od; 326 { 327 int err, fd, i, j; 328 Elf32_Ehdr ehdr; 329 Elf32_Word kernsize; 330 #if 0 331 Elf32_Word symsize, symstart; 332 #endif 333 334 /* 335 * Read kernel's exec-header. 336 */ 337 od->kstart = NULL; 338 err = 1; 339 if ((fd = open(od->osname, 0)) < 0) 340 goto error; 341 err = 2; 342 if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) 343 goto error; 344 err = 3; 345 if (*((u_int *)ehdr.e_ident) != ELFMAGIC) 346 goto error; 347 err = 4; 348 if (lseek(fd, (off_t)ehdr.e_phoff, SEEK_SET) < 0) 349 goto error; 350 351 /* 352 * calculate highest used address 353 */ 354 i = ehdr.e_phnum + 1; 355 kernsize = 0; 356 while (--i) { 357 Elf32_Phdr phdr; 358 Elf32_Word sum; 359 err = 5; 360 if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) 361 goto error; 362 sum = phdr.p_vaddr + phdr.p_memsz; 363 if ((phdr.p_flags & (PF_W|PF_X)) && (sum > kernsize)) 364 kernsize = sum; 365 } 366 367 #if 0 368 /* 369 * look for symbols and calculate the size 370 */ 371 err = 6; 372 if (lseek(fd, (off_t)ehdr.e_shoff, SEEK_SET) < 0) 373 goto error; 374 i = ehdr.e_shnum + 1; 375 symsize = 0; 376 symstart = 0; 377 while (--i) { 378 Elf32_Shdr shdr; 379 err = 7; 380 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) 381 goto error; 382 if ((shdr.sh_type == SHT_SYMTAB) || (shdr.sh_type == SHT_STRTAB)) 383 symsize += shdr.sh_size; 384 } 385 386 if (symsize) { 387 symstart = kernsize; 388 kernsize += symsize + sizeof(ehdr) + ehdr.e_shoff * sizeof(Elf32_Shdr); 389 } 390 #endif 391 392 od->ksize = kernsize; 393 od->kentry = ehdr.e_entry; 394 od->k_esym = 0; 395 396 err = 10; 397 if ((od->kstart = alloc(od->ksize)) == NULL) 398 goto error; 399 400 /* 401 * read segements, clear bss 402 */ 403 i = ehdr.e_phnum + 1; 404 j = 0; 405 while (--i) { 406 Elf32_Phdr phdr; 407 Elf32_Word pos; 408 u_char *p; 409 pos = ehdr.e_phoff + j * sizeof(phdr); 410 err = 11; 411 if (lseek(fd, (off_t)pos, SEEK_SET) < 0) 412 goto error; 413 err = 12; 414 if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) 415 goto error; 416 if (phdr.p_flags & (PF_W|PF_X)) { 417 err = 13; 418 if (lseek(fd, (off_t)phdr.p_offset, SEEK_SET) < 0) 419 goto error; 420 p = (u_char *)(od->kstart) + phdr.p_vaddr; 421 err = 14; 422 if (read(fd, p, phdr.p_filesz) != phdr.p_filesz) 423 goto error; 424 if (phdr.p_memsz > phdr.p_filesz) 425 bzero(p + phdr.p_filesz, phdr.p_memsz - phdr.p_filesz); 426 } 427 ++j; 428 } 429 430 #if 0 431 /* 432 * read symbol and string 433 */ 434 if (symsize) { 435 Elf32_Word pos; 436 int k = ehdr.e_shoff; 437 j = symstart + sizeof(ehdr); 438 pos = symstart + sizeof(ehdr) + ehdr.e_shoff * sizeof(Elf32_Shdr); 439 bzero((u_char *)(od->kstart) + j, ehdr.e_shoff * sizeof(Elf32_Shdr)); 440 i = ehdr.e_shnum + 1; 441 while (--i) { 442 Elf32_Shdr shdr; 443 u_char *p; 444 err = 20; 445 if (lseek(fd, (off_t)k, SEEK_SET) < 0) 446 goto error; 447 err = 21; 448 if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) 449 goto error; 450 if ((shdr.sh_type == SHT_SYMTAB) || (shdr.sh_type == SHT_STRTAB)) { 451 err = 22; 452 if (lseek(fd, (off_t)shdr.sh_offset, SEEK_SET) < 0) 453 goto error; 454 p = (u_char *)(od->kstart) + pos; 455 err = 23; 456 if (read(fd, p, shdr.sh_size) != shdr.sh_size) 457 goto error; 458 shdr.sh_offset = pos; 459 pos += shdr.sh_size; 460 bcopy(&shdr, (u_char *)(od->kstart) + j, sizeof(shdr)); 461 } 462 j += sizeof(shdr); 463 k += sizeof(shdr); 464 } 465 ehdr.e_shoff = symstart + sizeof(ehdr); 466 bcopy(&ehdr, (u_char *)(od->kstart) + symstart, sizeof(ehdr)); 467 } 468 #endif 469 470 return(0); 471 472 error: 473 474 if (fd >= 0) { 475 if (od->kstart) 476 free(od->kstart, od->ksize); 477 close(fd); 478 } 479 printf("Error %d in load_BSD.\n", err); 480 return(-1); 481 482 } 483 #endif /* __ELF__ */ 484