xref: /netbsd-src/sys/arch/i386/stand/lib/exec.c (revision cd22f25e6f6d1cc1f197fe8c5468a80f51d1c4e1)
1 /*	$NetBSD: exec.c,v 1.23 2008/05/02 15:26:38 ad Exp $	 */
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Copyright (c) 1982, 1986, 1990, 1993
31  *	The Regents of the University of California.  All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 3. Neither the name of the University nor the names of its contributors
42  *    may be used to endorse or promote products derived from this software
43  *    without specific prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  *
57  * 	@(#)boot.c	8.1 (Berkeley) 6/10/93
58  */
59 
60 /*
61  * Copyright (c) 1996
62  *	Matthias Drochner.  All rights reserved.
63  * Copyright (c) 1996
64  * 	Perry E. Metzger.  All rights reserved.
65  * Copyright (c) 1997
66  * 	Martin Husemann.  All rights reserved.
67  *
68  * Redistribution and use in source and binary forms, with or without
69  * modification, are permitted provided that the following conditions
70  * are met:
71  * 1. Redistributions of source code must retain the above copyright
72  *    notice, this list of conditions and the following disclaimer.
73  * 2. Redistributions in binary form must reproduce the above copyright
74  *    notice, this list of conditions and the following disclaimer in the
75  *    documentation and/or other materials provided with the distribution.
76  * 3. All advertising materials mentioning features or use of this software
77  *    must display the following acknowledgement:
78  *	This product includes software developed by the University of
79  *	California, Berkeley and its contributors.
80  * 4. Neither the name of the University nor the names of its contributors
81  *    may be used to endorse or promote products derived from this software
82  *    without specific prior written permission.
83  *
84  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
85  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
87  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
88  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
90  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94  * SUCH DAMAGE.
95  *
96  * 	@(#)boot.c	8.1 (Berkeley) 6/10/93
97  */
98 
99 /*
100  * starts NetBSD a.out kernel
101  * needs lowlevel startup from startprog.S
102  * This is a special version of exec.c to support use of XMS.
103  */
104 
105 #include <sys/param.h>
106 #include <sys/reboot.h>
107 
108 #include <lib/libsa/stand.h>
109 #include <lib/libkern/libkern.h>
110 
111 #include "loadfile.h"
112 #include "libi386.h"
113 #include "bootinfo.h"
114 #include "bootmod.h"
115 #ifdef SUPPORT_PS2
116 #include "biosmca.h"
117 #endif
118 
119 #define BOOT_NARGS	6
120 
121 #ifndef	PAGE_SIZE
122 #define	PAGE_SIZE	4096
123 #endif
124 
125 extern struct btinfo_console btinfo_console;
126 
127 boot_module_t *boot_modules;
128 bool boot_modules_enabled = true;
129 bool kernel_loaded;
130 
131 static struct btinfo_modulelist *btinfo_modulelist;
132 static size_t btinfo_modulelist_size;
133 static uint32_t image_end;
134 
135 static uint8_t *module_alloc(size_t);
136 static void	module_init(void);
137 
138 int
139 exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto)
140 {
141 	u_long          boot_argv[BOOT_NARGS];
142 	int		fd;
143 	u_long		marks[MARK_MAX];
144 	struct btinfo_symtab btinfo_symtab;
145 	u_long		extmem;
146 	u_long		basemem;
147 #ifdef XMS
148 	u_long		xmsmem;
149 	physaddr_t	origaddr = loadaddr;
150 #endif
151 
152 #ifdef	DEBUG
153 	printf("exec: file=%s loadaddr=0x%lx\n",
154 	       file ? file : "NULL", loadaddr);
155 #endif
156 
157 	BI_ALLOC(32); /* ??? */
158 
159 	BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console));
160 
161 	extmem = getextmem();
162 	basemem = getbasemem();
163 
164 #ifdef XMS
165 	if ((getextmem1() == 0) && (xmsmem = checkxms())) {
166 	        u_long kernsize;
167 
168 		/*
169 		 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
170 		 *  getextmem() is getextmem1(). Without, the "smart"
171 		 *  methods could fail to report all memory as well.
172 		 * xmsmem is a few kB less than the actual size, but
173 		 *  better than nothing.
174 		 */
175 		if (xmsmem > extmem)
176 			extmem = xmsmem;
177 		/*
178 		 * Get the size of the kernel
179 		 */
180 		marks[MARK_START] = loadaddr;
181 		if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
182 			goto out;
183 		close(fd);
184 
185 		kernsize = marks[MARK_END];
186 		kernsize = (kernsize + 1023) / 1024;
187 
188 		loadaddr = xmsalloc(kernsize);
189 		if (!loadaddr)
190 			return ENOMEM;
191 	}
192 #endif
193 	marks[MARK_START] = loadaddr;
194 	if ((fd = loadfile(file, marks, LOAD_KERNEL)) == -1)
195 		goto out;
196 
197 	boot_argv[0] = boothowto;
198 	boot_argv[1] = 0;
199 	boot_argv[2] = vtophys(bootinfo);	/* old cyl offset */
200 	/* argv[3] below */
201 	boot_argv[4] = extmem;
202 	boot_argv[5] = basemem;
203 
204 	close(fd);
205 
206 	/*
207 	 * Gather some information for the kernel. Do this after the
208 	 * "point of no return" to avoid memory leaks.
209 	 * (but before DOS might be trashed in the XMS case)
210 	 */
211 #ifdef PASS_BIOSGEOM
212 	bi_getbiosgeom();
213 #endif
214 #ifdef PASS_MEMMAP
215 	bi_getmemmap();
216 #endif
217 
218 #ifdef XMS
219 	if (loadaddr != origaddr) {
220 		/*
221 		 * We now have done our last DOS IO, so we may
222 		 * trash the OS. Copy the data from the temporary
223 		 * buffer to its real address.
224 		 */
225 		marks[MARK_START] -= loadaddr;
226 		marks[MARK_END] -= loadaddr;
227 		marks[MARK_SYM] -= loadaddr;
228 		marks[MARK_END] -= loadaddr;
229 		ppbcopy(loadaddr, origaddr, marks[MARK_END]);
230 	}
231 #endif
232 	marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
233 	    (-sizeof(int));
234 	boot_argv[3] = marks[MARK_END];
235 	image_end = marks[MARK_END];
236 	kernel_loaded = true;
237 
238 	/* pull in any modules if necessary */
239 	if (boot_modules_enabled) {
240 		module_init();
241 		if (btinfo_modulelist) {
242 			BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
243 			    btinfo_modulelist_size);
244 		}
245 	}
246 
247 #ifdef DEBUG
248 	printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
249 	    marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
250 #endif
251 
252 	btinfo_symtab.nsym = marks[MARK_NSYM];
253 	btinfo_symtab.ssym = marks[MARK_SYM];
254 	btinfo_symtab.esym = marks[MARK_END];
255 	BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab));
256 
257 	startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
258 		  x86_trunc_page(basemem*1024));
259 	panic("exec returned");
260 
261 out:
262 	BI_FREE();
263 	bootinfo = 0;
264 	return -1;
265 }
266 
267 static uint8_t *
268 module_alloc(size_t len)
269 {
270 	uint32_t addr;
271 
272 	addr = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
273 	image_end += (len + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
274 
275 #ifdef DEBUG
276 	printf("Allocated %d bytes of module memory at %x\n", len, addr);
277 #endif
278 
279 	return (uint8_t *)addr;
280 }
281 
282 static void
283 module_init(void)
284 {
285 	struct bi_modulelist_entry *bi;
286 	struct stat st;
287 	char *buf;
288 	boot_module_t *bm;
289 	size_t len;
290 	off_t off;
291 	int err, fd;
292 
293 	/* First, see which modules are valid and calculate btinfo size */
294 	len = sizeof(struct btinfo_modulelist);
295 	for (bm = boot_modules; bm; bm = bm->bm_next) {
296 		fd = open(bm->bm_path, 0);
297 		if (fd == -1) {
298 			printf("WARNING: couldn't open %s\n", bm->bm_path);
299 			bm->bm_len = -1;
300 			continue;
301 		}
302 		err = fstat(fd, &st);
303 		if (err == -1) {
304 			printf("WARNING: couldn't stat %s\n", bm->bm_path);
305 			close(fd);
306 			bm->bm_len = -1;
307 			continue;
308 		}
309 		bm->bm_len = st.st_size;
310 		close(fd);
311 		len += sizeof(struct bi_modulelist_entry);
312 	}
313 
314 	/* Allocate the module list */
315 	btinfo_modulelist = alloc(len);
316 	if (btinfo_modulelist == NULL) {
317 		printf("WARNING: couldn't allocate module list\n");
318 		return;
319 	}
320 	memset(btinfo_modulelist, 0, len);
321 	btinfo_modulelist_size = len;
322 
323 	/* Fill in btinfo structure */
324 	buf = (char *)btinfo_modulelist;
325 	btinfo_modulelist->num = 0;
326 	off = sizeof(struct btinfo_modulelist);
327 
328 	for (bm = boot_modules; bm; bm = bm->bm_next) {
329 		if (bm->bm_len == -1)
330 			continue;
331 		printf("Loading %s ", bm->bm_path);
332 		bm->bm_data = module_alloc(bm->bm_len);
333 		if (bm->bm_data == NULL) {
334 			printf("NO MEMORY\n");
335 			continue;
336 		}
337 		fd = open(bm->bm_path, 0);
338 		if (fd == -1) {
339 			printf("ERROR: couldn't open %s\n", bm->bm_path);
340 			continue;
341 		}
342 		len = pread(fd, bm->bm_data, bm->bm_len);
343 		if (len != bm->bm_len) {
344 			printf(" FAILED\n");
345 		} else {
346 			btinfo_modulelist->num++;
347 			bi = (struct bi_modulelist_entry *)(buf + off);
348 			off += sizeof(struct bi_modulelist_entry);
349 			strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1);
350 			bi->base = (uint32_t)bm->bm_data;
351 			bi->len = bm->bm_len;
352 			bi->type = BI_MODULE_ELF;
353 			printf(" \n");
354 		}
355 		close(fd);
356 	}
357 	btinfo_modulelist->endpa = image_end;
358 }
359