]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/boot/common/load_aout.c
This commit was generated by cvs2svn to compensate for changes in r95978,
[FreeBSD/FreeBSD.git] / sys / boot / common / load_aout.c
1 /*-
2  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <sys/exec.h>
31 #include <sys/imgact_aout.h>
32 #include <sys/reboot.h>
33 #include <sys/linker.h>
34 #include <string.h>
35 #include <machine/bootinfo.h>
36 #include <stand.h>
37 #include <a.out.h>
38 #define FREEBSD_AOUT
39 #include <link.h>
40
41 #include "bootstrap.h"
42
43 static int              aout_loadimage(struct preloaded_file *fp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel);
44
45 #if 0
46 static vm_offset_t      aout_findkldident(struct preloaded_file *fp, struct exec *ehdr);
47 static int              aout_fixupkldmod(struct preloaded_file *fp, struct exec *ehdr);
48 #endif
49
50 const char      *aout_kerneltype = "a.out kernel";
51 const char      *aout_moduletype = "a.out module";
52
53 /*
54  * Attempt to load the file (file) as an a.out module.  It will be stored at
55  * (dest), and a pointer to a module structure describing the loaded object
56  * will be saved in (result).
57  */
58 int
59 aout_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result)
60 {
61     struct preloaded_file       *fp, *kfp;
62     struct exec                 ehdr;
63     int                         fd;
64     vm_offset_t                 addr;
65     int                         err, kernel;
66     u_int                       pad;
67
68     fp = NULL;
69     
70     /*
71      * Open the image, read and validate the a.out header 
72      */
73     if (filename == NULL)       /* can't handle nameless */
74         return(EFTYPE);
75     if ((fd = open(filename, O_RDONLY)) == -1)
76         return(errno);
77     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
78         err = EFTYPE;           /* could be EIO, but may be small file */
79         goto oerr;
80     }
81     if (N_BADMAG(ehdr)) {
82         err = EFTYPE;
83         goto oerr;
84     }
85
86     /*
87      * Check to see what sort of module we are.
88      *
89      * XXX should check N_GETMID()
90      */
91     kfp = file_findfile(NULL, NULL);
92     if ((N_GETFLAG(ehdr)) & EX_DYNAMIC) {
93         /* Looks like a kld module */
94         if (kfp == NULL) {
95             printf("aout_loadfile: can't load module before kernel\n");
96             err = EPERM;
97             goto oerr;
98         }
99         if (strcmp(aout_kerneltype, kfp->f_type)) {
100             printf("aout_loadfile: can't load module with kernel type '%s'\n", kfp->f_type);
101             err = EPERM;
102             goto oerr;
103         }
104         /* Looks OK, got ahead */
105         kernel = 0;
106
107     } else if (N_GETFLAG(ehdr) == 0) {
108         /* Looks like a kernel */
109         if (kfp != NULL) {
110             printf("aout_loadfile: kernel already loaded\n");
111             err = EPERM;
112             goto oerr;
113         }
114         /* 
115          * Calculate destination address based on kernel entrypoint     
116          * XXX this is i386-freebsd-aout specific
117          */
118         dest = ehdr.a_entry & 0x100000;
119         if (dest == 0) {
120             printf("aout_loadfile: not a kernel (maybe static binary?)\n");
121             err = EPERM;
122             goto oerr;
123         }
124         kernel = 1;
125     } else {
126         err = EFTYPE;
127         goto oerr;
128     }
129
130     /* 
131      * Ok, we think we should handle this.
132      */
133     fp = file_alloc();
134     if (kernel)
135         setenv("kernelname", filename, 1);
136     fp->f_name = strdup(filename);
137     fp->f_type = strdup(kernel ? aout_kerneltype : aout_moduletype);
138
139     /* Page-align the load address */
140     addr = dest;
141     pad = (u_int)addr & PAGE_MASK;
142     if (pad != 0) {
143         pad = PAGE_SIZE - pad;
144         addr += pad;
145     }
146     fp->f_addr = addr;                                  /* save the aligned load address */
147     if (kernel)
148         printf("%s at %p\n", filename, (void *) addr);
149
150     fp->f_size = aout_loadimage(fp, fd, addr, &ehdr, kernel);
151     if (fp->f_size == 0)
152         goto ioerr;
153
154 #if 0
155     /* Handle KLD module data */
156     if (!kernel && ((err = aout_fixupkldmod(fp, &ehdr)) != 0))
157         goto oerr;
158 #endif
159
160     /* save exec header as metadata */
161     file_addmetadata(fp, MODINFOMD_AOUTEXEC, sizeof(struct exec), &ehdr);
162
163     /* Load OK, return module pointer */
164     *result = fp;
165     err = 0;
166     goto out;
167     
168  ioerr:
169     err = EIO;
170  oerr:
171     file_discard(fp);
172  out:
173     close(fd);
174     return(err);
175 }
176
177 /*
178  * With the file (fd) open on the image, and (ehdr) containing
179  * the exec header, load the image at (addr)
180  *
181  * Fixup the a_bss field in (ehdr) to reflect the padding added to
182  * align the symbol table.
183  */
184 static int
185 aout_loadimage(struct preloaded_file *fp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel)
186 {
187     u_int               pad;
188     vm_offset_t         addr;
189     size_t              ss;
190     ssize_t             result;
191     vm_offset_t         ssym, esym;
192     
193     addr = loadaddr;
194     lseek(fd, (off_t)N_TXTOFF(*ehdr), SEEK_SET);
195
196     /* text segment */
197     printf("  text=0x%lx ", ehdr->a_text);
198     result = archsw.arch_readin(fd, addr, ehdr->a_text);
199     if (result < 0 || (size_t)result != ehdr->a_text)
200         return(0);
201     addr += ehdr->a_text;
202
203     /* data segment */
204     printf("data=0x%lx ", ehdr->a_data);
205     result = archsw.arch_readin(fd, addr, ehdr->a_data);
206     if (result < 0 || (size_t)result != ehdr->a_data)
207         return(0);
208     addr += ehdr->a_data;
209
210     /* For kernels, we pad the BSS to a page boundary */
211     if (kernel) {
212         pad = (u_int)ehdr->a_bss & PAGE_MASK;
213         if (pad != 0) {
214             pad = PAGE_SIZE - pad;
215             ehdr->a_bss += pad;
216         }
217     }
218     printf("bss=0x%lx ", ehdr->a_bss);
219     addr += ehdr->a_bss;
220
221     /* symbol table size */
222     ssym = esym = addr;
223     if(ehdr->a_syms!=NULL) {
224         archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms));
225         addr += sizeof(ehdr->a_syms);
226
227         /* symbol table */
228         printf("symbols=[0x%lx+0x%lx", (long)sizeof(ehdr->a_syms),ehdr->a_syms);
229         result = archsw.arch_readin(fd, addr, ehdr->a_syms);
230         if (result < 0 || (size_t)result != ehdr->a_syms)
231                 return(0);
232         addr += ehdr->a_syms;
233
234         /* string table */
235         read(fd, &ss, sizeof(ss));
236         archsw.arch_copyin(&ss, addr, sizeof(ss));
237         addr += sizeof(ss);
238         ss -= sizeof(ss);
239         printf("+0x%lx+0x%x]", (long)sizeof(ss), ss);
240         result = archsw.arch_readin(fd, addr, ss);
241         if (result < 0 || (size_t)result != ss)
242                 return(0);
243         addr += ss;
244         esym = addr;
245
246         file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
247         file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym);
248     } else {
249         printf("symbols=[none]");
250     }
251     printf("\n");
252
253     return(addr - loadaddr);
254 }
255
256