1 /* $NetBSD: exec.c,v 1.41 2009/09/13 18:13:37 jmcneill Exp $ */
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
30 * Copyright (c) 1982, 1986, 1990, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
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.
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
57 * @(#)boot.c 8.1 (Berkeley) 6/10/93
62 * Matthias Drochner. All rights reserved.
64 * Perry E. Metzger. All rights reserved.
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
69 * 1. Redistributions of source code must retain the above copyright
70 * notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 * notice, this list of conditions and the following disclaimer in the
73 * documentation and/or other materials provided with the distribution.
74 * 3. All advertising materials mentioning features or use of this software
75 * must display the following acknowledgement:
76 * This product includes software developed by the University of
77 * California, Berkeley and its contributors.
78 * 4. Neither the name of the University nor the names of its contributors
79 * may be used to endorse or promote products derived from this software
80 * without specific prior written permission.
82 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
83 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
86 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94 * @(#)boot.c 8.1 (Berkeley) 6/10/93
98 * starts NetBSD a.out kernel
99 * needs lowlevel startup from startprog.S
100 * This is a special version of exec.c to support use of XMS.
103 #include <sys/param.h>
104 #include <sys/reboot.h>
105 #include <sys/reboot.h>
107 #include <machine/multiboot.h>
108 #include <machine/stdarg.h>
110 #include <lib/libsa/stand.h>
111 #include <lib/libkern/libkern.h>
113 #include "loadfile.h"
115 #include "bootinfo.h"
125 #define PAGE_SIZE 4096
128 #define MODULE_WARNING_DELAY 5000000
130 extern struct btinfo_console btinfo_console
;
132 boot_module_t
*boot_modules
;
133 bool boot_modules_enabled
= true;
136 static struct btinfo_framebuffer btinfo_framebuffer
;
138 static struct btinfo_modulelist
*btinfo_modulelist
;
139 static size_t btinfo_modulelist_size
;
140 static uint32_t image_end
;
141 static char module_base
[64] = "/";
144 static void module_init(const char *);
147 framebuffer_configure(struct btinfo_framebuffer
*fb
)
150 btinfo_framebuffer
= *fb
;
152 btinfo_framebuffer
.physaddr
= 0;
153 btinfo_framebuffer
.flags
= 0;
158 module_add(char *name
)
160 boot_module_t
*bm
, *bmp
;
164 while (*name
== ' ' || *name
== '\t')
167 bm
= alloc(sizeof(boot_module_t
));
168 len
= strlen(name
) + 1;
170 if (bm
== NULL
|| str
== NULL
) {
171 printf("couldn't allocate module\n");
174 memcpy(str
, name
, len
);
177 if (boot_modules
== NULL
)
180 for (bmp
= boot_modules
; bmp
->bm_next
;
188 common_load_kernel(const char *file
, u_long
*basemem
, u_long
*extmem
,
189 physaddr_t loadaddr
, int floppy
, u_long marks
[MARK_MAX
])
194 physaddr_t origaddr
= loadaddr
;
197 *extmem
= getextmem();
198 *basemem
= getbasemem();
201 if ((getextmem1() == 0) && (xmsmem
= checkxms())) {
205 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
206 * getextmem() is getextmem1(). Without, the "smart"
207 * methods could fail to report all memory as well.
208 * xmsmem is a few kB less than the actual size, but
209 * better than nothing.
211 if (xmsmem
> *extmem
)
214 * Get the size of the kernel
216 marks
[MARK_START
] = loadaddr
;
217 if ((fd
= loadfile(file
, marks
, COUNT_KERNEL
)) == -1)
221 kernsize
= marks
[MARK_END
];
222 kernsize
= (kernsize
+ 1023) / 1024;
224 loadaddr
= xmsalloc(kernsize
);
229 marks
[MARK_START
] = loadaddr
;
230 if ((fd
= loadfile(file
, marks
,
231 LOAD_KERNEL
& ~(floppy
? LOAD_NOTE
: 0))) == -1)
236 /* Now we know the root fs type, load modules for it. */
238 if (fsmod2
!= NULL
&& strcmp(fsmod
, fsmod2
) != 0)
242 * Gather some information for the kernel. Do this after the
243 * "point of no return" to avoid memory leaks.
244 * (but before DOS might be trashed in the XMS case)
254 if (loadaddr
!= origaddr
) {
256 * We now have done our last DOS IO, so we may
257 * trash the OS. Copy the data from the temporary
258 * buffer to its real address.
260 marks
[MARK_START
] -= loadaddr
;
261 marks
[MARK_END
] -= loadaddr
;
262 marks
[MARK_SYM
] -= loadaddr
;
263 marks
[MARK_END
] -= loadaddr
;
264 ppbcopy(loadaddr
, origaddr
, marks
[MARK_END
]);
267 marks
[MARK_END
] = (((u_long
) marks
[MARK_END
] + sizeof(int) - 1)) &
269 image_end
= marks
[MARK_END
];
270 kernel_loaded
= true;
276 exec_netbsd(const char *file
, physaddr_t loadaddr
, int boothowto
, int floppy
,
277 void (*callback
)(void))
279 u_long boot_argv
[BOOT_NARGS
];
280 u_long marks
[MARK_MAX
];
281 struct btinfo_symtab btinfo_symtab
;
286 printf("exec: file=%s loadaddr=0x%lx\n",
287 file
? file
: "NULL", loadaddr
);
290 BI_ALLOC(32); /* ??? */
292 BI_ADD(&btinfo_console
, BTINFO_CONSOLE
, sizeof(struct btinfo_console
));
296 if (common_load_kernel(file
, &basemem
, &extmem
, loadaddr
, floppy
, marks
))
299 boot_argv
[0] = boothowto
;
301 boot_argv
[2] = vtophys(bootinfo
); /* old cyl offset */
302 boot_argv
[3] = marks
[MARK_END
];
303 boot_argv
[4] = extmem
;
304 boot_argv
[5] = basemem
;
306 /* pull in any modules if necessary */
307 if (boot_modules_enabled
) {
309 if (btinfo_modulelist
) {
310 BI_ADD(btinfo_modulelist
, BTINFO_MODULELIST
,
311 btinfo_modulelist_size
);
316 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks
[MARK_ENTRY
],
317 marks
[MARK_NSYM
], marks
[MARK_SYM
], marks
[MARK_END
]);
320 btinfo_symtab
.nsym
= marks
[MARK_NSYM
];
321 btinfo_symtab
.ssym
= marks
[MARK_SYM
];
322 btinfo_symtab
.esym
= marks
[MARK_END
];
323 BI_ADD(&btinfo_symtab
, BTINFO_SYMTAB
, sizeof(struct btinfo_symtab
));
325 /* set new video mode if necessary */
327 BI_ADD(&btinfo_framebuffer
, BTINFO_FRAMEBUFFER
,
328 sizeof(struct btinfo_framebuffer
));
330 if (callback
!= NULL
)
332 startprog(marks
[MARK_ENTRY
], BOOT_NARGS
, boot_argv
,
333 x86_trunc_page(basemem
*1024));
334 panic("exec returned");
343 extract_device(const char *path
, char *buf
, size_t buflen
)
347 if (strchr(path
, ':') != NULL
) {
348 for (i
= 0; i
< buflen
- 2 && path
[i
] != ':'; i
++)
357 module_path(boot_module_t
*bm
, const char *kdev
)
359 static char buf
[256];
360 char name_buf
[256], dev_buf
[64];
361 const char *name
, *name2
, *p
;
364 for (name2
= name
; *name2
; ++name2
) {
365 if (*name2
== ' ' || *name2
== '\t') {
366 strlcpy(name_buf
, name
, sizeof(name_buf
));
367 if (name2
- name
< sizeof(name_buf
))
368 name_buf
[name2
- name
] = '\0';
373 if ((p
= strchr(name
, ':')) != NULL
) {
374 /* device specified, use it */
376 snprintf(buf
, sizeof(buf
), "%s", name
);
379 extract_device(name
, dev_buf
, sizeof(dev_buf
));
380 snprintf(buf
, sizeof(buf
), "%s%s/%s/%s.kmod",
381 dev_buf
, module_base
, p
, p
);
384 /* device not specified; load from kernel device if known */
386 snprintf(buf
, sizeof(buf
), "%s%s", kdev
, name
);
388 snprintf(buf
, sizeof(buf
), "%s%s/%s/%s.kmod",
389 kdev
, module_base
, name
, name
);
396 module_open(boot_module_t
*bm
, int mode
, const char *kdev
, bool doload
)
401 /* check the expanded path first */
402 path
= module_path(bm
, kdev
);
403 fd
= open(path
, mode
);
405 if ((howto
& AB_SILENT
) == 0 && doload
)
406 printf("Loading %s ", path
);
408 /* now attempt the raw path provided */
409 fd
= open(bm
->bm_path
, mode
);
410 if (fd
!= -1 && (howto
& AB_SILENT
) == 0 && doload
)
411 printf("Loading %s ", bm
->bm_path
);
413 if (!doload
&& fd
== -1) {
414 printf("WARNING: couldn't open %s", bm
->bm_path
);
415 if (strcmp(bm
->bm_path
, path
) != 0)
416 printf(" (%s)", path
);
423 module_init(const char *kernel_path
)
425 struct bi_modulelist_entry
*bi
;
433 int err
, fd
, nfail
= 0;
435 extract_device(kernel_path
, kdev
, sizeof(kdev
));
437 switch (netbsd_elf_class
) {
448 if (netbsd_version
/ 1000000 % 100 == 99) {
450 snprintf(module_base
, sizeof(module_base
),
451 "/stand/%s/%d.%d.%d/modules", machine
,
452 netbsd_version
/ 100000000,
453 netbsd_version
/ 1000000 % 100,
454 netbsd_version
/ 100 % 100);
455 } else if (netbsd_version
!= 0) {
457 snprintf(module_base
, sizeof(module_base
),
458 "/stand/%s/%d.%d/modules", machine
,
459 netbsd_version
/ 100000000,
460 netbsd_version
/ 1000000 % 100);
463 /* First, see which modules are valid and calculate btinfo size */
464 len
= sizeof(struct btinfo_modulelist
);
465 for (bm
= boot_modules
; bm
; bm
= bm
->bm_next
) {
466 fd
= module_open(bm
, 0, kdev
, false);
472 err
= fstat(fd
, &st
);
473 if (err
== -1 || st
.st_size
== -1) {
474 printf("WARNING: couldn't stat %s\n", bm
->bm_path
);
480 bm
->bm_len
= st
.st_size
;
482 len
+= sizeof(struct bi_modulelist_entry
);
485 /* Allocate the module list */
486 btinfo_modulelist
= alloc(len
);
487 if (btinfo_modulelist
== NULL
) {
488 printf("WARNING: couldn't allocate module list\n");
489 delay(MODULE_WARNING_DELAY
);
492 memset(btinfo_modulelist
, 0, len
);
493 btinfo_modulelist_size
= len
;
495 /* Fill in btinfo structure */
496 buf
= (char *)btinfo_modulelist
;
497 btinfo_modulelist
->num
= 0;
498 off
= sizeof(struct btinfo_modulelist
);
500 for (bm
= boot_modules
; bm
; bm
= bm
->bm_next
) {
501 if (bm
->bm_len
== -1)
503 fd
= module_open(bm
, 0, kdev
, true);
506 image_end
= (image_end
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1);
507 len
= pread(fd
, (void *)image_end
, SSIZE_MAX
);
508 if (len
< bm
->bm_len
) {
509 if ((howto
& AB_SILENT
) != 0)
510 printf("Loading %s ", bm
->bm_path
);
513 btinfo_modulelist
->num
++;
514 bi
= (struct bi_modulelist_entry
*)(buf
+ off
);
515 off
+= sizeof(struct bi_modulelist_entry
);
516 strncpy(bi
->path
, bm
->bm_path
, sizeof(bi
->path
) - 1);
517 bi
->base
= image_end
;
519 bi
->type
= BI_MODULE_ELF
;
520 if ((howto
& AB_SILENT
) == 0)
527 btinfo_modulelist
->endpa
= image_end
;
530 printf("WARNING: %d module%s failed to load\n",
531 nfail
, nfail
== 1 ? "" : "s");
533 delay(MODULE_WARNING_DELAY
);
539 exec_multiboot(const char *file
, char *args
)
541 struct multiboot_info
*mbi
;
542 struct multiboot_module
*mbm
;
543 struct bi_modulelist_entry
*bim
;
545 u_long marks
[MARK_MAX
];
550 mbi
= alloc(sizeof(struct multiboot_info
));
551 mbi
->mi_flags
= MULTIBOOT_INFO_HAS_MEMORY
;
553 if (common_load_kernel(file
, &basemem
, &extmem
, 0, 0, marks
))
556 mbi
->mi_mem_upper
= extmem
;
557 mbi
->mi_mem_lower
= basemem
;
560 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_CMDLINE
;
561 len
= strlen(file
) + 1 + strlen(args
) + 1;
562 cmdline
= alloc(len
);
563 snprintf(cmdline
, len
, "%s %s", file
, args
);
564 mbi
->mi_cmdline
= (char *) vtophys(cmdline
);
567 /* pull in any modules if necessary */
568 if (boot_modules_enabled
) {
570 if (btinfo_modulelist
) {
571 mbm
= alloc(sizeof(struct multiboot_module
) *
572 btinfo_modulelist
->num
);
574 bim
= (struct bi_modulelist_entry
*)
575 (((char *) btinfo_modulelist
) +
576 sizeof(struct btinfo_modulelist
));
577 for (i
= 0; i
< btinfo_modulelist
->num
; i
++) {
578 mbm
[i
].mmo_start
= bim
->base
;
579 mbm
[i
].mmo_end
= bim
->base
+ bim
->len
;
580 mbm
[i
].mmo_string
= (char *)vtophys(bim
->path
);
581 mbm
[i
].mmo_reserved
= 0;
584 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_MODS
;
585 mbi
->mi_mods_count
= btinfo_modulelist
->num
;
586 mbi
->mi_mods_addr
= vtophys(mbm
);
591 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks
[MARK_ENTRY
],
592 marks
[MARK_NSYM
], marks
[MARK_SYM
], marks
[MARK_END
]);
597 if (btinfo_symtab
.nsym
) {
598 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_ELF_SYMS
;
599 mbi
->mi_elfshdr_addr
= marks
[MARK_SYM
];
600 btinfo_symtab
.nsym
= marks
[MARK_NSYM
];
601 btinfo_symtab
.ssym
= marks
[MARK_SYM
];
602 btinfo_symtab
.esym
= marks
[MARK_END
];
605 multiboot(marks
[MARK_ENTRY
], vtophys(mbi
),
606 x86_trunc_page(mbi
->mi_mem_lower
*1024));
607 panic("exec returned");
615 x86_progress(const char *fmt
, ...)
619 if ((howto
& AB_SILENT
) != 0)