1*f14fb602SLionel Sambuc /* $NetBSD: exec.c,v 1.50 2012/05/21 21:34:16 dsl Exp $ */ 258a2b000SEvgeniy Ivanov 358a2b000SEvgeniy Ivanov /*- 458a2b000SEvgeniy Ivanov * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 558a2b000SEvgeniy Ivanov * All rights reserved. 658a2b000SEvgeniy Ivanov * 758a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 858a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 958a2b000SEvgeniy Ivanov * are met: 1058a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 1158a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 1258a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 1358a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 1458a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 1558a2b000SEvgeniy Ivanov * 1658a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1758a2b000SEvgeniy Ivanov * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 1858a2b000SEvgeniy Ivanov * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1958a2b000SEvgeniy Ivanov * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2058a2b000SEvgeniy Ivanov * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2158a2b000SEvgeniy Ivanov * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2258a2b000SEvgeniy Ivanov * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2358a2b000SEvgeniy Ivanov * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2458a2b000SEvgeniy Ivanov * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2558a2b000SEvgeniy Ivanov * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2658a2b000SEvgeniy Ivanov * POSSIBILITY OF SUCH DAMAGE. 2758a2b000SEvgeniy Ivanov */ 2858a2b000SEvgeniy Ivanov 2958a2b000SEvgeniy Ivanov /* 3058a2b000SEvgeniy Ivanov * Copyright (c) 1982, 1986, 1990, 1993 3158a2b000SEvgeniy Ivanov * The Regents of the University of California. All rights reserved. 3258a2b000SEvgeniy Ivanov * 3358a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 3458a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 3558a2b000SEvgeniy Ivanov * are met: 3658a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 3758a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 3858a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 3958a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 4058a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 4158a2b000SEvgeniy Ivanov * 3. Neither the name of the University nor the names of its contributors 4258a2b000SEvgeniy Ivanov * may be used to endorse or promote products derived from this software 4358a2b000SEvgeniy Ivanov * without specific prior written permission. 4458a2b000SEvgeniy Ivanov * 4558a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 4658a2b000SEvgeniy Ivanov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4758a2b000SEvgeniy Ivanov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4858a2b000SEvgeniy Ivanov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 4958a2b000SEvgeniy Ivanov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5058a2b000SEvgeniy Ivanov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5158a2b000SEvgeniy Ivanov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5258a2b000SEvgeniy Ivanov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5358a2b000SEvgeniy Ivanov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5458a2b000SEvgeniy Ivanov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5558a2b000SEvgeniy Ivanov * SUCH DAMAGE. 5658a2b000SEvgeniy Ivanov * 5758a2b000SEvgeniy Ivanov * @(#)boot.c 8.1 (Berkeley) 6/10/93 5858a2b000SEvgeniy Ivanov */ 5958a2b000SEvgeniy Ivanov 6058a2b000SEvgeniy Ivanov /* 6158a2b000SEvgeniy Ivanov * Copyright (c) 1996 6258a2b000SEvgeniy Ivanov * Matthias Drochner. All rights reserved. 6358a2b000SEvgeniy Ivanov * Copyright (c) 1996 6458a2b000SEvgeniy Ivanov * Perry E. Metzger. All rights reserved. 6558a2b000SEvgeniy Ivanov * 6658a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without 6758a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions 6858a2b000SEvgeniy Ivanov * are met: 6958a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright 7058a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer. 7158a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright 7258a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the 7358a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution. 7458a2b000SEvgeniy Ivanov * 7558a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 7658a2b000SEvgeniy Ivanov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 7758a2b000SEvgeniy Ivanov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7858a2b000SEvgeniy Ivanov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 7958a2b000SEvgeniy Ivanov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 8058a2b000SEvgeniy Ivanov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 8158a2b000SEvgeniy Ivanov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 8258a2b000SEvgeniy Ivanov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 8358a2b000SEvgeniy Ivanov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 8458a2b000SEvgeniy Ivanov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 8558a2b000SEvgeniy Ivanov * SUCH DAMAGE. 8658a2b000SEvgeniy Ivanov * 8758a2b000SEvgeniy Ivanov * @(#)boot.c 8.1 (Berkeley) 6/10/93 8858a2b000SEvgeniy Ivanov */ 8958a2b000SEvgeniy Ivanov 9058a2b000SEvgeniy Ivanov /* 9158a2b000SEvgeniy Ivanov * starts NetBSD a.out kernel 9258a2b000SEvgeniy Ivanov * needs lowlevel startup from startprog.S 9358a2b000SEvgeniy Ivanov * This is a special version of exec.c to support use of XMS. 9458a2b000SEvgeniy Ivanov */ 9558a2b000SEvgeniy Ivanov 9658a2b000SEvgeniy Ivanov #include <sys/param.h> 9758a2b000SEvgeniy Ivanov #include <sys/reboot.h> 9858a2b000SEvgeniy Ivanov #include <sys/reboot.h> 9958a2b000SEvgeniy Ivanov 10058a2b000SEvgeniy Ivanov #include <machine/multiboot.h> 10158a2b000SEvgeniy Ivanov 10258a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h> 10358a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h> 10458a2b000SEvgeniy Ivanov 10558a2b000SEvgeniy Ivanov #include "loadfile.h" 10658a2b000SEvgeniy Ivanov #include "libi386.h" 10758a2b000SEvgeniy Ivanov #include "bootinfo.h" 10858a2b000SEvgeniy Ivanov #include "bootmod.h" 10958a2b000SEvgeniy Ivanov #include "vbe.h" 11058a2b000SEvgeniy Ivanov #ifdef SUPPORT_PS2 11158a2b000SEvgeniy Ivanov #include "biosmca.h" 11258a2b000SEvgeniy Ivanov #endif 11358a2b000SEvgeniy Ivanov 11458a2b000SEvgeniy Ivanov #define BOOT_NARGS 6 11558a2b000SEvgeniy Ivanov 11658a2b000SEvgeniy Ivanov #ifndef PAGE_SIZE 11758a2b000SEvgeniy Ivanov #define PAGE_SIZE 4096 11858a2b000SEvgeniy Ivanov #endif 11958a2b000SEvgeniy Ivanov 12058a2b000SEvgeniy Ivanov #define MODULE_WARNING_SEC 5 12158a2b000SEvgeniy Ivanov 12258a2b000SEvgeniy Ivanov extern struct btinfo_console btinfo_console; 12358a2b000SEvgeniy Ivanov 12458a2b000SEvgeniy Ivanov boot_module_t *boot_modules; 12558a2b000SEvgeniy Ivanov bool boot_modules_enabled = true; 12658a2b000SEvgeniy Ivanov bool kernel_loaded; 12758a2b000SEvgeniy Ivanov 12858a2b000SEvgeniy Ivanov typedef struct userconf_command { 12958a2b000SEvgeniy Ivanov char *uc_text; 13058a2b000SEvgeniy Ivanov size_t uc_len; 13158a2b000SEvgeniy Ivanov struct userconf_command *uc_next; 13258a2b000SEvgeniy Ivanov } userconf_command_t; 13358a2b000SEvgeniy Ivanov userconf_command_t *userconf_commands = NULL; 13458a2b000SEvgeniy Ivanov 13558a2b000SEvgeniy Ivanov static struct btinfo_framebuffer btinfo_framebuffer; 13658a2b000SEvgeniy Ivanov 13758a2b000SEvgeniy Ivanov static struct btinfo_modulelist *btinfo_modulelist; 13858a2b000SEvgeniy Ivanov static size_t btinfo_modulelist_size; 13958a2b000SEvgeniy Ivanov static uint32_t image_end; 14058a2b000SEvgeniy Ivanov static char module_base[64] = "/"; 14158a2b000SEvgeniy Ivanov static int howto; 14258a2b000SEvgeniy Ivanov 14358a2b000SEvgeniy Ivanov static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL; 14458a2b000SEvgeniy Ivanov static size_t btinfo_userconfcommands_size = 0; 14558a2b000SEvgeniy Ivanov 14658a2b000SEvgeniy Ivanov static void module_init(const char *); 14758a2b000SEvgeniy Ivanov static void module_add_common(char *, uint8_t); 14858a2b000SEvgeniy Ivanov 14958a2b000SEvgeniy Ivanov static void userconf_init(void); 15058a2b000SEvgeniy Ivanov 15158a2b000SEvgeniy Ivanov void 15258a2b000SEvgeniy Ivanov framebuffer_configure(struct btinfo_framebuffer *fb) 15358a2b000SEvgeniy Ivanov { 15458a2b000SEvgeniy Ivanov if (fb) 15558a2b000SEvgeniy Ivanov btinfo_framebuffer = *fb; 15658a2b000SEvgeniy Ivanov else { 15758a2b000SEvgeniy Ivanov btinfo_framebuffer.physaddr = 0; 15858a2b000SEvgeniy Ivanov btinfo_framebuffer.flags = 0; 15958a2b000SEvgeniy Ivanov } 16058a2b000SEvgeniy Ivanov } 16158a2b000SEvgeniy Ivanov 16258a2b000SEvgeniy Ivanov void 16358a2b000SEvgeniy Ivanov module_add(char *name) 16458a2b000SEvgeniy Ivanov { 16558a2b000SEvgeniy Ivanov return module_add_common(name, BM_TYPE_KMOD); 16658a2b000SEvgeniy Ivanov } 16758a2b000SEvgeniy Ivanov 16858a2b000SEvgeniy Ivanov void 16958a2b000SEvgeniy Ivanov splash_add(char *name) 17058a2b000SEvgeniy Ivanov { 17158a2b000SEvgeniy Ivanov return module_add_common(name, BM_TYPE_IMAGE); 17258a2b000SEvgeniy Ivanov } 17358a2b000SEvgeniy Ivanov 17458a2b000SEvgeniy Ivanov void 17558a2b000SEvgeniy Ivanov rnd_add(char *name) 17658a2b000SEvgeniy Ivanov { 17758a2b000SEvgeniy Ivanov return module_add_common(name, BM_TYPE_RND); 17858a2b000SEvgeniy Ivanov } 17958a2b000SEvgeniy Ivanov 18058a2b000SEvgeniy Ivanov static void 18158a2b000SEvgeniy Ivanov module_add_common(char *name, uint8_t type) 18258a2b000SEvgeniy Ivanov { 18358a2b000SEvgeniy Ivanov boot_module_t *bm, *bmp; 18458a2b000SEvgeniy Ivanov size_t len; 18558a2b000SEvgeniy Ivanov char *str; 18658a2b000SEvgeniy Ivanov 18758a2b000SEvgeniy Ivanov while (*name == ' ' || *name == '\t') 18858a2b000SEvgeniy Ivanov ++name; 18958a2b000SEvgeniy Ivanov 19058a2b000SEvgeniy Ivanov bm = alloc(sizeof(boot_module_t)); 19158a2b000SEvgeniy Ivanov len = strlen(name) + 1; 19258a2b000SEvgeniy Ivanov str = alloc(len); 19358a2b000SEvgeniy Ivanov if (bm == NULL || str == NULL) { 19458a2b000SEvgeniy Ivanov printf("couldn't allocate module\n"); 19558a2b000SEvgeniy Ivanov return; 19658a2b000SEvgeniy Ivanov } 19758a2b000SEvgeniy Ivanov memcpy(str, name, len); 19858a2b000SEvgeniy Ivanov bm->bm_path = str; 19958a2b000SEvgeniy Ivanov bm->bm_next = NULL; 20058a2b000SEvgeniy Ivanov bm->bm_type = type; 20158a2b000SEvgeniy Ivanov if (boot_modules == NULL) 20258a2b000SEvgeniy Ivanov boot_modules = bm; 20358a2b000SEvgeniy Ivanov else { 20458a2b000SEvgeniy Ivanov for (bmp = boot_modules; bmp->bm_next; 20558a2b000SEvgeniy Ivanov bmp = bmp->bm_next) 20658a2b000SEvgeniy Ivanov ; 20758a2b000SEvgeniy Ivanov bmp->bm_next = bm; 20858a2b000SEvgeniy Ivanov } 20958a2b000SEvgeniy Ivanov } 21058a2b000SEvgeniy Ivanov 21158a2b000SEvgeniy Ivanov void 21258a2b000SEvgeniy Ivanov userconf_add(char *cmd) 21358a2b000SEvgeniy Ivanov { 21458a2b000SEvgeniy Ivanov userconf_command_t *uc; 21558a2b000SEvgeniy Ivanov size_t len; 21658a2b000SEvgeniy Ivanov char *text; 21758a2b000SEvgeniy Ivanov 21858a2b000SEvgeniy Ivanov while (*cmd == ' ' || *cmd == '\t') 21958a2b000SEvgeniy Ivanov ++cmd; 22058a2b000SEvgeniy Ivanov 22158a2b000SEvgeniy Ivanov uc = alloc(sizeof(*uc)); 22258a2b000SEvgeniy Ivanov if (uc == NULL) { 22358a2b000SEvgeniy Ivanov printf("couldn't allocate command\n"); 22458a2b000SEvgeniy Ivanov return; 22558a2b000SEvgeniy Ivanov } 22658a2b000SEvgeniy Ivanov 22758a2b000SEvgeniy Ivanov len = strlen(cmd) + 1; 22858a2b000SEvgeniy Ivanov text = alloc(len); 22958a2b000SEvgeniy Ivanov if (text == NULL) { 23058a2b000SEvgeniy Ivanov dealloc(uc, sizeof(*uc)); 23158a2b000SEvgeniy Ivanov printf("couldn't allocate command\n"); 23258a2b000SEvgeniy Ivanov return; 23358a2b000SEvgeniy Ivanov } 23458a2b000SEvgeniy Ivanov memcpy(text, cmd, len); 23558a2b000SEvgeniy Ivanov 23658a2b000SEvgeniy Ivanov uc->uc_text = text; 23758a2b000SEvgeniy Ivanov uc->uc_len = len; 23858a2b000SEvgeniy Ivanov uc->uc_next = NULL; 23958a2b000SEvgeniy Ivanov 24058a2b000SEvgeniy Ivanov if (userconf_commands == NULL) 24158a2b000SEvgeniy Ivanov userconf_commands = uc; 24258a2b000SEvgeniy Ivanov else { 24358a2b000SEvgeniy Ivanov userconf_command_t *ucp; 24458a2b000SEvgeniy Ivanov for (ucp = userconf_commands; ucp->uc_next != NULL; 24558a2b000SEvgeniy Ivanov ucp = ucp->uc_next) 24658a2b000SEvgeniy Ivanov ; 24758a2b000SEvgeniy Ivanov ucp->uc_next = uc; 24858a2b000SEvgeniy Ivanov } 24958a2b000SEvgeniy Ivanov } 25058a2b000SEvgeniy Ivanov 25158a2b000SEvgeniy Ivanov static int 25258a2b000SEvgeniy Ivanov common_load_kernel(const char *file, u_long *basemem, u_long *extmem, 25358a2b000SEvgeniy Ivanov physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX]) 25458a2b000SEvgeniy Ivanov { 25558a2b000SEvgeniy Ivanov int fd; 25658a2b000SEvgeniy Ivanov #ifdef XMS 25758a2b000SEvgeniy Ivanov u_long xmsmem; 25858a2b000SEvgeniy Ivanov physaddr_t origaddr = loadaddr; 25958a2b000SEvgeniy Ivanov #endif 26058a2b000SEvgeniy Ivanov 26158a2b000SEvgeniy Ivanov *extmem = getextmem(); 26258a2b000SEvgeniy Ivanov *basemem = getbasemem(); 26358a2b000SEvgeniy Ivanov 26458a2b000SEvgeniy Ivanov #ifdef XMS 26558a2b000SEvgeniy Ivanov if ((getextmem1() == 0) && (xmsmem = checkxms())) { 26658a2b000SEvgeniy Ivanov u_long kernsize; 26758a2b000SEvgeniy Ivanov 26858a2b000SEvgeniy Ivanov /* 26958a2b000SEvgeniy Ivanov * With "CONSERVATIVE_MEMDETECT", extmem is 0 because 27058a2b000SEvgeniy Ivanov * getextmem() is getextmem1(). Without, the "smart" 27158a2b000SEvgeniy Ivanov * methods could fail to report all memory as well. 27258a2b000SEvgeniy Ivanov * xmsmem is a few kB less than the actual size, but 27358a2b000SEvgeniy Ivanov * better than nothing. 27458a2b000SEvgeniy Ivanov */ 27558a2b000SEvgeniy Ivanov if (xmsmem > *extmem) 27658a2b000SEvgeniy Ivanov *extmem = xmsmem; 27758a2b000SEvgeniy Ivanov /* 27858a2b000SEvgeniy Ivanov * Get the size of the kernel 27958a2b000SEvgeniy Ivanov */ 28058a2b000SEvgeniy Ivanov marks[MARK_START] = loadaddr; 28158a2b000SEvgeniy Ivanov if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1) 28258a2b000SEvgeniy Ivanov return EIO; 28358a2b000SEvgeniy Ivanov close(fd); 28458a2b000SEvgeniy Ivanov 28558a2b000SEvgeniy Ivanov kernsize = marks[MARK_END]; 28658a2b000SEvgeniy Ivanov kernsize = (kernsize + 1023) / 1024; 28758a2b000SEvgeniy Ivanov 28858a2b000SEvgeniy Ivanov loadaddr = xmsalloc(kernsize); 28958a2b000SEvgeniy Ivanov if (!loadaddr) 29058a2b000SEvgeniy Ivanov return ENOMEM; 29158a2b000SEvgeniy Ivanov } 29258a2b000SEvgeniy Ivanov #endif 29358a2b000SEvgeniy Ivanov marks[MARK_START] = loadaddr; 29458a2b000SEvgeniy Ivanov if ((fd = loadfile(file, marks, 29558a2b000SEvgeniy Ivanov LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1) 29658a2b000SEvgeniy Ivanov return EIO; 29758a2b000SEvgeniy Ivanov 29858a2b000SEvgeniy Ivanov close(fd); 29958a2b000SEvgeniy Ivanov 300*f14fb602SLionel Sambuc /* If the root fs type is unusual, load its module. */ 301adb5107eSAntoine Leca if (fsmod != NULL) 30258a2b000SEvgeniy Ivanov module_add(fsmod); 303*f14fb602SLionel Sambuc #if defined(__minix) 304adb5107eSAntoine Leca if (fsmod !=NULL && fsmod2 != NULL && strcmp(fsmod, fsmod2) != 0) 30558a2b000SEvgeniy Ivanov module_add(fsmod2); 306*f14fb602SLionel Sambuc #endif /* defined(__minix) */ 30758a2b000SEvgeniy Ivanov 30858a2b000SEvgeniy Ivanov /* 30958a2b000SEvgeniy Ivanov * Gather some information for the kernel. Do this after the 31058a2b000SEvgeniy Ivanov * "point of no return" to avoid memory leaks. 31158a2b000SEvgeniy Ivanov * (but before DOS might be trashed in the XMS case) 31258a2b000SEvgeniy Ivanov */ 31358a2b000SEvgeniy Ivanov #ifdef PASS_BIOSGEOM 31458a2b000SEvgeniy Ivanov bi_getbiosgeom(); 31558a2b000SEvgeniy Ivanov #endif 31658a2b000SEvgeniy Ivanov #ifdef PASS_MEMMAP 31758a2b000SEvgeniy Ivanov bi_getmemmap(); 31858a2b000SEvgeniy Ivanov #endif 31958a2b000SEvgeniy Ivanov 32058a2b000SEvgeniy Ivanov #ifdef XMS 32158a2b000SEvgeniy Ivanov if (loadaddr != origaddr) { 32258a2b000SEvgeniy Ivanov /* 32358a2b000SEvgeniy Ivanov * We now have done our last DOS IO, so we may 32458a2b000SEvgeniy Ivanov * trash the OS. Copy the data from the temporary 32558a2b000SEvgeniy Ivanov * buffer to its real address. 32658a2b000SEvgeniy Ivanov */ 32758a2b000SEvgeniy Ivanov marks[MARK_START] -= loadaddr; 32858a2b000SEvgeniy Ivanov marks[MARK_END] -= loadaddr; 32958a2b000SEvgeniy Ivanov marks[MARK_SYM] -= loadaddr; 33058a2b000SEvgeniy Ivanov marks[MARK_END] -= loadaddr; 33158a2b000SEvgeniy Ivanov ppbcopy(loadaddr, origaddr, marks[MARK_END]); 33258a2b000SEvgeniy Ivanov } 33358a2b000SEvgeniy Ivanov #endif 33458a2b000SEvgeniy Ivanov marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) & 33558a2b000SEvgeniy Ivanov (-sizeof(int)); 33658a2b000SEvgeniy Ivanov image_end = marks[MARK_END]; 33758a2b000SEvgeniy Ivanov kernel_loaded = true; 33858a2b000SEvgeniy Ivanov 33958a2b000SEvgeniy Ivanov return 0; 34058a2b000SEvgeniy Ivanov } 34158a2b000SEvgeniy Ivanov 34258a2b000SEvgeniy Ivanov int 34358a2b000SEvgeniy Ivanov exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy, 34458a2b000SEvgeniy Ivanov void (*callback)(void)) 34558a2b000SEvgeniy Ivanov { 34658a2b000SEvgeniy Ivanov u_long boot_argv[BOOT_NARGS]; 34758a2b000SEvgeniy Ivanov u_long marks[MARK_MAX]; 34858a2b000SEvgeniy Ivanov struct btinfo_symtab btinfo_symtab; 34958a2b000SEvgeniy Ivanov u_long extmem; 35058a2b000SEvgeniy Ivanov u_long basemem; 35158a2b000SEvgeniy Ivanov 35258a2b000SEvgeniy Ivanov #ifdef DEBUG 35358a2b000SEvgeniy Ivanov printf("exec: file=%s loadaddr=0x%lx\n", 35458a2b000SEvgeniy Ivanov file ? file : "NULL", loadaddr); 35558a2b000SEvgeniy Ivanov #endif 35658a2b000SEvgeniy Ivanov 35758a2b000SEvgeniy Ivanov BI_ALLOC(32); /* ??? */ 35858a2b000SEvgeniy Ivanov 35958a2b000SEvgeniy Ivanov BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console)); 36058a2b000SEvgeniy Ivanov 36158a2b000SEvgeniy Ivanov howto = boothowto; 36258a2b000SEvgeniy Ivanov 36358a2b000SEvgeniy Ivanov if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks)) 36458a2b000SEvgeniy Ivanov goto out; 36558a2b000SEvgeniy Ivanov 36658a2b000SEvgeniy Ivanov boot_argv[0] = boothowto; 36758a2b000SEvgeniy Ivanov boot_argv[1] = 0; 36858a2b000SEvgeniy Ivanov boot_argv[2] = vtophys(bootinfo); /* old cyl offset */ 36958a2b000SEvgeniy Ivanov boot_argv[3] = marks[MARK_END]; 37058a2b000SEvgeniy Ivanov boot_argv[4] = extmem; 37158a2b000SEvgeniy Ivanov boot_argv[5] = basemem; 37258a2b000SEvgeniy Ivanov 37358a2b000SEvgeniy Ivanov /* pull in any modules if necessary */ 37458a2b000SEvgeniy Ivanov if (boot_modules_enabled) { 37558a2b000SEvgeniy Ivanov module_init(file); 37658a2b000SEvgeniy Ivanov if (btinfo_modulelist) { 37758a2b000SEvgeniy Ivanov BI_ADD(btinfo_modulelist, BTINFO_MODULELIST, 37858a2b000SEvgeniy Ivanov btinfo_modulelist_size); 37958a2b000SEvgeniy Ivanov } 38058a2b000SEvgeniy Ivanov } 38158a2b000SEvgeniy Ivanov 38258a2b000SEvgeniy Ivanov userconf_init(); 38358a2b000SEvgeniy Ivanov if (btinfo_userconfcommands != NULL) 38458a2b000SEvgeniy Ivanov BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS, 38558a2b000SEvgeniy Ivanov btinfo_userconfcommands_size); 38658a2b000SEvgeniy Ivanov 38758a2b000SEvgeniy Ivanov #ifdef DEBUG 38858a2b000SEvgeniy Ivanov printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], 38958a2b000SEvgeniy Ivanov marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); 39058a2b000SEvgeniy Ivanov #endif 39158a2b000SEvgeniy Ivanov 39258a2b000SEvgeniy Ivanov btinfo_symtab.nsym = marks[MARK_NSYM]; 39358a2b000SEvgeniy Ivanov btinfo_symtab.ssym = marks[MARK_SYM]; 39458a2b000SEvgeniy Ivanov btinfo_symtab.esym = marks[MARK_END]; 39558a2b000SEvgeniy Ivanov BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab)); 39658a2b000SEvgeniy Ivanov 39758a2b000SEvgeniy Ivanov /* set new video mode if necessary */ 39858a2b000SEvgeniy Ivanov vbe_commit(); 39958a2b000SEvgeniy Ivanov BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER, 40058a2b000SEvgeniy Ivanov sizeof(struct btinfo_framebuffer)); 40158a2b000SEvgeniy Ivanov 40258a2b000SEvgeniy Ivanov if (callback != NULL) 40358a2b000SEvgeniy Ivanov (*callback)(); 40458a2b000SEvgeniy Ivanov startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv, 40558a2b000SEvgeniy Ivanov x86_trunc_page(basemem*1024)); 40658a2b000SEvgeniy Ivanov panic("exec returned"); 40758a2b000SEvgeniy Ivanov 40858a2b000SEvgeniy Ivanov out: 40958a2b000SEvgeniy Ivanov BI_FREE(); 41058a2b000SEvgeniy Ivanov bootinfo = 0; 41158a2b000SEvgeniy Ivanov return -1; 41258a2b000SEvgeniy Ivanov } 41358a2b000SEvgeniy Ivanov 41458a2b000SEvgeniy Ivanov static void 41558a2b000SEvgeniy Ivanov extract_device(const char *path, char *buf, size_t buflen) 41658a2b000SEvgeniy Ivanov { 41758a2b000SEvgeniy Ivanov int i; 41858a2b000SEvgeniy Ivanov 41958a2b000SEvgeniy Ivanov if (strchr(path, ':') != NULL) { 42058a2b000SEvgeniy Ivanov for (i = 0; i < buflen - 2 && path[i] != ':'; i++) 42158a2b000SEvgeniy Ivanov buf[i] = path[i]; 42258a2b000SEvgeniy Ivanov buf[i++] = ':'; 42358a2b000SEvgeniy Ivanov buf[i] = '\0'; 42458a2b000SEvgeniy Ivanov } else 42558a2b000SEvgeniy Ivanov buf[0] = '\0'; 42658a2b000SEvgeniy Ivanov } 42758a2b000SEvgeniy Ivanov 42858a2b000SEvgeniy Ivanov static const char * 42958a2b000SEvgeniy Ivanov module_path(boot_module_t *bm, const char *kdev) 43058a2b000SEvgeniy Ivanov { 43158a2b000SEvgeniy Ivanov static char buf[256]; 43258a2b000SEvgeniy Ivanov char name_buf[256], dev_buf[64]; 43358a2b000SEvgeniy Ivanov const char *name, *name2, *p; 43458a2b000SEvgeniy Ivanov 43558a2b000SEvgeniy Ivanov name = bm->bm_path; 43658a2b000SEvgeniy Ivanov for (name2 = name; *name2; ++name2) { 43758a2b000SEvgeniy Ivanov if (*name2 == ' ' || *name2 == '\t') { 43858a2b000SEvgeniy Ivanov strlcpy(name_buf, name, sizeof(name_buf)); 43958a2b000SEvgeniy Ivanov if (name2 - name < sizeof(name_buf)) 44058a2b000SEvgeniy Ivanov name_buf[name2 - name] = '\0'; 44158a2b000SEvgeniy Ivanov name = name_buf; 44258a2b000SEvgeniy Ivanov break; 44358a2b000SEvgeniy Ivanov } 44458a2b000SEvgeniy Ivanov } 44558a2b000SEvgeniy Ivanov if ((p = strchr(name, ':')) != NULL) { 44658a2b000SEvgeniy Ivanov /* device specified, use it */ 44758a2b000SEvgeniy Ivanov if (p[1] == '/') 44858a2b000SEvgeniy Ivanov snprintf(buf, sizeof(buf), "%s", name); 44958a2b000SEvgeniy Ivanov else { 45058a2b000SEvgeniy Ivanov p++; 45158a2b000SEvgeniy Ivanov extract_device(name, dev_buf, sizeof(dev_buf)); 45258a2b000SEvgeniy Ivanov snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", 45358a2b000SEvgeniy Ivanov dev_buf, module_base, p, p); 45458a2b000SEvgeniy Ivanov } 45558a2b000SEvgeniy Ivanov } else { 45658a2b000SEvgeniy Ivanov /* device not specified; load from kernel device if known */ 45758a2b000SEvgeniy Ivanov if (name[0] == '/') 45858a2b000SEvgeniy Ivanov snprintf(buf, sizeof(buf), "%s%s", kdev, name); 45958a2b000SEvgeniy Ivanov else 46058a2b000SEvgeniy Ivanov snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", 46158a2b000SEvgeniy Ivanov kdev, module_base, name, name); 46258a2b000SEvgeniy Ivanov } 46358a2b000SEvgeniy Ivanov 46458a2b000SEvgeniy Ivanov return buf; 46558a2b000SEvgeniy Ivanov } 46658a2b000SEvgeniy Ivanov 46758a2b000SEvgeniy Ivanov static int 46858a2b000SEvgeniy Ivanov module_open(boot_module_t *bm, int mode, const char *kdev, bool doload) 46958a2b000SEvgeniy Ivanov { 47058a2b000SEvgeniy Ivanov int fd; 47158a2b000SEvgeniy Ivanov const char *path; 47258a2b000SEvgeniy Ivanov 47358a2b000SEvgeniy Ivanov /* check the expanded path first */ 47458a2b000SEvgeniy Ivanov path = module_path(bm, kdev); 47558a2b000SEvgeniy Ivanov fd = open(path, mode); 47658a2b000SEvgeniy Ivanov if (fd != -1) { 47758a2b000SEvgeniy Ivanov if ((howto & AB_SILENT) == 0 && doload) 47858a2b000SEvgeniy Ivanov printf("Loading %s ", path); 47958a2b000SEvgeniy Ivanov } else { 48058a2b000SEvgeniy Ivanov /* now attempt the raw path provided */ 48158a2b000SEvgeniy Ivanov fd = open(bm->bm_path, mode); 48258a2b000SEvgeniy Ivanov if (fd != -1 && (howto & AB_SILENT) == 0 && doload) 48358a2b000SEvgeniy Ivanov printf("Loading %s ", bm->bm_path); 48458a2b000SEvgeniy Ivanov } 48558a2b000SEvgeniy Ivanov if (!doload && fd == -1) { 48658a2b000SEvgeniy Ivanov printf("WARNING: couldn't open %s", bm->bm_path); 48758a2b000SEvgeniy Ivanov if (strcmp(bm->bm_path, path) != 0) 48858a2b000SEvgeniy Ivanov printf(" (%s)", path); 48958a2b000SEvgeniy Ivanov printf("\n"); 49058a2b000SEvgeniy Ivanov } 49158a2b000SEvgeniy Ivanov return fd; 49258a2b000SEvgeniy Ivanov } 49358a2b000SEvgeniy Ivanov 49458a2b000SEvgeniy Ivanov static void 49558a2b000SEvgeniy Ivanov module_init(const char *kernel_path) 49658a2b000SEvgeniy Ivanov { 49758a2b000SEvgeniy Ivanov struct bi_modulelist_entry *bi; 49858a2b000SEvgeniy Ivanov struct stat st; 49958a2b000SEvgeniy Ivanov const char *machine; 50058a2b000SEvgeniy Ivanov char kdev[64]; 50158a2b000SEvgeniy Ivanov char *buf; 50258a2b000SEvgeniy Ivanov boot_module_t *bm; 50358a2b000SEvgeniy Ivanov size_t len; 50458a2b000SEvgeniy Ivanov off_t off; 50558a2b000SEvgeniy Ivanov int err, fd, nfail = 0; 50658a2b000SEvgeniy Ivanov 50758a2b000SEvgeniy Ivanov extract_device(kernel_path, kdev, sizeof(kdev)); 50858a2b000SEvgeniy Ivanov 50958a2b000SEvgeniy Ivanov switch (netbsd_elf_class) { 51058a2b000SEvgeniy Ivanov case ELFCLASS32: 51158a2b000SEvgeniy Ivanov machine = "i386"; 51258a2b000SEvgeniy Ivanov break; 51358a2b000SEvgeniy Ivanov case ELFCLASS64: 51458a2b000SEvgeniy Ivanov machine = "amd64"; 51558a2b000SEvgeniy Ivanov break; 51658a2b000SEvgeniy Ivanov default: 51758a2b000SEvgeniy Ivanov machine = "generic"; 51858a2b000SEvgeniy Ivanov break; 51958a2b000SEvgeniy Ivanov } 52058a2b000SEvgeniy Ivanov if (netbsd_version / 1000000 % 100 == 99) { 52158a2b000SEvgeniy Ivanov /* -current */ 52258a2b000SEvgeniy Ivanov snprintf(module_base, sizeof(module_base), 52358a2b000SEvgeniy Ivanov "/stand/%s/%d.%d.%d/modules", machine, 52458a2b000SEvgeniy Ivanov netbsd_version / 100000000, 52558a2b000SEvgeniy Ivanov netbsd_version / 1000000 % 100, 52658a2b000SEvgeniy Ivanov netbsd_version / 100 % 100); 52758a2b000SEvgeniy Ivanov } else if (netbsd_version != 0) { 52858a2b000SEvgeniy Ivanov /* release */ 52958a2b000SEvgeniy Ivanov snprintf(module_base, sizeof(module_base), 53058a2b000SEvgeniy Ivanov "/stand/%s/%d.%d/modules", machine, 53158a2b000SEvgeniy Ivanov netbsd_version / 100000000, 53258a2b000SEvgeniy Ivanov netbsd_version / 1000000 % 100); 53358a2b000SEvgeniy Ivanov } 53458a2b000SEvgeniy Ivanov 53558a2b000SEvgeniy Ivanov /* First, see which modules are valid and calculate btinfo size */ 53658a2b000SEvgeniy Ivanov len = sizeof(struct btinfo_modulelist); 53758a2b000SEvgeniy Ivanov for (bm = boot_modules; bm; bm = bm->bm_next) { 53858a2b000SEvgeniy Ivanov fd = module_open(bm, 0, kdev, false); 53958a2b000SEvgeniy Ivanov if (fd == -1) { 54058a2b000SEvgeniy Ivanov bm->bm_len = -1; 54158a2b000SEvgeniy Ivanov ++nfail; 54258a2b000SEvgeniy Ivanov continue; 54358a2b000SEvgeniy Ivanov } 54458a2b000SEvgeniy Ivanov err = fstat(fd, &st); 54558a2b000SEvgeniy Ivanov if (err == -1 || st.st_size == -1) { 54658a2b000SEvgeniy Ivanov printf("WARNING: couldn't stat %s\n", bm->bm_path); 54758a2b000SEvgeniy Ivanov close(fd); 54858a2b000SEvgeniy Ivanov bm->bm_len = -1; 54958a2b000SEvgeniy Ivanov ++nfail; 55058a2b000SEvgeniy Ivanov continue; 55158a2b000SEvgeniy Ivanov } 55258a2b000SEvgeniy Ivanov bm->bm_len = st.st_size; 55358a2b000SEvgeniy Ivanov close(fd); 55458a2b000SEvgeniy Ivanov len += sizeof(struct bi_modulelist_entry); 55558a2b000SEvgeniy Ivanov } 55658a2b000SEvgeniy Ivanov 55758a2b000SEvgeniy Ivanov /* Allocate the module list */ 55858a2b000SEvgeniy Ivanov btinfo_modulelist = alloc(len); 55958a2b000SEvgeniy Ivanov if (btinfo_modulelist == NULL) { 56058a2b000SEvgeniy Ivanov printf("WARNING: couldn't allocate module list\n"); 56158a2b000SEvgeniy Ivanov wait_sec(MODULE_WARNING_SEC); 56258a2b000SEvgeniy Ivanov return; 56358a2b000SEvgeniy Ivanov } 56458a2b000SEvgeniy Ivanov memset(btinfo_modulelist, 0, len); 56558a2b000SEvgeniy Ivanov btinfo_modulelist_size = len; 56658a2b000SEvgeniy Ivanov 56758a2b000SEvgeniy Ivanov /* Fill in btinfo structure */ 56858a2b000SEvgeniy Ivanov buf = (char *)btinfo_modulelist; 56958a2b000SEvgeniy Ivanov btinfo_modulelist->num = 0; 57058a2b000SEvgeniy Ivanov off = sizeof(struct btinfo_modulelist); 57158a2b000SEvgeniy Ivanov 57258a2b000SEvgeniy Ivanov for (bm = boot_modules; bm; bm = bm->bm_next) { 57358a2b000SEvgeniy Ivanov if (bm->bm_len == -1) 57458a2b000SEvgeniy Ivanov continue; 57558a2b000SEvgeniy Ivanov fd = module_open(bm, 0, kdev, true); 57658a2b000SEvgeniy Ivanov if (fd == -1) 57758a2b000SEvgeniy Ivanov continue; 57858a2b000SEvgeniy Ivanov image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 57958a2b000SEvgeniy Ivanov len = pread(fd, (void *)image_end, SSIZE_MAX); 58058a2b000SEvgeniy Ivanov if (len < bm->bm_len) { 58158a2b000SEvgeniy Ivanov if ((howto & AB_SILENT) != 0) 58258a2b000SEvgeniy Ivanov printf("Loading %s ", bm->bm_path); 58358a2b000SEvgeniy Ivanov printf(" FAILED\n"); 58458a2b000SEvgeniy Ivanov } else { 58558a2b000SEvgeniy Ivanov btinfo_modulelist->num++; 58658a2b000SEvgeniy Ivanov bi = (struct bi_modulelist_entry *)(buf + off); 58758a2b000SEvgeniy Ivanov off += sizeof(struct bi_modulelist_entry); 58858a2b000SEvgeniy Ivanov strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1); 58958a2b000SEvgeniy Ivanov bi->base = image_end; 59058a2b000SEvgeniy Ivanov bi->len = len; 59158a2b000SEvgeniy Ivanov switch (bm->bm_type) { 59258a2b000SEvgeniy Ivanov case BM_TYPE_KMOD: 59358a2b000SEvgeniy Ivanov bi->type = BI_MODULE_ELF; 59458a2b000SEvgeniy Ivanov break; 59558a2b000SEvgeniy Ivanov case BM_TYPE_IMAGE: 59658a2b000SEvgeniy Ivanov bi->type = BI_MODULE_IMAGE; 59758a2b000SEvgeniy Ivanov break; 59858a2b000SEvgeniy Ivanov case BM_TYPE_RND: 59958a2b000SEvgeniy Ivanov default: 60058a2b000SEvgeniy Ivanov /* safest -- rnd checks the sha1 */ 60158a2b000SEvgeniy Ivanov bi->type = BI_MODULE_RND; 60258a2b000SEvgeniy Ivanov break; 60358a2b000SEvgeniy Ivanov } 60458a2b000SEvgeniy Ivanov if ((howto & AB_SILENT) == 0) 60558a2b000SEvgeniy Ivanov printf(" \n"); 60658a2b000SEvgeniy Ivanov } 60758a2b000SEvgeniy Ivanov if (len > 0) 60858a2b000SEvgeniy Ivanov image_end += len; 60958a2b000SEvgeniy Ivanov close(fd); 61058a2b000SEvgeniy Ivanov } 61158a2b000SEvgeniy Ivanov btinfo_modulelist->endpa = image_end; 61258a2b000SEvgeniy Ivanov 61358a2b000SEvgeniy Ivanov if (nfail > 0) { 61458a2b000SEvgeniy Ivanov printf("WARNING: %d module%s failed to load\n", 61558a2b000SEvgeniy Ivanov nfail, nfail == 1 ? "" : "s"); 61658a2b000SEvgeniy Ivanov #if notyet 61758a2b000SEvgeniy Ivanov wait_sec(MODULE_WARNING_SEC); 61858a2b000SEvgeniy Ivanov #endif 61958a2b000SEvgeniy Ivanov } 62058a2b000SEvgeniy Ivanov } 62158a2b000SEvgeniy Ivanov 62258a2b000SEvgeniy Ivanov static void 62358a2b000SEvgeniy Ivanov userconf_init(void) 62458a2b000SEvgeniy Ivanov { 62558a2b000SEvgeniy Ivanov size_t count, len; 62658a2b000SEvgeniy Ivanov userconf_command_t *uc; 62758a2b000SEvgeniy Ivanov char *buf; 62858a2b000SEvgeniy Ivanov off_t off; 62958a2b000SEvgeniy Ivanov 63058a2b000SEvgeniy Ivanov /* Calculate the userconf commands list size */ 63158a2b000SEvgeniy Ivanov count = 0; 63258a2b000SEvgeniy Ivanov for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) 63358a2b000SEvgeniy Ivanov count++; 63458a2b000SEvgeniy Ivanov len = sizeof(btinfo_userconfcommands) + 63558a2b000SEvgeniy Ivanov count * sizeof(struct bi_userconfcommand); 63658a2b000SEvgeniy Ivanov 63758a2b000SEvgeniy Ivanov /* Allocate the userconf commands list */ 63858a2b000SEvgeniy Ivanov btinfo_userconfcommands = alloc(len); 63958a2b000SEvgeniy Ivanov if (btinfo_userconfcommands == NULL) { 64058a2b000SEvgeniy Ivanov printf("WARNING: couldn't allocate userconf commands list\n"); 64158a2b000SEvgeniy Ivanov return; 64258a2b000SEvgeniy Ivanov } 64358a2b000SEvgeniy Ivanov memset(btinfo_userconfcommands, 0, len); 64458a2b000SEvgeniy Ivanov btinfo_userconfcommands_size = len; 64558a2b000SEvgeniy Ivanov 64658a2b000SEvgeniy Ivanov /* Fill in btinfo structure */ 64758a2b000SEvgeniy Ivanov buf = (char *)btinfo_userconfcommands; 64858a2b000SEvgeniy Ivanov off = sizeof(*btinfo_userconfcommands); 64958a2b000SEvgeniy Ivanov btinfo_userconfcommands->num = 0; 65058a2b000SEvgeniy Ivanov for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) { 65158a2b000SEvgeniy Ivanov struct bi_userconfcommand *bi; 65258a2b000SEvgeniy Ivanov bi = (struct bi_userconfcommand *)(buf + off); 65358a2b000SEvgeniy Ivanov strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1); 65458a2b000SEvgeniy Ivanov 65558a2b000SEvgeniy Ivanov off += sizeof(*bi); 65658a2b000SEvgeniy Ivanov btinfo_userconfcommands->num++; 65758a2b000SEvgeniy Ivanov } 65858a2b000SEvgeniy Ivanov } 65958a2b000SEvgeniy Ivanov 66058a2b000SEvgeniy Ivanov int 66158a2b000SEvgeniy Ivanov exec_multiboot(const char *file, char *args) 66258a2b000SEvgeniy Ivanov { 66358a2b000SEvgeniy Ivanov struct multiboot_info *mbi; 66458a2b000SEvgeniy Ivanov struct multiboot_module *mbm; 66558a2b000SEvgeniy Ivanov struct bi_modulelist_entry *bim; 66658a2b000SEvgeniy Ivanov int i, len; 66758a2b000SEvgeniy Ivanov u_long marks[MARK_MAX]; 66858a2b000SEvgeniy Ivanov u_long extmem; 66958a2b000SEvgeniy Ivanov u_long basemem; 67058a2b000SEvgeniy Ivanov char *cmdline; 67158a2b000SEvgeniy Ivanov 67258a2b000SEvgeniy Ivanov mbi = alloc(sizeof(struct multiboot_info)); 67358a2b000SEvgeniy Ivanov mbi->mi_flags = MULTIBOOT_INFO_HAS_MEMORY; 67458a2b000SEvgeniy Ivanov 67558a2b000SEvgeniy Ivanov if (common_load_kernel(file, &basemem, &extmem, 0, 0, marks)) 67658a2b000SEvgeniy Ivanov goto out; 67758a2b000SEvgeniy Ivanov 67858a2b000SEvgeniy Ivanov mbi->mi_mem_upper = extmem; 67958a2b000SEvgeniy Ivanov mbi->mi_mem_lower = basemem; 68058a2b000SEvgeniy Ivanov 68158a2b000SEvgeniy Ivanov if (args) { 68258a2b000SEvgeniy Ivanov mbi->mi_flags |= MULTIBOOT_INFO_HAS_CMDLINE; 68358a2b000SEvgeniy Ivanov len = strlen(file) + 1 + strlen(args) + 1; 68458a2b000SEvgeniy Ivanov cmdline = alloc(len); 68558a2b000SEvgeniy Ivanov snprintf(cmdline, len, "%s %s", file, args); 68658a2b000SEvgeniy Ivanov mbi->mi_cmdline = (char *) vtophys(cmdline); 68758a2b000SEvgeniy Ivanov } 68858a2b000SEvgeniy Ivanov 68958a2b000SEvgeniy Ivanov /* pull in any modules if necessary */ 69058a2b000SEvgeniy Ivanov if (boot_modules_enabled) { 69158a2b000SEvgeniy Ivanov module_init(file); 69258a2b000SEvgeniy Ivanov if (btinfo_modulelist) { 69358a2b000SEvgeniy Ivanov mbm = alloc(sizeof(struct multiboot_module) * 69458a2b000SEvgeniy Ivanov btinfo_modulelist->num); 69558a2b000SEvgeniy Ivanov 69658a2b000SEvgeniy Ivanov bim = (struct bi_modulelist_entry *) 69758a2b000SEvgeniy Ivanov (((char *) btinfo_modulelist) + 69858a2b000SEvgeniy Ivanov sizeof(struct btinfo_modulelist)); 69958a2b000SEvgeniy Ivanov for (i = 0; i < btinfo_modulelist->num; i++) { 70058a2b000SEvgeniy Ivanov mbm[i].mmo_start = bim->base; 70158a2b000SEvgeniy Ivanov mbm[i].mmo_end = bim->base + bim->len; 70258a2b000SEvgeniy Ivanov mbm[i].mmo_string = (char *)vtophys(bim->path); 70358a2b000SEvgeniy Ivanov mbm[i].mmo_reserved = 0; 70458a2b000SEvgeniy Ivanov bim++; 70558a2b000SEvgeniy Ivanov } 70658a2b000SEvgeniy Ivanov mbi->mi_flags |= MULTIBOOT_INFO_HAS_MODS; 70758a2b000SEvgeniy Ivanov mbi->mi_mods_count = btinfo_modulelist->num; 70858a2b000SEvgeniy Ivanov mbi->mi_mods_addr = vtophys(mbm); 70958a2b000SEvgeniy Ivanov } 71058a2b000SEvgeniy Ivanov } 71158a2b000SEvgeniy Ivanov 71258a2b000SEvgeniy Ivanov #ifdef DEBUG 71358a2b000SEvgeniy Ivanov printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], 71458a2b000SEvgeniy Ivanov marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); 71558a2b000SEvgeniy Ivanov #endif 71658a2b000SEvgeniy Ivanov 71758a2b000SEvgeniy Ivanov 71858a2b000SEvgeniy Ivanov #if 0 71958a2b000SEvgeniy Ivanov if (btinfo_symtab.nsym) { 72058a2b000SEvgeniy Ivanov mbi->mi_flags |= MULTIBOOT_INFO_HAS_ELF_SYMS; 72158a2b000SEvgeniy Ivanov mbi->mi_elfshdr_addr = marks[MARK_SYM]; 72258a2b000SEvgeniy Ivanov btinfo_symtab.nsym = marks[MARK_NSYM]; 72358a2b000SEvgeniy Ivanov btinfo_symtab.ssym = marks[MARK_SYM]; 72458a2b000SEvgeniy Ivanov btinfo_symtab.esym = marks[MARK_END]; 72558a2b000SEvgeniy Ivanov #endif 72658a2b000SEvgeniy Ivanov 72758a2b000SEvgeniy Ivanov multiboot(marks[MARK_ENTRY], vtophys(mbi), 72858a2b000SEvgeniy Ivanov x86_trunc_page(mbi->mi_mem_lower*1024)); 72958a2b000SEvgeniy Ivanov panic("exec returned"); 73058a2b000SEvgeniy Ivanov 73158a2b000SEvgeniy Ivanov out: 73258a2b000SEvgeniy Ivanov dealloc(mbi, 0); 73358a2b000SEvgeniy Ivanov return -1; 73458a2b000SEvgeniy Ivanov } 73558a2b000SEvgeniy Ivanov 73658a2b000SEvgeniy Ivanov void 73758a2b000SEvgeniy Ivanov x86_progress(const char *fmt, ...) 73858a2b000SEvgeniy Ivanov { 73958a2b000SEvgeniy Ivanov va_list ap; 74058a2b000SEvgeniy Ivanov 74158a2b000SEvgeniy Ivanov if ((howto & AB_SILENT) != 0) 74258a2b000SEvgeniy Ivanov return; 74358a2b000SEvgeniy Ivanov va_start(ap, fmt); 74458a2b000SEvgeniy Ivanov vprintf(fmt, ap); 74558a2b000SEvgeniy Ivanov va_end(ap); 74658a2b000SEvgeniy Ivanov } 747