root/lib/libsa/loadfile.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. loadfile
  2. coff_exec
  3. aout_exec

    1 /* $NetBSD: loadfile.c,v 1.10 2000/12/03 02:53:04 tsutsui Exp $ */
    2 /* $OpenBSD: loadfile.c,v 1.14 2007/06/26 10:32:50 tom Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1997 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center and by Christos Zoulas.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Copyright (c) 1992, 1993
   43  *      The Regents of the University of California.  All rights reserved.
   44  *
   45  * This code is derived from software contributed to Berkeley by
   46  * Ralph Campbell.
   47  *
   48  * Redistribution and use in source and binary forms, with or without
   49  * modification, are permitted provided that the following conditions
   50  * are met:
   51  * 1. Redistributions of source code must retain the above copyright
   52  *    notice, this list of conditions and the following disclaimer.
   53  * 2. Redistributions in binary form must reproduce the above copyright
   54  *    notice, this list of conditions and the following disclaimer in the
   55  *    documentation and/or other materials provided with the distribution.
   56  * 3. Neither the name of the University nor the names of its contributors
   57  *    may be used to endorse or promote products derived from this software
   58  *    without specific prior written permission.
   59  *
   60  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   61  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   62  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   63  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   64  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   65  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   66  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   67  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   68  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   69  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   70  * SUCH DAMAGE.
   71  *
   72  *      @(#)boot.c      8.1 (Berkeley) 6/10/93
   73  */
   74 
   75 #ifdef _STANDALONE
   76 #include <lib/libkern/libkern.h>
   77 #include <lib/libsa/stand.h>
   78 #else
   79 #include <stdio.h>
   80 #include <string.h>
   81 #include <errno.h>
   82 #include <stdlib.h>
   83 #include <unistd.h>
   84 #include <fcntl.h>
   85 #include <err.h>
   86 #endif
   87 
   88 #include <sys/param.h>
   89 #include <sys/exec.h>
   90 
   91 #include "loadfile.h"
   92 
   93 #ifdef BOOT_ECOFF
   94 #include <sys/exec_ecoff.h>
   95 static int coff_exec(int, struct ecoff_exechdr *, u_long *, int);
   96 #endif
   97 #ifdef BOOT_AOUT
   98 #include <sys/exec_aout.h>
   99 static int aout_exec(int, struct exec *, u_long *, int);
  100 #endif
  101 
  102 #ifdef BOOT_ELF
  103 #include <sys/exec_elf.h>
  104 #if defined(BOOT_ELF32) && defined(BOOT_ELF64)
  105 /*
  106  * Both defined, so elf32_exec() and elf64_exec() need to be separately
  107  * created (can't do it by including loadfile_elf.c here).
  108  */
  109 int elf32_exec(int, Elf32_Ehdr *, u_long *, int);
  110 int elf64_exec(int, Elf64_Ehdr *, u_long *, int);
  111 #else
  112 #include "loadfile_elf.c"
  113 #endif
  114 #endif
  115 
  116 /*
  117  * Open 'filename', read in program and return -1 on error otherwise fd,
  118  * with file still open.
  119  * Also fills in marks.
  120  */
  121 int
  122 loadfile(const char *fname, u_long *marks, int flags)
  123 {
  124         union {
  125 #ifdef BOOT_ECOFF
  126                 struct ecoff_exechdr coff;
  127 #endif
  128 #if defined(BOOT_ELF32) || (defined(BOOT_ELF) && ELFSIZE == 32)
  129                 Elf32_Ehdr elf32;
  130 #endif
  131 #if defined(BOOT_ELF64) || (defined(BOOT_ELF) && ELFSIZE == 64)
  132                 Elf64_Ehdr elf64;
  133 #endif
  134 #ifdef BOOT_AOUT
  135                 struct exec aout;
  136 #endif
  137 
  138         } hdr;
  139         ssize_t nr;
  140         int fd, rval;
  141 
  142         /* Open the file. */
  143         if ((fd = open(fname, 0)) < 0) {
  144                 WARN(("open %s", fname ? fname : "<default>"));
  145                 return -1;
  146         }
  147 
  148         /* Read the exec header. */
  149         if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
  150                 WARN(("read header"));
  151                 goto err;
  152         }
  153 
  154 #ifdef BOOT_ECOFF
  155         if (!ECOFF_BADMAG(&hdr.coff)) {
  156                 rval = coff_exec(fd, &hdr.coff, marks, flags);
  157         } else
  158 #endif
  159 #if defined(BOOT_ELF32) || (defined(BOOT_ELF) && ELFSIZE == 32)
  160         if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
  161             hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
  162                 rval = elf32_exec(fd, &hdr.elf32, marks, flags);
  163         } else
  164 #endif
  165 #if defined(BOOT_ELF64) || (defined(BOOT_ELF) && ELFSIZE == 64)
  166         if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 &&
  167             hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) {
  168                 rval = elf64_exec(fd, &hdr.elf64, marks, flags);
  169         } else
  170 #endif
  171 #ifdef BOOT_AOUT
  172         if (OKMAGIC(N_GETMAGIC(hdr.aout))
  173 #ifndef NO_MID_CHECK
  174             && N_GETMID(hdr.aout) == MID_MACHINE
  175 #endif
  176             ) {
  177                 rval = aout_exec(fd, &hdr.aout, marks, flags);
  178         } else
  179 #endif
  180         {
  181                 rval = 1;
  182                 errno = EFTYPE;
  183                 WARN(("%s", fname ? fname : "<default>"));
  184         }
  185 
  186         if (rval == 0) {
  187                 PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START]));
  188                 return fd;
  189         }
  190 err:
  191         (void)close(fd);
  192         return -1;
  193 }
  194 
  195 #ifdef BOOT_ECOFF
  196 static int
  197 coff_exec(int fd, struct ecoff_exechdr *coff, u_long *marks, int flags)
  198 {
  199         paddr_t offset = marks[MARK_START];
  200         paddr_t minp = ~0, maxp = 0, pos;
  201 
  202         /* Read in text. */
  203         if (lseek(fd, ECOFF_TXTOFF(coff), SEEK_SET) == -1)  {
  204                 WARN(("lseek text"));
  205                 return 1;
  206         }
  207 
  208         if (coff->a.tsize != 0) {
  209                 if (flags & LOAD_TEXT) {
  210                         PROGRESS(("%lu", coff->a.tsize));
  211                         if (READ(fd, coff->a.text_start, coff->a.tsize) !=
  212                             coff->a.tsize) {
  213                                 return 1;
  214                         }
  215                 }
  216                 else {
  217                         if (lseek(fd, coff->a.tsize, SEEK_CUR) == -1) {
  218                                 WARN(("read text"));
  219                                 return 1;
  220                         }
  221                 }
  222                 if (flags & (COUNT_TEXT|LOAD_TEXT)) {
  223                         pos = coff->a.text_start;
  224                         if (minp > pos)
  225                                 minp = pos;
  226                         pos += coff->a.tsize;
  227                         if (maxp < pos)
  228                                 maxp = pos;
  229                 }
  230         }
  231 
  232         /* Read in data. */
  233         if (coff->a.dsize != 0) {
  234                 if (flags & LOAD_DATA) {
  235                         PROGRESS(("+%lu", coff->a.dsize));
  236                         if (READ(fd, coff->a.data_start, coff->a.dsize) !=
  237                             coff->a.dsize) {
  238                                 WARN(("read data"));
  239                                 return 1;
  240                         }
  241                 }
  242                 if (flags & (COUNT_DATA|LOAD_DATA)) {
  243                         pos = coff->a.data_start;
  244                         if (minp > pos)
  245                                 minp = pos;
  246                         pos += coff->a.dsize;
  247                         if (maxp < pos)
  248                                 maxp = pos;
  249                 }
  250         }
  251 
  252         /* Zero out bss. */
  253         if (coff->a.bsize != 0) {
  254                 if (flags & LOAD_BSS) {
  255                         PROGRESS(("+%lu", coff->a.bsize));
  256                         BZERO(coff->a.bss_start, coff->a.bsize);
  257                 }
  258                 if (flags & (COUNT_BSS|LOAD_BSS)) {
  259                         pos = coff->a.bss_start;
  260                         if (minp > pos)
  261                                 minp = pos;
  262                         pos = coff->a.bsize;
  263                         if (maxp < pos)
  264                                 maxp = pos;
  265                 }
  266         }
  267 
  268         marks[MARK_START] = LOADADDR(minp);
  269         marks[MARK_ENTRY] = LOADADDR(coff->a.entry);
  270         marks[MARK_NSYM] = 1;   /* XXX: Kernel needs >= 0 */
  271         marks[MARK_SYM] = LOADADDR(maxp);
  272         marks[MARK_END] = LOADADDR(maxp);
  273         return 0;
  274 }
  275 #endif /* BOOT_ECOFF */
  276 
  277 #ifdef BOOT_AOUT
  278 static int
  279 aout_exec(int fd, struct exec *x, u_long *marks, int flags)
  280 {
  281         u_long entry = x->a_entry;
  282         paddr_t aoutp = 0;
  283         paddr_t minp, maxp;
  284         int cc;
  285         paddr_t offset = marks[MARK_START];
  286         u_long magic = N_GETMAGIC(*x);
  287         int sub;
  288 
  289         /* In OMAGIC and NMAGIC, exec header isn't part of text segment */
  290         if (magic == OMAGIC || magic == NMAGIC)
  291                 sub = 0;
  292         else
  293                 sub = sizeof(*x);
  294 
  295         minp = maxp = ALIGNENTRY(entry);
  296 
  297         if (lseek(fd, sizeof(*x), SEEK_SET) == -1)  {
  298                 WARN(("lseek text"));
  299                 return 1;
  300         }
  301 
  302         /*
  303          * Leave a copy of the exec header before the text.
  304          * The kernel may use this to verify that the
  305          * symbols were loaded by this boot program.
  306          */
  307         if (magic == OMAGIC || magic == NMAGIC) {
  308                 if (flags & LOAD_HDR && maxp >= sizeof(*x))
  309                         BCOPY(x, maxp - sizeof(*x), sizeof(*x));
  310         }
  311         else {
  312                 if (flags & LOAD_HDR)
  313                         BCOPY(x, maxp, sizeof(*x));
  314                 if (flags & (LOAD_HDR|COUNT_HDR))
  315                         maxp += sizeof(*x);
  316         }
  317 
  318         /*
  319          * Read in the text segment.
  320          */
  321         if (flags & LOAD_TEXT) {
  322                 PROGRESS(("%ld", x->a_text));
  323 
  324                 if (READ(fd, maxp, x->a_text - sub) != x->a_text - sub) {
  325                         WARN(("read text"));
  326                         return 1;
  327                 }
  328         } else {
  329                 if (lseek(fd, x->a_text - sub, SEEK_CUR) == -1) {
  330                         WARN(("seek text"));
  331                         return 1;
  332                 }
  333         }
  334         if (flags & (LOAD_TEXT|COUNT_TEXT))
  335                 maxp += x->a_text - sub;
  336 
  337         /*
  338          * Provide alignment if required
  339          */
  340         if (magic == ZMAGIC || magic == NMAGIC) {
  341                 int size = -(unsigned int)maxp & (__LDPGSZ - 1);
  342 
  343                 if (flags & LOAD_TEXTA) {
  344                         PROGRESS(("/%d", size));
  345                         BZERO(maxp, size);
  346                 }
  347 
  348                 if (flags & (LOAD_TEXTA|COUNT_TEXTA))
  349                         maxp += size;
  350         }
  351 
  352         /*
  353          * Read in the data segment.
  354          */
  355         if (flags & LOAD_DATA) {
  356                 PROGRESS(("+%ld", x->a_data));
  357 
  358                 if (READ(fd, maxp, x->a_data) != x->a_data) {
  359                         WARN(("read data"));
  360                         return 1;
  361                 }
  362         }
  363         else {
  364                 if (lseek(fd, x->a_data, SEEK_CUR) == -1) {
  365                         WARN(("seek data"));
  366                         return 1;
  367                 }
  368         }
  369         if (flags & (LOAD_DATA|COUNT_DATA))
  370                 maxp += x->a_data;
  371 
  372         /*
  373          * Zero out the BSS section.
  374          * (Kernel doesn't care, but do it anyway.)
  375          */
  376         if (flags & LOAD_BSS) {
  377                 PROGRESS(("+%ld", x->a_bss));
  378 
  379                 BZERO(maxp, x->a_bss);
  380         }
  381 
  382         if (flags & (LOAD_BSS|COUNT_BSS))
  383                 maxp += x->a_bss;
  384 
  385         /*
  386          * Read in the symbol table and strings.
  387          * (Always set the symtab size word.)
  388          */
  389         if (flags & LOAD_SYM)
  390                 BCOPY(&x->a_syms, maxp, sizeof(x->a_syms));
  391 
  392         if (flags & (LOAD_SYM|COUNT_SYM)) {
  393                 maxp += sizeof(x->a_syms);
  394                 aoutp = maxp;
  395         }
  396 
  397         if (x->a_syms > 0) {
  398                 /* Symbol table and string table length word. */
  399 
  400                 if (flags & LOAD_SYM) {
  401                         PROGRESS(("+[%ld", x->a_syms));
  402 
  403                         if (READ(fd, maxp, x->a_syms) != x->a_syms) {
  404                                 WARN(("read symbols"));
  405                                 return 1;
  406                         }
  407                 } else  {
  408                         if (lseek(fd, x->a_syms, SEEK_CUR) == -1) {
  409                                 WARN(("seek symbols"));
  410                                 return 1;
  411                         }
  412                 }
  413                 if (flags & (LOAD_SYM|COUNT_SYM))
  414                         maxp += x->a_syms;
  415 
  416                 if (read(fd, &cc, sizeof(cc)) != sizeof(cc)) {
  417                         WARN(("read string table"));
  418                         return 1;
  419                 }
  420 
  421                 if (flags & LOAD_SYM) {
  422                         BCOPY(&cc, maxp, sizeof(cc));
  423 
  424                         /* String table. Length word includes itself. */
  425 
  426                         PROGRESS(("+%d]", cc));
  427                 }
  428                 if (flags & (LOAD_SYM|COUNT_SYM))
  429                         maxp += sizeof(cc);
  430 
  431                 cc -= sizeof(int);
  432                 if (cc <= 0) {
  433                         WARN(("symbol table too short"));
  434                         return 1;
  435                 }
  436 
  437                 if (flags & LOAD_SYM) {
  438                         if (READ(fd, maxp, cc) != cc) {
  439                                 WARN(("read strings"));
  440                                 return 1;
  441                         }
  442                 } else {
  443                         if (lseek(fd, cc, SEEK_CUR) == -1) {
  444                                 WARN(("seek strings"));
  445                                 return 1;
  446                         }
  447                 }
  448                 if (flags & (LOAD_SYM|COUNT_SYM))
  449                         maxp += cc;
  450         }
  451 
  452         marks[MARK_START] = LOADADDR(minp);
  453         marks[MARK_ENTRY] = LOADADDR(entry);
  454         marks[MARK_NSYM] = x->a_syms;
  455         marks[MARK_SYM] = LOADADDR(aoutp);
  456         marks[MARK_END] = LOADADDR(maxp);
  457         return 0;
  458 }
  459 #endif /* BOOT_AOUT */

/* [<][>][^][v][top][bottom][index][help] */