[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     ! 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