Annotation of sys/arch/sparc/stand/boot/loadfile.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: loadfile.c,v 1.5 2003/08/14 17:13:57 deraadt Exp $ */
! 2: /* $NetBSD: loadfile.c,v 1.3 1997/04/06 08:40:59 cgd Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1992, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to Berkeley by
! 9: * Ralph Campbell.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: *
! 35: * @(#)boot.c 8.1 (Berkeley) 6/10/93
! 36: */
! 37:
! 38: #define ELFSIZE 32
! 39:
! 40: #include <lib/libkern/libkern.h>
! 41: #include <lib/libsa/stand.h>
! 42: #include <sparc/stand/common/promdev.h>
! 43:
! 44: #include <sys/param.h>
! 45: #include <sys/exec.h>
! 46: #include <sys/exec_elf.h>
! 47:
! 48: #include <ddb/db_aout.h>
! 49:
! 50: #ifdef SPARC_BOOT_AOUT
! 51: static int aout_exec(int, struct exec *, vaddr_t *);
! 52: #endif
! 53: #ifdef SPARC_BOOT_ELF
! 54: static int elf_exec(int, Elf_Ehdr *, vaddr_t *);
! 55: #endif
! 56: int loadfile(int, vaddr_t *);
! 57:
! 58: vaddr_t ssym, esym;
! 59:
! 60: union {
! 61: #ifdef SPARC_BOOT_AOUT
! 62: struct exec aout;
! 63: #endif
! 64: #ifdef SPARC_BOOT_ELF
! 65: Elf_Ehdr elf;
! 66: #endif
! 67: } hdr;
! 68:
! 69: /*
! 70: * Open 'filename', read in program and return the entry point or -1 if error.
! 71: */
! 72: int
! 73: loadfile(int fd, vaddr_t *entryp)
! 74: {
! 75: struct devices *dp;
! 76: int rval;
! 77:
! 78: /* Read the exec header. */
! 79: if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
! 80: printf("read header: %s\n", strerror(errno));
! 81: goto err;
! 82: }
! 83:
! 84: #ifdef SPARC_BOOT_ELF
! 85: if (memcmp(ELFMAG, hdr.elf.e_ident, SELFMAG) == 0) {
! 86: rval = elf_exec(fd, &hdr.elf, entryp);
! 87: } else
! 88: #endif
! 89: #ifdef SPARC_BOOT_AOUT
! 90: if (!N_BADMAG(hdr.aout)) {
! 91: rval = aout_exec(fd, &hdr.aout, entryp);
! 92: } else
! 93: #endif
! 94: {
! 95: printf("unknown executable format\n");
! 96: }
! 97:
! 98: err:
! 99: if (fd >= 0)
! 100: close(fd);
! 101: return (rval);
! 102: }
! 103:
! 104: #ifdef SPARC_BOOT_AOUT
! 105: static int
! 106: aout_exec(int fd, struct exec *aout, vaddr_t *entryp)
! 107: {
! 108: caddr_t addr = (caddr_t)LOADADDR;
! 109: int strtablen;
! 110: char *strtab;
! 111: vaddr_t entry = (vaddr_t)LOADADDR;
! 112: int i;
! 113:
! 114: printf("%d", aout->a_text);
! 115: if (N_GETMAGIC(*aout) == ZMAGIC) {
! 116: entry = (vaddr_t)(addr+sizeof(struct exec));
! 117: addr += sizeof(struct exec);
! 118: }
! 119: /* we can't lseek() here - we may be booting off tape */
! 120: bcopy((char *)aout + sizeof(struct exec), addr,
! 121: sizeof(hdr) - sizeof(struct exec));
! 122: if (read(fd, (char *)addr + sizeof(hdr) - sizeof(struct exec),
! 123: aout->a_text - (sizeof(hdr) - sizeof(struct exec))) !=
! 124: aout->a_text - (sizeof(hdr) - sizeof(struct exec)))
! 125: goto shread;
! 126: addr += aout->a_text;
! 127: if (N_GETMAGIC(*aout) == ZMAGIC || N_GETMAGIC(*aout) == NMAGIC)
! 128: while ((int)addr & __LDPGSZ)
! 129: *addr++ = 0;
! 130: printf("+%d", aout->a_data);
! 131: if (read(fd, addr, aout->a_data) != aout->a_data)
! 132: goto shread;
! 133: addr += aout->a_data;
! 134: printf("+%d", aout->a_bss);
! 135: for (i = aout->a_bss; i ; --i)
! 136: *addr++ = 0;
! 137: if (aout->a_syms != 0) {
! 138: bcopy(&aout->a_syms, addr, sizeof(aout->a_syms));
! 139: addr += sizeof(aout->a_syms);
! 140: printf("+[%d", aout->a_syms);
! 141: if (read(fd, addr, aout->a_syms) != aout->a_syms)
! 142: goto shread;
! 143: addr += aout->a_syms;
! 144:
! 145: if (read(fd, &strtablen, sizeof(int)) != sizeof(int))
! 146: goto shread;
! 147:
! 148: bcopy(&strtablen, addr, sizeof(int));
! 149: if (i = strtablen) {
! 150: i -= sizeof(int);
! 151: addr += sizeof(int);
! 152: if (read(fd, addr, i) != i)
! 153: goto shread;
! 154: addr += i;
! 155: }
! 156: printf("+%d]", i);
! 157: esym = ((u_int)aout->a_entry - (u_int)LOADADDR) +
! 158: (((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1));
! 159: }
! 160: printf("=0x%x\n", addr);
! 161: close(fd);
! 162:
! 163: *entryp = entry;
! 164: return (0);
! 165:
! 166: shread:
! 167: printf("boot: short read\n");
! 168: return (1);
! 169: }
! 170: #endif /* SPARC_BOOT_AOUT */
! 171:
! 172: #ifdef SPARC_BOOT_ELF
! 173:
! 174: /*
! 175: * If we're booting off tape, we can't seek.
! 176: * Emulate forward moves with reads, and give up on backwards moves.
! 177: * bsd.rd ought to be correctly ordered.
! 178: */
! 179: static int
! 180: elf_seek(int fd, off_t relpos)
! 181: {
! 182: #define DUMBBUFSIZE 4096
! 183: char dumbbuf[DUMBBUFSIZE];
! 184: int len;
! 185:
! 186: if (relpos < 0) {
! 187: #ifdef DEBUG
! 188: printf("elf_seek: attempting to seek backwards from %llx bytes, "
! 189: "may fail!\n", -relpos);
! 190: #endif
! 191: if (lseek(fd, relpos, SEEK_CUR) < 0)
! 192: return (-1);
! 193: return (0);
! 194: }
! 195:
! 196: while (relpos != 0) {
! 197: len = relpos > DUMBBUFSIZE ? DUMBBUFSIZE : relpos;
! 198: if (read(fd, dumbbuf, len) != len)
! 199: return (-1);
! 200: relpos -= len;
! 201: }
! 202:
! 203: return (0);
! 204: #undef DUMBBUFSIZE
! 205: }
! 206:
! 207: static int
! 208: elf_exec(int fd, Elf_Ehdr *elf, vaddr_t *entryp)
! 209: {
! 210: int i;
! 211: int first = 1, havesyms;
! 212: Elf_Shdr *shp;
! 213: Elf_Off off;
! 214: size_t sz;
! 215: vaddr_t addr = 0;
! 216: Elf_Ehdr *fake_elf;
! 217: #define NUM_HEADERS 12 /* should be more than enough */
! 218: Elf_Phdr headers[NUM_HEADERS], *phdr;
! 219: off_t pos, newpos;
! 220:
! 221: *entryp = 0;
! 222:
! 223: #define A(x) ((x) - *entryp + (vaddr_t)LOADADDR)
! 224:
! 225: pos = sizeof(hdr);
! 226:
! 227: /* load the headers */
! 228: if (elf->e_phnum > NUM_HEADERS)
! 229: elf->e_phnum = NUM_HEADERS; /* amnesia rules */
! 230: newpos = elf->e_phoff;
! 231: if (elf_seek(fd, newpos - pos))
! 232: return (1);
! 233: pos = newpos;
! 234: if (read(fd, (void *)headers, elf->e_phnum * sizeof(Elf_Phdr)) !=
! 235: elf->e_phnum * sizeof(Elf_Phdr)) {
! 236: printf("read phdr: %s\n", strerror(errno));
! 237: return (1);
! 238: }
! 239: pos += elf->e_phnum * sizeof(Elf_Phdr);
! 240:
! 241: /* loop through the pheaders and find the entry point. */
! 242: for (i = 0; i < elf->e_phnum; i++) {
! 243: phdr = &headers[i];
! 244: if (phdr->p_type != PT_LOAD ||
! 245: (phdr->p_flags & (PF_W|PF_X)) == 0 ||
! 246: (phdr->p_vaddr != elf->e_entry))
! 247: continue;
! 248:
! 249: *entryp = phdr->p_vaddr;
! 250: }
! 251:
! 252: if (*entryp == 0) {
! 253: printf("Can't find entry point.\n");
! 254: return (-1);
! 255: }
! 256:
! 257: for (i = 0; i < elf->e_phnum; i++) {
! 258: phdr = &headers[i];
! 259: if (phdr->p_type != PT_LOAD ||
! 260: (phdr->p_flags & (PF_W|PF_X)) == 0)
! 261: continue;
! 262:
! 263: /* Read in segment. */
! 264: printf("%s%lu", first ? "" : "+", phdr->p_filesz);
! 265: newpos = phdr->p_offset;
! 266: if (elf_seek(fd, newpos - pos))
! 267: return (1);
! 268: pos = newpos;
! 269:
! 270: if (read(fd, (caddr_t)A(phdr->p_vaddr), phdr->p_filesz) !=
! 271: phdr->p_filesz) {
! 272: (void)printf("read text: %s\n", strerror(errno));
! 273: return (1);
! 274: }
! 275: pos += phdr->p_filesz;
! 276:
! 277: /* keep track of highest addr we loaded. */
! 278: if (first || addr < (phdr->p_vaddr + phdr->p_memsz))
! 279: addr = (phdr->p_vaddr + phdr->p_memsz);
! 280:
! 281: /* Zero out bss. */
! 282: if (phdr->p_filesz < phdr->p_memsz) {
! 283: printf("+%lu", phdr->p_memsz - phdr->p_filesz);
! 284: bzero((caddr_t)A(phdr->p_vaddr) + phdr->p_filesz,
! 285: phdr->p_memsz - phdr->p_filesz);
! 286: }
! 287: first = 0;
! 288: }
! 289:
! 290: addr = A(addr);
! 291: addr = roundup(addr, sizeof(long));
! 292:
! 293: ssym = addr;
! 294: /*
! 295: * Retrieve symbols.
! 296: */
! 297: addr += sizeof(Elf_Ehdr);
! 298:
! 299: newpos = elf->e_shoff;
! 300: if (elf_seek(fd, newpos - pos)) {
! 301: printf("seek to section headers: %s\n", strerror(errno));
! 302: return (1);
! 303: }
! 304: pos = newpos;
! 305:
! 306: sz = elf->e_shnum * sizeof(Elf_Shdr);
! 307: shp = (Elf_Shdr *)addr;
! 308: addr += roundup(sz, sizeof(long));
! 309:
! 310: if (read(fd, shp, sz) != sz) {
! 311: printf("read section headers: %d\n", strerror(errno));
! 312: return (1);
! 313: }
! 314: pos += sz;
! 315:
! 316: /*
! 317: * Now load the symbol sections themselves. Make sure the
! 318: * sections are aligned. Don't bother with string tables if
! 319: * there are no symbol sections.
! 320: */
! 321: off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(long));
! 322:
! 323: for (havesyms = i = 0; i < elf->e_shnum; i++)
! 324: if (shp[i].sh_type == SHT_SYMTAB)
! 325: havesyms = 1;
! 326:
! 327: if (!havesyms)
! 328: goto no_syms;
! 329:
! 330: for (first = 1, i = 0; i < elf->e_shnum; i++) {
! 331: if (shp[i].sh_type == SHT_SYMTAB ||
! 332: shp[i].sh_type == SHT_STRTAB) {
! 333: printf("%s%ld", first ? " [" : "+",
! 334: (u_long)shp[i].sh_size);
! 335: newpos = shp[i].sh_offset;
! 336: if (elf_seek(fd, newpos - pos)) {
! 337: printf("lseek symbols: %s\n", strerror(errno));
! 338: return (1);
! 339: }
! 340: pos = newpos;
! 341: if (read(fd, (void *)addr, shp[i].sh_size) !=
! 342: shp[i].sh_size) {
! 343: printf("read symbols: %s\n", strerror(errno));
! 344: return (1);
! 345: }
! 346: pos += shp[i].sh_size;
! 347: addr += roundup(shp[i].sh_size, sizeof(long));
! 348: shp[i].sh_offset = off;
! 349: off += roundup(shp[i].sh_size, sizeof(long));
! 350: first = 0;
! 351: }
! 352: }
! 353: if (havesyms && first == 0)
! 354: printf("]");
! 355:
! 356: elf->e_phoff = 0;
! 357: elf->e_shoff = sizeof(Elf_Ehdr);
! 358: elf->e_phentsize = 0;
! 359: elf->e_phnum = 0;
! 360: bcopy(elf, (void *)ssym, sizeof(*elf));
! 361:
! 362: no_syms:
! 363: esym = (addr - (vaddr_t)LOADADDR) + *entryp;
! 364:
! 365: *entryp = (vaddr_t)LOADADDR;
! 366:
! 367: printf("\n");
! 368: return (0);
! 369: #undef NUM_HEADERS
! 370: }
! 371: #endif /* SPARC_BOOT_ELF */
CVSweb