1 /* $NetBSD: exec.c,v 1.59 2014/04/06 19:18:00 jakllsch 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.
75 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
76 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
79 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
80 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
81 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
84 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 * @(#)boot.c 8.1 (Berkeley) 6/10/93
91 * starts NetBSD a.out kernel
92 * needs lowlevel startup from startprog.S
93 * This is a special version of exec.c to support use of XMS.
96 #include <sys/param.h>
97 #include <sys/reboot.h>
98 #include <sys/reboot.h>
100 #include <i386/multiboot.h>
102 #include <lib/libsa/stand.h>
103 #include <lib/libkern/libkern.h>
105 #include "loadfile.h"
107 #include "bootinfo.h"
117 #define PAGE_SIZE 4096
120 #define MODULE_WARNING_SEC 5
122 extern struct btinfo_console btinfo_console
;
124 boot_module_t
*boot_modules
;
125 bool boot_modules_enabled
= true;
128 typedef struct userconf_command
{
131 struct userconf_command
*uc_next
;
132 } userconf_command_t
;
133 userconf_command_t
*userconf_commands
= NULL
;
135 static struct btinfo_framebuffer btinfo_framebuffer
;
137 static struct btinfo_modulelist
*btinfo_modulelist
;
138 static size_t btinfo_modulelist_size
;
139 static uint32_t image_end
;
140 static char module_base
[64] = "/";
143 static struct btinfo_userconfcommands
*btinfo_userconfcommands
= NULL
;
144 static size_t btinfo_userconfcommands_size
= 0;
146 static void module_init(const char *);
147 static void module_add_common(const char *, uint8_t);
149 static void userconf_init(void);
152 framebuffer_configure(struct btinfo_framebuffer
*fb
)
155 btinfo_framebuffer
= *fb
;
157 btinfo_framebuffer
.physaddr
= 0;
158 btinfo_framebuffer
.flags
= 0;
163 module_add(char *name
)
165 return module_add_common(name
, BM_TYPE_KMOD
);
169 splash_add(char *name
)
171 return module_add_common(name
, BM_TYPE_IMAGE
);
177 return module_add_common(name
, BM_TYPE_RND
);
183 return module_add_common(name
, BM_TYPE_FS
);
187 module_add_common(const char *name
, uint8_t type
)
189 boot_module_t
*bm
, *bmp
;
193 while (*name
== ' ' || *name
== '\t')
196 bm
= alloc(sizeof(boot_module_t
));
197 len
= strlen(name
) + 1;
199 if (bm
== NULL
|| str
== NULL
) {
200 printf("couldn't allocate module\n");
203 memcpy(str
, name
, len
);
207 if (boot_modules
== NULL
)
210 for (bmp
= boot_modules
; bmp
->bm_next
;
218 userconf_add(char *cmd
)
220 userconf_command_t
*uc
;
224 while (*cmd
== ' ' || *cmd
== '\t')
227 uc
= alloc(sizeof(*uc
));
229 printf("couldn't allocate command\n");
233 len
= strlen(cmd
) + 1;
236 dealloc(uc
, sizeof(*uc
));
237 printf("couldn't allocate command\n");
240 memcpy(text
, cmd
, len
);
246 if (userconf_commands
== NULL
)
247 userconf_commands
= uc
;
249 userconf_command_t
*ucp
;
250 for (ucp
= userconf_commands
; ucp
->uc_next
!= NULL
;
258 common_load_kernel(const char *file
, u_long
*basemem
, u_long
*extmem
,
259 physaddr_t loadaddr
, int floppy
, u_long marks
[MARK_MAX
])
264 physaddr_t origaddr
= loadaddr
;
267 *extmem
= getextmem();
268 *basemem
= getbasemem();
271 if ((getextmem1() == 0) && (xmsmem
= checkxms())) {
275 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
276 * getextmem() is getextmem1(). Without, the "smart"
277 * methods could fail to report all memory as well.
278 * xmsmem is a few kB less than the actual size, but
279 * better than nothing.
281 if (xmsmem
> *extmem
)
284 * Get the size of the kernel
286 marks
[MARK_START
] = loadaddr
;
287 if ((fd
= loadfile(file
, marks
, COUNT_KERNEL
)) == -1)
291 kernsize
= marks
[MARK_END
];
292 kernsize
= (kernsize
+ 1023) / 1024;
294 loadaddr
= xmsalloc(kernsize
);
299 marks
[MARK_START
] = loadaddr
;
300 if ((fd
= loadfile(file
, marks
,
301 LOAD_KERNEL
& ~(floppy
? LOAD_BACKWARDS
: 0))) == -1)
306 #if !defined(__minix) /* this just gives us a cd9660-not-found warning.. */
307 /* If the root fs type is unusual, load its module. */
309 module_add_common(fsmod
, BM_TYPE_KMOD
);
310 #endif /* !defined(__minix) */
313 * Gather some information for the kernel. Do this after the
314 * "point of no return" to avoid memory leaks.
315 * (but before DOS might be trashed in the XMS case)
325 if (loadaddr
!= origaddr
) {
327 * We now have done our last DOS IO, so we may
328 * trash the OS. Copy the data from the temporary
329 * buffer to its real address.
331 marks
[MARK_START
] -= loadaddr
;
332 marks
[MARK_END
] -= loadaddr
;
333 marks
[MARK_SYM
] -= loadaddr
;
334 marks
[MARK_END
] -= loadaddr
;
335 ppbcopy(loadaddr
, origaddr
, marks
[MARK_END
]);
338 marks
[MARK_END
] = (((u_long
) marks
[MARK_END
] + sizeof(int) - 1)) &
340 image_end
= marks
[MARK_END
];
341 kernel_loaded
= true;
347 exec_netbsd(const char *file
, physaddr_t loadaddr
, int boothowto
, int floppy
,
348 void (*callback
)(void))
350 uint32_t boot_argv
[BOOT_NARGS
];
351 u_long marks
[MARK_MAX
];
352 struct btinfo_symtab btinfo_symtab
;
357 printf("exec: file=%s loadaddr=0x%lx\n",
358 file
? file
: "NULL", loadaddr
);
361 BI_ALLOC(32); /* ??? */
363 BI_ADD(&btinfo_console
, BTINFO_CONSOLE
, sizeof(struct btinfo_console
));
367 memset(marks
, 0, sizeof(marks
));
369 if (common_load_kernel(file
, &basemem
, &extmem
, loadaddr
, floppy
, marks
))
372 boot_argv
[0] = boothowto
;
374 boot_argv
[2] = vtophys(bootinfo
); /* old cyl offset */
375 boot_argv
[3] = marks
[MARK_END
];
376 boot_argv
[4] = extmem
;
377 boot_argv
[5] = basemem
;
379 /* pull in any modules if necessary */
380 if (boot_modules_enabled
) {
382 if (btinfo_modulelist
) {
383 BI_ADD(btinfo_modulelist
, BTINFO_MODULELIST
,
384 btinfo_modulelist_size
);
389 if (btinfo_userconfcommands
!= NULL
)
390 BI_ADD(btinfo_userconfcommands
, BTINFO_USERCONFCOMMANDS
,
391 btinfo_userconfcommands_size
);
394 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks
[MARK_ENTRY
],
395 marks
[MARK_NSYM
], marks
[MARK_SYM
], marks
[MARK_END
]);
398 btinfo_symtab
.nsym
= marks
[MARK_NSYM
];
399 btinfo_symtab
.ssym
= marks
[MARK_SYM
];
400 btinfo_symtab
.esym
= marks
[MARK_END
];
401 BI_ADD(&btinfo_symtab
, BTINFO_SYMTAB
, sizeof(struct btinfo_symtab
));
403 /* set new video mode if necessary */
405 BI_ADD(&btinfo_framebuffer
, BTINFO_FRAMEBUFFER
,
406 sizeof(struct btinfo_framebuffer
));
408 if (callback
!= NULL
)
410 startprog(marks
[MARK_ENTRY
], BOOT_NARGS
, boot_argv
,
411 x86_trunc_page(basemem
*1024));
412 panic("exec returned");
421 extract_device(const char *path
, char *buf
, size_t buflen
)
425 if (strchr(path
, ':') != NULL
) {
426 for (i
= 0; i
< buflen
- 2 && path
[i
] != ':'; i
++)
435 module_path(boot_module_t
*bm
, const char *kdev
)
437 static char buf
[256];
438 char name_buf
[256], dev_buf
[64];
439 const char *name
, *name2
, *p
;
442 for (name2
= name
; *name2
; ++name2
) {
443 if (*name2
== ' ' || *name2
== '\t') {
444 strlcpy(name_buf
, name
, sizeof(name_buf
));
445 if ((uintptr_t)name2
- (uintptr_t)name
< sizeof(name_buf
))
446 name_buf
[name2
- name
] = '\0';
451 if ((p
= strchr(name
, ':')) != NULL
) {
452 /* device specified, use it */
454 snprintf(buf
, sizeof(buf
), "%s", name
);
457 extract_device(name
, dev_buf
, sizeof(dev_buf
));
458 snprintf(buf
, sizeof(buf
), "%s%s/%s/%s.kmod",
459 dev_buf
, module_base
, p
, p
);
462 /* device not specified; load from kernel device if known */
464 snprintf(buf
, sizeof(buf
), "%s%s", kdev
, name
);
466 snprintf(buf
, sizeof(buf
), "%s%s/%s/%s.kmod",
467 kdev
, module_base
, name
, name
);
474 module_open(boot_module_t
*bm
, int mode
, const char *kdev
, bool doload
)
479 /* check the expanded path first */
480 path
= module_path(bm
, kdev
);
481 fd
= open(path
, mode
);
483 if ((howto
& AB_SILENT
) == 0 && doload
)
484 printf("Loading %s ", path
);
486 /* now attempt the raw path provided */
487 fd
= open(bm
->bm_path
, mode
);
488 if (fd
!= -1 && (howto
& AB_SILENT
) == 0 && doload
)
489 printf("Loading %s ", bm
->bm_path
);
491 if (!doload
&& fd
== -1) {
492 printf("WARNING: couldn't open %s", bm
->bm_path
);
493 if (strcmp(bm
->bm_path
, path
) != 0)
494 printf(" (%s)", path
);
501 module_init(const char *kernel_path
)
503 struct bi_modulelist_entry
*bi
;
511 int err
, fd
, nfail
= 0;
513 extract_device(kernel_path
, kdev
, sizeof(kdev
));
515 switch (netbsd_elf_class
) {
526 if (netbsd_version
/ 1000000 % 100 == 99) {
528 snprintf(module_base
, sizeof(module_base
),
529 "/stand/%s/%d.%d.%d/modules", machine
,
530 netbsd_version
/ 100000000,
531 netbsd_version
/ 1000000 % 100,
532 netbsd_version
/ 100 % 100);
533 } else if (netbsd_version
!= 0) {
535 snprintf(module_base
, sizeof(module_base
),
536 "/stand/%s/%d.%d/modules", machine
,
537 netbsd_version
/ 100000000,
538 netbsd_version
/ 1000000 % 100);
541 /* First, see which modules are valid and calculate btinfo size */
542 len
= sizeof(struct btinfo_modulelist
);
543 for (bm
= boot_modules
; bm
; bm
= bm
->bm_next
) {
544 fd
= module_open(bm
, 0, kdev
, false);
550 err
= fstat(fd
, &st
);
551 if (err
== -1 || st
.st_size
== -1) {
552 printf("WARNING: couldn't stat %s\n", bm
->bm_path
);
558 bm
->bm_len
= st
.st_size
;
560 len
+= sizeof(struct bi_modulelist_entry
);
563 /* Allocate the module list */
564 btinfo_modulelist
= alloc(len
);
565 if (btinfo_modulelist
== NULL
) {
566 printf("WARNING: couldn't allocate module list\n");
567 wait_sec(MODULE_WARNING_SEC
);
570 memset(btinfo_modulelist
, 0, len
);
571 btinfo_modulelist_size
= len
;
573 /* Fill in btinfo structure */
574 buf
= (char *)btinfo_modulelist
;
575 btinfo_modulelist
->num
= 0;
576 off
= sizeof(struct btinfo_modulelist
);
578 for (bm
= boot_modules
; bm
; bm
= bm
->bm_next
) {
579 if (bm
->bm_len
== -1)
581 fd
= module_open(bm
, 0, kdev
, true);
584 image_end
= (image_end
+ PAGE_SIZE
- 1) & ~(PAGE_SIZE
- 1);
585 len
= pread(fd
, (void *)(uintptr_t)image_end
, SSIZE_MAX
);
586 if (len
< bm
->bm_len
) {
587 if ((howto
& AB_SILENT
) != 0)
588 printf("Loading %s ", bm
->bm_path
);
591 btinfo_modulelist
->num
++;
592 bi
= (struct bi_modulelist_entry
*)(buf
+ off
);
593 off
+= sizeof(struct bi_modulelist_entry
);
594 strncpy(bi
->path
, bm
->bm_path
, sizeof(bi
->path
) - 1);
595 bi
->base
= image_end
;
597 switch (bm
->bm_type
) {
599 bi
->type
= BI_MODULE_ELF
;
602 bi
->type
= BI_MODULE_IMAGE
;
605 bi
->type
= BI_MODULE_FS
;
609 /* safest -- rnd checks the sha1 */
610 bi
->type
= BI_MODULE_RND
;
613 if ((howto
& AB_SILENT
) == 0)
620 btinfo_modulelist
->endpa
= image_end
;
623 printf("WARNING: %d module%s failed to load\n",
624 nfail
, nfail
== 1 ? "" : "s");
626 wait_sec(MODULE_WARNING_SEC
);
635 userconf_command_t
*uc
;
639 /* Calculate the userconf commands list size */
641 for (uc
= userconf_commands
; uc
!= NULL
; uc
= uc
->uc_next
)
643 len
= sizeof(*btinfo_userconfcommands
) +
644 count
* sizeof(struct bi_userconfcommand
);
646 /* Allocate the userconf commands list */
647 btinfo_userconfcommands
= alloc(len
);
648 if (btinfo_userconfcommands
== NULL
) {
649 printf("WARNING: couldn't allocate userconf commands list\n");
652 memset(btinfo_userconfcommands
, 0, len
);
653 btinfo_userconfcommands_size
= len
;
655 /* Fill in btinfo structure */
656 buf
= (char *)btinfo_userconfcommands
;
657 off
= sizeof(*btinfo_userconfcommands
);
658 btinfo_userconfcommands
->num
= 0;
659 for (uc
= userconf_commands
; uc
!= NULL
; uc
= uc
->uc_next
) {
660 struct bi_userconfcommand
*bi
;
661 bi
= (struct bi_userconfcommand
*)(buf
+ off
);
662 strncpy(bi
->text
, uc
->uc_text
, sizeof(bi
->text
) - 1);
665 btinfo_userconfcommands
->num
++;
669 #if defined(PASS_MEMMAP) && defined(__minix)
671 * Construct a memory map for the multiboot info structure, with memory ranges
672 * as reported by the BIOS. If successful, set the HAS_MMAP flag. Code copied
673 * largely from bootinfo_memmap.c.
676 memmap_init(struct multiboot_info
* mbi
)
678 multiboot_memory_map_t
*mmap
;
679 int buf
[5], i
, nranges
;
684 if (getmementry(&i
, buf
))
692 mbi
->mmap_length
= sizeof(multiboot_memory_map_t
) * nranges
;
694 mmap
= alloc(mbi
->mmap_length
);
696 mbi
->mmap_addr
= vtophys(mmap
);
699 while (nranges
-- > 0) {
700 getmementry(&i
, buf
);
702 /* Stupid tricks to deal with alignment issues. */
703 memcpy(&mmap
->mm_base_addr
, buf
, sizeof(buf
));
704 mmap
->mm_size
= sizeof(*mmap
) - sizeof(mmap
->mm_size
);
708 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_MMAP
;
710 #endif /* PASS_MEMMAP && __minix */
713 exec_multiboot(const char *file
, char *args
)
715 struct multiboot_info
*mbi
;
716 struct multiboot_module
*mbm
;
717 struct bi_modulelist_entry
*bim
;
719 u_long marks
[MARK_MAX
];
724 mbi
= alloc(sizeof(struct multiboot_info
));
725 mbi
->mi_flags
= MULTIBOOT_INFO_HAS_MEMORY
;
727 if (common_load_kernel(file
, &basemem
, &extmem
, 0, 0, marks
))
730 mbi
->mi_mem_upper
= extmem
;
731 mbi
->mi_mem_lower
= basemem
;
734 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_CMDLINE
;
735 len
= strlen(file
) + 1 + strlen(args
) + 1;
736 cmdline
= alloc(len
);
737 snprintf(cmdline
, len
, "%s %s", file
, args
);
738 mbi
->mi_cmdline
= (char *) vtophys(cmdline
);
741 /* pull in any modules if necessary */
742 if (boot_modules_enabled
) {
744 if (btinfo_modulelist
) {
745 mbm
= alloc(sizeof(struct multiboot_module
) *
746 btinfo_modulelist
->num
);
748 bim
= (struct bi_modulelist_entry
*)
749 (((char *) btinfo_modulelist
) +
750 sizeof(struct btinfo_modulelist
));
751 for (i
= 0; i
< btinfo_modulelist
->num
; i
++) {
752 mbm
[i
].mmo_start
= bim
->base
;
753 mbm
[i
].mmo_end
= bim
->base
+ bim
->len
;
754 mbm
[i
].mmo_string
= (char *)vtophys(bim
->path
);
755 mbm
[i
].mmo_reserved
= 0;
758 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_MODS
;
759 mbi
->mi_mods_count
= btinfo_modulelist
->num
;
760 mbi
->mi_mods_addr
= vtophys(mbm
);
764 #if defined(PASS_MEMMAP) && defined(__minix)
766 * The MINIX3 kernel needs a full memory map. Without it, it will do
767 * silly things such as overwriting the ACPI tables.
770 #endif /* PASS_MEMMAP && __minix */
773 printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks
[MARK_ENTRY
],
774 marks
[MARK_NSYM
], marks
[MARK_SYM
], marks
[MARK_END
]);
779 if (btinfo_symtab
.nsym
) {
780 mbi
->mi_flags
|= MULTIBOOT_INFO_HAS_ELF_SYMS
;
781 mbi
->mi_elfshdr_addr
= marks
[MARK_SYM
];
782 btinfo_symtab
.nsym
= marks
[MARK_NSYM
];
783 btinfo_symtab
.ssym
= marks
[MARK_SYM
];
784 btinfo_symtab
.esym
= marks
[MARK_END
];
787 multiboot(marks
[MARK_ENTRY
], vtophys(mbi
),
788 x86_trunc_page(mbi
->mi_mem_lower
*1024));
789 panic("exec returned");
797 x86_progress(const char *fmt
, ...)
801 if ((howto
& AB_SILENT
) != 0)