Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.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: src/sys/boot/common/load_aout.c,v 1.16.2.2 2000/12/28 13:12:35 ps Exp $
27  * $DragonFly: src/sys/boot/common/Attic/load_aout.c,v 1.2 2003/06/17 04:28:16 dillon Exp $
28  */
29
30 #include <sys/param.h>
31 #include <sys/exec.h>
32 #include <sys/imgact_aout.h>
33 #include <sys/reboot.h>
34 #include <sys/linker.h>
35 #include <string.h>
36 #include <machine/bootinfo.h>
37 #include <stand.h>
38 #include <a.out.h>
39 #define FREEBSD_AOUT
40 #include <link.h>
41
42 #include "bootstrap.h"
43
44 static int              aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel);
45
46 #if 0
47 static vm_offset_t      aout_findkldident(struct loaded_module *mp, struct exec *ehdr);
48 static int              aout_fixupkldmod(struct loaded_module *mp, struct exec *ehdr);
49 #endif
50
51 const char      *aout_kerneltype = "a.out kernel";
52 const char      *aout_moduletype = "a.out module";
53
54 /*
55  * Attempt to load the file (file) as an a.out module.  It will be stored at
56  * (dest), and a pointer to a module structure describing the loaded object
57  * will be saved in (result).
58  */
59 int
60 aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
61 {
62     struct loaded_module        *mp, *kmp;
63     struct exec                 ehdr;
64     int                         fd;
65     vm_offset_t                 addr;
66     int                         err, kernel;
67     u_int                       pad;
68     char                        *s;
69
70     mp = NULL;
71     
72     /*
73      * Open the image, read and validate the a.out header 
74      */
75     if (filename == NULL)       /* can't handle nameless */
76         return(EFTYPE);
77     if ((fd = open(filename, O_RDONLY)) == -1)
78         return(errno);
79     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
80         err = EFTYPE;           /* could be EIO, but may be small file */
81         goto oerr;
82     }
83     if (N_BADMAG(ehdr)) {
84         err = EFTYPE;
85         goto oerr;
86     }
87
88     /*
89      * Check to see what sort of module we are.
90      *
91      * XXX should check N_GETMID()
92      */
93     kmp = mod_findmodule(NULL, NULL);
94     if ((N_GETFLAG(ehdr)) & EX_DYNAMIC) {
95         /* Looks like a kld module */
96         if (kmp == NULL) {
97             printf("aout_loadmodule: can't load module before kernel\n");
98             err = EPERM;
99             goto oerr;
100         }
101         if (strcmp(aout_kerneltype, kmp->m_type)) {
102             printf("aout_loadmodule: can't load module with kernel type '%s'\n", kmp->m_type);
103             err = EPERM;
104             goto oerr;
105         }
106         /* Looks OK, got ahead */
107         kernel = 0;
108
109     } else if (N_GETFLAG(ehdr) == 0) {
110         /* Looks like a kernel */
111         if (kmp != NULL) {
112             printf("aout_loadmodule: kernel already loaded\n");
113             err = EPERM;
114             goto oerr;
115         }
116         /* 
117          * Calculate destination address based on kernel entrypoint     
118          * XXX this is i386-freebsd-aout specific
119          */
120         dest = ehdr.a_entry & 0x100000;
121         if (dest == 0) {
122             printf("aout_loadmodule: not a kernel (maybe static binary?)\n");
123             err = EPERM;
124             goto oerr;
125         }
126         kernel = 1;
127     } else {
128         err = EFTYPE;
129         goto oerr;
130     }
131
132     /* 
133      * Ok, we think we should handle this.
134      */
135     mp = mod_allocmodule();
136     if (kernel)
137         setenv("kernelname", filename, 1);
138     s = strrchr(filename, '/');
139     if (s)
140         mp->m_name = strdup(s + 1); 
141     else
142         mp->m_name = strdup(filename);
143     mp->m_type = strdup(kernel ? aout_kerneltype : aout_moduletype);
144
145     /* Page-align the load address */
146     addr = dest;
147     pad = (u_int)addr & PAGE_MASK;
148     if (pad != 0) {
149         pad = PAGE_SIZE - pad;
150         addr += pad;
151     }
152     mp->m_addr = addr;                                  /* save the aligned load address */
153     if (kernel)
154         printf("%s at %p\n", filename, (void *) addr);
155
156     mp->m_size = aout_loadimage(mp, fd, addr, &ehdr, kernel);
157     if (mp->m_size == 0)
158         goto ioerr;
159
160 #if 0
161     /* Handle KLD module data */
162     if (!kernel && ((err = aout_fixupkldmod(mp, &ehdr)) != 0))
163         goto oerr;
164 #endif
165
166     /* save exec header as metadata */
167     mod_addmetadata(mp, MODINFOMD_AOUTEXEC, sizeof(struct exec), &ehdr);
168
169     /* Load OK, return module pointer */
170     *result = (struct loaded_module *)mp;
171     err = 0;
172     goto out;
173     
174  ioerr:
175     err = EIO;
176  oerr:
177     mod_discard(mp);
178  out:
179     close(fd);
180     return(err);
181 }
182
183 /*
184  * With the file (fd) open on the image, and (ehdr) containing
185  * the exec header, load the image at (addr)
186  *
187  * Fixup the a_bss field in (ehdr) to reflect the padding added to
188  * align the symbol table.
189  */
190 static int
191 aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel)
192 {
193     u_int               pad;
194     vm_offset_t         addr;
195     size_t              ss;
196     ssize_t             result;
197     vm_offset_t         ssym, esym;
198     
199     addr = loadaddr;
200     lseek(fd, (off_t)N_TXTOFF(*ehdr), SEEK_SET);
201
202     /* text segment */
203     printf("  text=0x%lx ", ehdr->a_text);
204     result = archsw.arch_readin(fd, addr, ehdr->a_text);
205     if (result < 0 || (size_t)result != ehdr->a_text)
206         return(0);
207     addr += ehdr->a_text;
208
209     /* data segment */
210     printf("data=0x%lx ", ehdr->a_data);
211     result = archsw.arch_readin(fd, addr, ehdr->a_data);
212     if (result < 0 || (size_t)result != ehdr->a_data)
213         return(0);
214     addr += ehdr->a_data;
215
216     /* For kernels, we pad the BSS to a page boundary */
217     if (kernel) {
218         pad = (u_int)ehdr->a_bss & PAGE_MASK;
219         if (pad != 0) {
220             pad = PAGE_SIZE - pad;
221             ehdr->a_bss += pad;
222         }
223     }
224     printf("bss=0x%lx ", ehdr->a_bss);
225     addr += ehdr->a_bss;
226
227     /* symbol table size */
228     ssym = esym = addr;
229     if(ehdr->a_syms!=NULL) {
230         archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms));
231         addr += sizeof(ehdr->a_syms);
232
233         /* symbol table */
234         printf("symbols=[0x%lx+0x%lx", (long)sizeof(ehdr->a_syms),ehdr->a_syms);
235         result = archsw.arch_readin(fd, addr, ehdr->a_syms);
236         if (result < 0 || (size_t)result != ehdr->a_syms)
237                 return(0);
238         addr += ehdr->a_syms;
239
240         /* string table */
241         read(fd, &ss, sizeof(ss));
242         archsw.arch_copyin(&ss, addr, sizeof(ss));
243         addr += sizeof(ss);
244         ss -= sizeof(ss);
245         printf("+0x%lx+0x%x]", (long)sizeof(ss), ss);
246         result = archsw.arch_readin(fd, addr, ss);
247         if (result < 0 || (size_t)result != ss)
248                 return(0);
249         addr += ss;
250         esym = addr;
251
252         mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym);
253         mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym);
254     } else {
255         printf("symbols=[none]");
256     }
257     printf("\n");
258
259     return(addr - loadaddr);
260 }
261
262