[BACK]Return to loadfile.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / stand / boot

Annotation of sys/arch/sparc/stand/boot/loadfile.c, Revision 1.1.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