Home | History | Annotate | Line # | Download | only in lib
exec.c revision 1.76.10.1
      1  1.76.10.1      cjep /*	$NetBSD: exec.c,v 1.76.10.1 2021/05/31 22:15:13 cjep Exp $	 */
      2       1.23        ad 
      3       1.62      maxv /*
      4       1.40        ad  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
      5       1.23        ad  * All rights reserved.
      6       1.23        ad  *
      7       1.23        ad  * Redistribution and use in source and binary forms, with or without
      8       1.23        ad  * modification, are permitted provided that the following conditions
      9       1.23        ad  * are met:
     10       1.23        ad  * 1. Redistributions of source code must retain the above copyright
     11       1.23        ad  *    notice, this list of conditions and the following disclaimer.
     12       1.23        ad  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.23        ad  *    notice, this list of conditions and the following disclaimer in the
     14       1.23        ad  *    documentation and/or other materials provided with the distribution.
     15       1.23        ad  *
     16       1.23        ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17       1.23        ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18       1.23        ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19       1.23        ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20       1.23        ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21       1.23        ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22       1.23        ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23       1.23        ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24       1.23        ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25       1.23        ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26       1.23        ad  * POSSIBILITY OF SUCH DAMAGE.
     27       1.23        ad  */
     28        1.1     perry 
     29        1.1     perry /*
     30        1.1     perry  * Copyright (c) 1982, 1986, 1990, 1993
     31        1.1     perry  *	The Regents of the University of California.  All rights reserved.
     32       1.19       agc  *
     33       1.19       agc  * Redistribution and use in source and binary forms, with or without
     34       1.19       agc  * modification, are permitted provided that the following conditions
     35       1.19       agc  * are met:
     36       1.19       agc  * 1. Redistributions of source code must retain the above copyright
     37       1.19       agc  *    notice, this list of conditions and the following disclaimer.
     38       1.19       agc  * 2. Redistributions in binary form must reproduce the above copyright
     39       1.19       agc  *    notice, this list of conditions and the following disclaimer in the
     40       1.19       agc  *    documentation and/or other materials provided with the distribution.
     41       1.19       agc  * 3. Neither the name of the University nor the names of its contributors
     42       1.19       agc  *    may be used to endorse or promote products derived from this software
     43       1.19       agc  *    without specific prior written permission.
     44       1.19       agc  *
     45       1.19       agc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     46       1.19       agc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     47       1.19       agc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     48       1.19       agc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     49       1.19       agc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     50       1.19       agc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     51       1.19       agc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     52       1.19       agc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     53       1.19       agc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     54       1.19       agc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     55       1.19       agc  * SUCH DAMAGE.
     56       1.19       agc  *
     57       1.19       agc  * 	@(#)boot.c	8.1 (Berkeley) 6/10/93
     58       1.19       agc  */
     59       1.19       agc 
     60       1.19       agc /*
     61        1.1     perry  * Copyright (c) 1996
     62        1.1     perry  *	Matthias Drochner.  All rights reserved.
     63        1.1     perry  * Copyright (c) 1996
     64        1.1     perry  * 	Perry E. Metzger.  All rights reserved.
     65        1.1     perry  *
     66        1.1     perry  * Redistribution and use in source and binary forms, with or without
     67        1.1     perry  * modification, are permitted provided that the following conditions
     68        1.1     perry  * are met:
     69        1.1     perry  * 1. Redistributions of source code must retain the above copyright
     70        1.1     perry  *    notice, this list of conditions and the following disclaimer.
     71        1.1     perry  * 2. Redistributions in binary form must reproduce the above copyright
     72        1.1     perry  *    notice, this list of conditions and the following disclaimer in the
     73        1.1     perry  *    documentation and/or other materials provided with the distribution.
     74        1.1     perry  *
     75        1.1     perry  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     76        1.1     perry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     77        1.1     perry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     78        1.1     perry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     79        1.1     perry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     80        1.1     perry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     81        1.1     perry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     82        1.1     perry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     83        1.1     perry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     84        1.1     perry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     85        1.1     perry  * SUCH DAMAGE.
     86        1.1     perry  *
     87        1.1     perry  * 	@(#)boot.c	8.1 (Berkeley) 6/10/93
     88        1.1     perry  */
     89        1.1     perry 
     90        1.2   thorpej /*
     91       1.62      maxv  * Starts a NetBSD ELF kernel. The low level startup is done in startprog.S.
     92        1.8  christos  * This is a special version of exec.c to support use of XMS.
     93        1.1     perry  */
     94        1.8  christos 
     95        1.1     perry #include <sys/param.h>
     96        1.1     perry #include <sys/reboot.h>
     97        1.1     perry 
     98        1.1     perry #include <lib/libsa/stand.h>
     99       1.23        ad #include <lib/libkern/libkern.h>
    100        1.4  drochner 
    101        1.6  christos #include "loadfile.h"
    102        1.1     perry #include "libi386.h"
    103        1.4  drochner #include "bootinfo.h"
    104       1.23        ad #include "bootmod.h"
    105       1.42  jmcneill #include "vbe.h"
    106       1.16  jdolecek #ifdef SUPPORT_PS2
    107       1.16  jdolecek #include "biosmca.h"
    108       1.16  jdolecek #endif
    109       1.63    nonaka #ifdef EFIBOOT
    110       1.63    nonaka #include "efiboot.h"
    111       1.63    nonaka #undef DEBUG	/* XXX */
    112       1.63    nonaka #endif
    113        1.1     perry 
    114        1.6  christos #define BOOT_NARGS	6
    115        1.1     perry 
    116       1.23        ad #ifndef	PAGE_SIZE
    117       1.23        ad #define	PAGE_SIZE	4096
    118       1.23        ad #endif
    119       1.23        ad 
    120       1.43   tsutsui #define MODULE_WARNING_SEC	5
    121       1.41  jmcneill 
    122       1.72  pgoyette #define MAXMODNAME	32	/* from <sys/module.h> */
    123       1.72  pgoyette 
    124        1.4  drochner extern struct btinfo_console btinfo_console;
    125  1.76.10.1      cjep extern struct btinfo_rootdevice bi_root;
    126        1.4  drochner 
    127       1.23        ad boot_module_t *boot_modules;
    128       1.23        ad bool boot_modules_enabled = true;
    129       1.23        ad bool kernel_loaded;
    130       1.23        ad 
    131       1.47  uebayasi typedef struct userconf_command {
    132       1.47  uebayasi 	char *uc_text;
    133       1.47  uebayasi 	size_t uc_len;
    134       1.47  uebayasi 	struct userconf_command *uc_next;
    135       1.47  uebayasi } userconf_command_t;
    136       1.47  uebayasi userconf_command_t *userconf_commands = NULL;
    137       1.47  uebayasi 
    138       1.74      manu struct btinfo_framebuffer btinfo_framebuffer;
    139       1.39  jmcneill 
    140       1.74      manu struct btinfo_modulelist *btinfo_modulelist;
    141       1.23        ad static size_t btinfo_modulelist_size;
    142       1.23        ad static uint32_t image_end;
    143       1.26        ad static char module_base[64] = "/";
    144       1.40        ad static int howto;
    145       1.23        ad 
    146       1.47  uebayasi static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL;
    147       1.47  uebayasi static size_t btinfo_userconfcommands_size = 0;
    148       1.47  uebayasi 
    149       1.41  jmcneill static void	module_init(const char *);
    150       1.57  jakllsch static void	module_add_common(const char *, uint8_t);
    151       1.23        ad 
    152       1.47  uebayasi static void	userconf_init(void);
    153       1.47  uebayasi 
    154       1.67    nonaka static void	extract_device(const char *, char *, size_t);
    155       1.76  christos static void	module_base_path(char *, size_t, const char *);
    156       1.67    nonaka static int	module_open(boot_module_t *, int, const char *, const char *,
    157       1.67    nonaka 		    bool);
    158       1.67    nonaka 
    159       1.34        ad void
    160       1.39  jmcneill framebuffer_configure(struct btinfo_framebuffer *fb)
    161       1.39  jmcneill {
    162       1.39  jmcneill 	if (fb)
    163       1.39  jmcneill 		btinfo_framebuffer = *fb;
    164       1.39  jmcneill 	else {
    165       1.39  jmcneill 		btinfo_framebuffer.physaddr = 0;
    166       1.39  jmcneill 		btinfo_framebuffer.flags = 0;
    167       1.39  jmcneill 	}
    168       1.39  jmcneill }
    169       1.39  jmcneill 
    170       1.39  jmcneill void
    171       1.34        ad module_add(char *name)
    172       1.34        ad {
    173       1.46  jmcneill 	return module_add_common(name, BM_TYPE_KMOD);
    174       1.46  jmcneill }
    175       1.46  jmcneill 
    176       1.46  jmcneill void
    177       1.46  jmcneill splash_add(char *name)
    178       1.46  jmcneill {
    179       1.46  jmcneill 	return module_add_common(name, BM_TYPE_IMAGE);
    180       1.46  jmcneill }
    181       1.46  jmcneill 
    182       1.49       tls void
    183       1.49       tls rnd_add(char *name)
    184       1.49       tls {
    185       1.49       tls 	return module_add_common(name, BM_TYPE_RND);
    186       1.49       tls }
    187       1.49       tls 
    188       1.51  jmcneill void
    189       1.51  jmcneill fs_add(char *name)
    190       1.51  jmcneill {
    191       1.51  jmcneill 	return module_add_common(name, BM_TYPE_FS);
    192       1.51  jmcneill }
    193       1.51  jmcneill 
    194       1.72  pgoyette /*
    195       1.72  pgoyette  * Add a /-separated list of module names to the boot list
    196       1.72  pgoyette  */
    197       1.72  pgoyette void
    198       1.72  pgoyette module_add_split(const char *name, uint8_t type)
    199       1.72  pgoyette {
    200       1.72  pgoyette 	char mod_name[MAXMODNAME];
    201       1.72  pgoyette 	int i;
    202       1.72  pgoyette 	const char *mp = name;
    203       1.72  pgoyette 	char *ep;
    204       1.72  pgoyette 
    205       1.72  pgoyette 	while (*mp) {				/* scan list of module names */
    206       1.72  pgoyette 		i = MAXMODNAME;
    207       1.72  pgoyette 		ep = mod_name;
    208       1.72  pgoyette 		while (--i) {			/* scan for end of first name */
    209       1.72  pgoyette 			*ep = *mp;
    210       1.72  pgoyette 			if (*ep == '/')		/* NUL-terminate the name */
    211       1.72  pgoyette 				*ep = '\0';
    212       1.72  pgoyette 
    213       1.72  pgoyette 			if (*ep == 0 ) {	/* add non-empty name */
    214       1.72  pgoyette 				if (ep != mod_name)
    215       1.72  pgoyette 					module_add_common(mod_name, type);
    216       1.72  pgoyette 				break;
    217       1.72  pgoyette 			}
    218       1.72  pgoyette 			ep++; mp++;
    219       1.72  pgoyette 		}
    220       1.72  pgoyette 		if (*ep != 0) {
    221       1.72  pgoyette 			printf("module name too long\n");
    222       1.72  pgoyette 			return;
    223       1.72  pgoyette 		}
    224       1.72  pgoyette 		if  (*mp == '/') {		/* skip separator if more */
    225       1.72  pgoyette 			mp++;
    226       1.72  pgoyette 		}
    227       1.72  pgoyette 	}
    228       1.72  pgoyette }
    229       1.72  pgoyette 
    230       1.46  jmcneill static void
    231       1.57  jakllsch module_add_common(const char *name, uint8_t type)
    232       1.46  jmcneill {
    233       1.34        ad 	boot_module_t *bm, *bmp;
    234       1.34        ad 	size_t len;
    235       1.34        ad 	char *str;
    236       1.34        ad 
    237       1.35        ad 	while (*name == ' ' || *name == '\t')
    238       1.35        ad 		++name;
    239       1.35        ad 
    240       1.67    nonaka 	for (bm = boot_modules; bm != NULL; bm = bm->bm_next)
    241       1.67    nonaka 		if (bm->bm_type == type && strcmp(bm->bm_path, name) == 0)
    242       1.67    nonaka 			return;
    243       1.67    nonaka 
    244       1.34        ad 	bm = alloc(sizeof(boot_module_t));
    245       1.34        ad 	len = strlen(name) + 1;
    246       1.34        ad 	str = alloc(len);
    247       1.34        ad 	if (bm == NULL || str == NULL) {
    248       1.34        ad 		printf("couldn't allocate module\n");
    249       1.34        ad 		return;
    250       1.34        ad 	}
    251       1.34        ad 	memcpy(str, name, len);
    252       1.34        ad 	bm->bm_path = str;
    253       1.34        ad 	bm->bm_next = NULL;
    254       1.46  jmcneill 	bm->bm_type = type;
    255       1.34        ad 	if (boot_modules == NULL)
    256       1.34        ad 		boot_modules = bm;
    257       1.34        ad 	else {
    258       1.34        ad 		for (bmp = boot_modules; bmp->bm_next;
    259       1.34        ad 		    bmp = bmp->bm_next)
    260       1.34        ad 			;
    261       1.34        ad 		bmp->bm_next = bm;
    262       1.34        ad 	}
    263       1.34        ad }
    264       1.34        ad 
    265       1.47  uebayasi void
    266       1.47  uebayasi userconf_add(char *cmd)
    267       1.47  uebayasi {
    268       1.47  uebayasi 	userconf_command_t *uc;
    269       1.47  uebayasi 	size_t len;
    270       1.47  uebayasi 	char *text;
    271       1.47  uebayasi 
    272       1.47  uebayasi 	while (*cmd == ' ' || *cmd == '\t')
    273       1.47  uebayasi 		++cmd;
    274       1.47  uebayasi 
    275       1.47  uebayasi 	uc = alloc(sizeof(*uc));
    276       1.47  uebayasi 	if (uc == NULL) {
    277       1.47  uebayasi 		printf("couldn't allocate command\n");
    278       1.47  uebayasi 		return;
    279       1.47  uebayasi 	}
    280       1.47  uebayasi 
    281       1.47  uebayasi 	len = strlen(cmd) + 1;
    282       1.47  uebayasi 	text = alloc(len);
    283       1.47  uebayasi 	if (text == NULL) {
    284       1.47  uebayasi 		dealloc(uc, sizeof(*uc));
    285       1.47  uebayasi 		printf("couldn't allocate command\n");
    286       1.47  uebayasi 		return;
    287       1.47  uebayasi 	}
    288       1.47  uebayasi 	memcpy(text, cmd, len);
    289       1.47  uebayasi 
    290       1.47  uebayasi 	uc->uc_text = text;
    291       1.47  uebayasi 	uc->uc_len = len;
    292       1.47  uebayasi 	uc->uc_next = NULL;
    293       1.47  uebayasi 
    294       1.47  uebayasi 	if (userconf_commands == NULL)
    295       1.47  uebayasi 		userconf_commands = uc;
    296       1.47  uebayasi 	else {
    297       1.47  uebayasi 		userconf_command_t *ucp;
    298       1.47  uebayasi 		for (ucp = userconf_commands; ucp->uc_next != NULL;
    299       1.47  uebayasi 		     ucp = ucp->uc_next)
    300       1.47  uebayasi 			;
    301       1.47  uebayasi 		ucp->uc_next = uc;
    302       1.47  uebayasi 	}
    303       1.47  uebayasi }
    304       1.47  uebayasi 
    305       1.69      maxv struct btinfo_prekern bi_prekern;
    306       1.69      maxv int has_prekern = 0;
    307       1.69      maxv 
    308       1.69      maxv static int
    309       1.69      maxv common_load_prekern(const char *file, u_long *basemem, u_long *extmem,
    310       1.69      maxv     physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
    311       1.69      maxv {
    312       1.69      maxv 	paddr_t kernpa_start, kernpa_end;
    313       1.69      maxv 	char prekernpath[] = "/prekern";
    314       1.70      maxv 	u_long prekern_start;
    315       1.69      maxv 	int fd, flags;
    316       1.69      maxv 
    317       1.69      maxv 	*extmem = getextmem();
    318       1.69      maxv 	*basemem = getbasemem();
    319       1.69      maxv 
    320       1.69      maxv 	marks[MARK_START] = loadaddr;
    321       1.69      maxv 
    322       1.69      maxv 	/* Load the prekern (static) */
    323       1.70      maxv 	flags = LOAD_KERNEL & ~(LOAD_HDR|LOAD_SYM);
    324       1.69      maxv 	if ((fd = loadfile(prekernpath, marks, flags)) == -1)
    325       1.75  christos 		return errno;
    326       1.69      maxv 	close(fd);
    327       1.69      maxv 
    328       1.70      maxv 	prekern_start = marks[MARK_START];
    329       1.70      maxv 
    330       1.70      maxv 	/* The kernel starts at 2MB. */
    331       1.70      maxv 	marks[MARK_START] = loadaddr;
    332       1.70      maxv 	marks[MARK_END] = loadaddr + (1UL << 21);
    333       1.70      maxv 	kernpa_start = (1UL << 21);
    334       1.69      maxv 
    335       1.69      maxv 	/* Load the kernel (dynamic) */
    336       1.69      maxv 	flags = (LOAD_KERNEL | LOAD_DYN) & ~(floppy ? LOAD_BACKWARDS : 0);
    337       1.69      maxv 	if ((fd = loadfile(file, marks, flags)) == -1)
    338       1.75  christos 		return errno;
    339       1.69      maxv 	close(fd);
    340       1.69      maxv 
    341       1.70      maxv 	kernpa_end = marks[MARK_END] - loadaddr;
    342       1.69      maxv 
    343       1.69      maxv 	/* If the root fs type is unusual, load its module. */
    344       1.69      maxv 	if (fsmod != NULL)
    345       1.72  pgoyette 		module_add_split(fsmod, BM_TYPE_KMOD);
    346       1.69      maxv 
    347       1.69      maxv 	bi_prekern.kernpa_start = kernpa_start;
    348       1.69      maxv 	bi_prekern.kernpa_end = kernpa_end;
    349       1.69      maxv 	BI_ADD(&bi_prekern, BTINFO_PREKERN, sizeof(struct btinfo_prekern));
    350       1.69      maxv 
    351       1.69      maxv 	/*
    352       1.69      maxv 	 * Gather some information for the kernel. Do this after the
    353       1.69      maxv 	 * "point of no return" to avoid memory leaks.
    354       1.69      maxv 	 * (but before DOS might be trashed in the XMS case)
    355       1.69      maxv 	 */
    356       1.69      maxv #ifdef PASS_BIOSGEOM
    357       1.69      maxv 	bi_getbiosgeom();
    358       1.69      maxv #endif
    359       1.69      maxv #ifdef PASS_MEMMAP
    360       1.69      maxv 	bi_getmemmap();
    361       1.69      maxv #endif
    362       1.69      maxv 
    363       1.70      maxv 	marks[MARK_START] = prekern_start;
    364       1.69      maxv 	marks[MARK_END] = (((u_long)marks[MARK_END] + sizeof(int) - 1)) &
    365       1.69      maxv 	    (-sizeof(int));
    366       1.69      maxv 	image_end = marks[MARK_END];
    367       1.69      maxv 	kernel_loaded = true;
    368       1.69      maxv 
    369       1.69      maxv 	return 0;
    370       1.69      maxv }
    371       1.69      maxv 
    372       1.32     joerg static int
    373       1.32     joerg common_load_kernel(const char *file, u_long *basemem, u_long *extmem,
    374       1.32     joerg     physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX])
    375        1.1     perry {
    376       1.32     joerg 	int fd;
    377        1.8  christos #ifdef XMS
    378       1.62      maxv 	u_long xmsmem;
    379       1.62      maxv 	physaddr_t origaddr = loadaddr;
    380        1.8  christos #endif
    381        1.8  christos 
    382       1.32     joerg 	*extmem = getextmem();
    383       1.32     joerg 	*basemem = getbasemem();
    384        1.8  christos 
    385        1.8  christos #ifdef XMS
    386        1.8  christos 	if ((getextmem1() == 0) && (xmsmem = checkxms())) {
    387       1.62      maxv 		u_long kernsize;
    388        1.8  christos 
    389        1.8  christos 		/*
    390        1.8  christos 		 * With "CONSERVATIVE_MEMDETECT", extmem is 0 because
    391       1.62      maxv 		 * getextmem() is getextmem1(). Without, the "smart"
    392       1.62      maxv 		 * methods could fail to report all memory as well.
    393        1.8  christos 		 * xmsmem is a few kB less than the actual size, but
    394       1.62      maxv 		 * better than nothing.
    395        1.8  christos 		 */
    396       1.32     joerg 		if (xmsmem > *extmem)
    397       1.32     joerg 			*extmem = xmsmem;
    398       1.21  junyoung 		/*
    399        1.8  christos 		 * Get the size of the kernel
    400        1.8  christos 		 */
    401        1.8  christos 		marks[MARK_START] = loadaddr;
    402       1.12  christos 		if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
    403       1.75  christos 			return errno;
    404        1.8  christos 		close(fd);
    405        1.8  christos 
    406        1.8  christos 		kernsize = marks[MARK_END];
    407        1.8  christos 		kernsize = (kernsize + 1023) / 1024;
    408        1.8  christos 
    409        1.8  christos 		loadaddr = xmsalloc(kernsize);
    410        1.8  christos 		if (!loadaddr)
    411       1.21  junyoung 			return ENOMEM;
    412        1.8  christos 	}
    413        1.8  christos #endif
    414        1.7  christos 	marks[MARK_START] = loadaddr;
    415       1.29  christos 	if ((fd = loadfile(file, marks,
    416       1.44  christos 	    LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
    417       1.75  christos 		return errno;
    418        1.1     perry 
    419        1.8  christos 	close(fd);
    420       1.10  drochner 
    421       1.50       dsl 	/* If the root fs type is unusual, load its module. */
    422       1.50       dsl 	if (fsmod != NULL)
    423       1.72  pgoyette 		module_add_split(fsmod, BM_TYPE_KMOD);
    424       1.34        ad 
    425       1.10  drochner 	/*
    426       1.10  drochner 	 * Gather some information for the kernel. Do this after the
    427       1.10  drochner 	 * "point of no return" to avoid memory leaks.
    428       1.10  drochner 	 * (but before DOS might be trashed in the XMS case)
    429       1.10  drochner 	 */
    430       1.10  drochner #ifdef PASS_BIOSGEOM
    431       1.10  drochner 	bi_getbiosgeom();
    432       1.10  drochner #endif
    433       1.10  drochner #ifdef PASS_MEMMAP
    434       1.10  drochner 	bi_getmemmap();
    435       1.10  drochner #endif
    436        1.8  christos 
    437        1.8  christos #ifdef XMS
    438        1.8  christos 	if (loadaddr != origaddr) {
    439        1.8  christos 		/*
    440       1.14      ross 		 * We now have done our last DOS IO, so we may
    441        1.8  christos 		 * trash the OS. Copy the data from the temporary
    442       1.20       wiz 		 * buffer to its real address.
    443        1.8  christos 		 */
    444        1.8  christos 		marks[MARK_START] -= loadaddr;
    445        1.8  christos 		marks[MARK_END] -= loadaddr;
    446        1.8  christos 		marks[MARK_SYM] -= loadaddr;
    447        1.8  christos 		marks[MARK_END] -= loadaddr;
    448        1.8  christos 		ppbcopy(loadaddr, origaddr, marks[MARK_END]);
    449        1.8  christos 	}
    450        1.8  christos #endif
    451        1.8  christos 	marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
    452        1.8  christos 	    (-sizeof(int));
    453       1.23        ad 	image_end = marks[MARK_END];
    454       1.23        ad 	kernel_loaded = true;
    455        1.1     perry 
    456       1.32     joerg 	return 0;
    457       1.32     joerg }
    458       1.32     joerg 
    459       1.32     joerg int
    460       1.40        ad exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy,
    461       1.62      maxv     void (*callback)(void))
    462       1.32     joerg {
    463       1.62      maxv 	uint32_t boot_argv[BOOT_NARGS];
    464       1.62      maxv 	u_long marks[MARK_MAX];
    465       1.32     joerg 	struct btinfo_symtab btinfo_symtab;
    466       1.62      maxv 	u_long extmem;
    467       1.62      maxv 	u_long basemem;
    468       1.63    nonaka 	int error;
    469       1.64    nonaka #ifdef EFIBOOT
    470       1.64    nonaka 	int i;
    471       1.64    nonaka #endif
    472       1.32     joerg 
    473       1.32     joerg #ifdef	DEBUG
    474       1.62      maxv 	printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL",
    475       1.62      maxv 	    loadaddr);
    476       1.32     joerg #endif
    477       1.32     joerg 
    478       1.61      maxv 	BI_ALLOC(BTINFO_MAX);
    479       1.32     joerg 
    480       1.32     joerg 	BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console));
    481  1.76.10.1      cjep 	if (bi_root.devname[0])
    482  1.76.10.1      cjep 		BI_ADD(&bi_root, BTINFO_ROOTDEVICE, sizeof(struct btinfo_rootdevice));
    483       1.32     joerg 
    484       1.40        ad 	howto = boothowto;
    485       1.40        ad 
    486       1.56  jakllsch 	memset(marks, 0, sizeof(marks));
    487       1.56  jakllsch 
    488       1.69      maxv 	if (has_prekern) {
    489       1.69      maxv 		error = common_load_prekern(file, &basemem, &extmem, loadaddr,
    490       1.69      maxv 		    floppy, marks);
    491       1.69      maxv 	} else {
    492       1.69      maxv 		error = common_load_kernel(file, &basemem, &extmem, loadaddr,
    493       1.69      maxv 		    floppy, marks);
    494       1.69      maxv 	}
    495       1.63    nonaka 	if (error) {
    496       1.63    nonaka 		errno = error;
    497       1.32     joerg 		goto out;
    498       1.63    nonaka 	}
    499       1.67    nonaka #ifdef EFIBOOT
    500       1.67    nonaka 	/* adjust to the real load address */
    501       1.67    nonaka 	marks[MARK_START] -= efi_loadaddr;
    502       1.67    nonaka 	marks[MARK_ENTRY] -= efi_loadaddr;
    503       1.67    nonaka 	marks[MARK_DATA] -= efi_loadaddr;
    504       1.67    nonaka 	/* MARK_NSYM */
    505       1.67    nonaka 	marks[MARK_SYM] -= efi_loadaddr;
    506       1.67    nonaka 	marks[MARK_END] -= efi_loadaddr;
    507       1.67    nonaka #endif
    508       1.32     joerg 
    509       1.31     joerg 	boot_argv[0] = boothowto;
    510       1.31     joerg 	boot_argv[1] = 0;
    511       1.31     joerg 	boot_argv[2] = vtophys(bootinfo);	/* old cyl offset */
    512       1.31     joerg 	boot_argv[3] = marks[MARK_END];
    513       1.31     joerg 	boot_argv[4] = extmem;
    514       1.31     joerg 	boot_argv[5] = basemem;
    515       1.31     joerg 
    516       1.23        ad 	/* pull in any modules if necessary */
    517       1.23        ad 	if (boot_modules_enabled) {
    518       1.41  jmcneill 		module_init(file);
    519       1.23        ad 		if (btinfo_modulelist) {
    520       1.67    nonaka #ifdef EFIBOOT
    521       1.67    nonaka 			/* convert module loaded address to paddr */
    522       1.67    nonaka 			struct bi_modulelist_entry *bim;
    523       1.67    nonaka 			bim = (void *)(btinfo_modulelist + 1);
    524       1.67    nonaka 			for (i = 0; i < btinfo_modulelist->num; i++, bim++)
    525       1.67    nonaka 				bim->base -= efi_loadaddr;
    526       1.67    nonaka 			btinfo_modulelist->endpa -= efi_loadaddr;
    527       1.67    nonaka #endif
    528       1.23        ad 			BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
    529       1.23        ad 			    btinfo_modulelist_size);
    530       1.23        ad 		}
    531       1.23        ad 	}
    532        1.1     perry 
    533       1.47  uebayasi 	userconf_init();
    534       1.47  uebayasi 	if (btinfo_userconfcommands != NULL)
    535       1.47  uebayasi 		BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS,
    536       1.58  jakllsch 		    btinfo_userconfcommands_size);
    537       1.47  uebayasi 
    538        1.1     perry #ifdef DEBUG
    539        1.8  christos 	printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
    540        1.7  christos 	    marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
    541        1.1     perry #endif
    542        1.1     perry 
    543        1.8  christos 	btinfo_symtab.nsym = marks[MARK_NSYM];
    544        1.8  christos 	btinfo_symtab.ssym = marks[MARK_SYM];
    545        1.8  christos 	btinfo_symtab.esym = marks[MARK_END];
    546        1.8  christos 	BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab));
    547        1.8  christos 
    548       1.42  jmcneill 	/* set new video mode if necessary */
    549       1.42  jmcneill 	vbe_commit();
    550       1.42  jmcneill 	BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER,
    551       1.42  jmcneill 	    sizeof(struct btinfo_framebuffer));
    552       1.42  jmcneill 
    553       1.40        ad 	if (callback != NULL)
    554       1.40        ad 		(*callback)();
    555       1.63    nonaka #ifdef EFIBOOT
    556       1.64    nonaka 	/* Copy bootinfo to safe arena. */
    557       1.64    nonaka 	for (i = 0; i < bootinfo->nentries; i++) {
    558       1.64    nonaka 		struct btinfo_common *bi = (void *)(u_long)bootinfo->entry[i];
    559       1.64    nonaka 		char *p = alloc(bi->len);
    560       1.64    nonaka 		memcpy(p, bi, bi->len);
    561       1.64    nonaka 		bootinfo->entry[i] = vtophys(p);
    562       1.64    nonaka 	}
    563       1.64    nonaka 
    564       1.65    nonaka 	efi_kernel_start = marks[MARK_START];
    565       1.70      maxv 	efi_kernel_size = image_end - (efi_loadaddr + efi_kernel_start);
    566       1.63    nonaka #endif
    567       1.15       dbj 	startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
    568       1.62      maxv 	    x86_trunc_page(basemem * 1024));
    569        1.1     perry 	panic("exec returned");
    570        1.1     perry 
    571        1.4  drochner out:
    572        1.4  drochner 	BI_FREE();
    573       1.60      maxv 	bootinfo = NULL;
    574       1.21  junyoung 	return -1;
    575        1.1     perry }
    576       1.23        ad 
    577       1.41  jmcneill static void
    578       1.41  jmcneill extract_device(const char *path, char *buf, size_t buflen)
    579       1.41  jmcneill {
    580       1.59  jakllsch 	size_t i;
    581       1.41  jmcneill 
    582       1.41  jmcneill 	if (strchr(path, ':') != NULL) {
    583       1.41  jmcneill 		for (i = 0; i < buflen - 2 && path[i] != ':'; i++)
    584       1.41  jmcneill 			buf[i] = path[i];
    585       1.41  jmcneill 		buf[i++] = ':';
    586       1.41  jmcneill 		buf[i] = '\0';
    587       1.41  jmcneill 	} else
    588       1.41  jmcneill 		buf[0] = '\0';
    589       1.41  jmcneill }
    590       1.41  jmcneill 
    591       1.26        ad static const char *
    592       1.67    nonaka module_path(boot_module_t *bm, const char *kdev, const char *base_path)
    593       1.26        ad {
    594       1.26        ad 	static char buf[256];
    595       1.41  jmcneill 	char name_buf[256], dev_buf[64];
    596       1.41  jmcneill 	const char *name, *name2, *p;
    597       1.26        ad 
    598       1.26        ad 	name = bm->bm_path;
    599       1.33     joerg 	for (name2 = name; *name2; ++name2) {
    600       1.33     joerg 		if (*name2 == ' ' || *name2 == '\t') {
    601       1.33     joerg 			strlcpy(name_buf, name, sizeof(name_buf));
    602       1.59  jakllsch 			if ((uintptr_t)name2 - (uintptr_t)name < sizeof(name_buf))
    603       1.33     joerg 				name_buf[name2 - name] = '\0';
    604       1.33     joerg 			name = name_buf;
    605       1.33     joerg 			break;
    606       1.33     joerg 		}
    607       1.33     joerg 	}
    608       1.41  jmcneill 	if ((p = strchr(name, ':')) != NULL) {
    609       1.41  jmcneill 		/* device specified, use it */
    610       1.41  jmcneill 		if (p[1] == '/')
    611       1.41  jmcneill 			snprintf(buf, sizeof(buf), "%s", name);
    612       1.41  jmcneill 		else {
    613       1.41  jmcneill 			p++;
    614       1.41  jmcneill 			extract_device(name, dev_buf, sizeof(dev_buf));
    615       1.41  jmcneill 			snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
    616       1.67    nonaka 			    dev_buf, base_path, p, p);
    617       1.41  jmcneill 		}
    618       1.41  jmcneill 	} else {
    619       1.41  jmcneill 		/* device not specified; load from kernel device if known */
    620       1.58  jakllsch 		if (name[0] == '/')
    621       1.41  jmcneill 			snprintf(buf, sizeof(buf), "%s%s", kdev, name);
    622       1.41  jmcneill 		else
    623       1.41  jmcneill 			snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
    624       1.67    nonaka 			    kdev, base_path, name, name);
    625       1.41  jmcneill 	}
    626       1.33     joerg 
    627       1.26        ad 	return buf;
    628       1.26        ad }
    629       1.26        ad 
    630       1.36  christos static int
    631       1.67    nonaka module_open(boot_module_t *bm, int mode, const char *kdev,
    632       1.67    nonaka     const char *base_path, bool doload)
    633       1.28     chris {
    634       1.28     chris 	int fd;
    635       1.28     chris 	const char *path;
    636       1.36  christos 
    637       1.28     chris 	/* check the expanded path first */
    638       1.67    nonaka 	path = module_path(bm, kdev, base_path);
    639       1.28     chris 	fd = open(path, mode);
    640       1.41  jmcneill 	if (fd != -1) {
    641       1.41  jmcneill 		if ((howto & AB_SILENT) == 0 && doload)
    642       1.41  jmcneill 			printf("Loading %s ", path);
    643       1.41  jmcneill 	} else {
    644       1.28     chris 		/* now attempt the raw path provided */
    645       1.28     chris 		fd = open(bm->bm_path, mode);
    646       1.41  jmcneill 		if (fd != -1 && (howto & AB_SILENT) == 0 && doload)
    647       1.41  jmcneill 			printf("Loading %s ", bm->bm_path);
    648       1.41  jmcneill 	}
    649       1.41  jmcneill 	if (!doload && fd == -1) {
    650       1.41  jmcneill 		printf("WARNING: couldn't open %s", bm->bm_path);
    651       1.41  jmcneill 		if (strcmp(bm->bm_path, path) != 0)
    652       1.41  jmcneill 			printf(" (%s)", path);
    653       1.41  jmcneill 		printf("\n");
    654       1.28     chris 	}
    655       1.28     chris 	return fd;
    656       1.28     chris }
    657       1.28     chris 
    658       1.23        ad static void
    659       1.76  christos module_base_path(char *buf, size_t bufsize, const char *kernel_path)
    660       1.23        ad {
    661       1.76  christos #ifdef KERNEL_DIR
    662       1.76  christos 	/* we cheat here, because %.* does not work with the mini printf */
    663       1.76  christos 	char *ptr = strrchr(kernel_path, '/');
    664       1.76  christos 	if (ptr) *ptr = '\0';
    665       1.76  christos 	snprintf(buf, bufsize, "%s/modules", kernel_path);
    666       1.76  christos 	if (ptr) *ptr = '/';
    667       1.76  christos #else
    668       1.30     joerg 	const char *machine;
    669       1.23        ad 
    670       1.30     joerg 	switch (netbsd_elf_class) {
    671       1.30     joerg 	case ELFCLASS32:
    672       1.30     joerg 		machine = "i386";
    673       1.30     joerg 		break;
    674       1.30     joerg 	case ELFCLASS64:
    675       1.30     joerg 		machine = "amd64";
    676       1.30     joerg 		break;
    677       1.30     joerg 	default:
    678       1.30     joerg 		machine = "generic";
    679       1.30     joerg 		break;
    680       1.30     joerg 	}
    681       1.30     joerg 	if (netbsd_version / 1000000 % 100 == 99) {
    682       1.30     joerg 		/* -current */
    683       1.67    nonaka 		snprintf(buf, bufsize,
    684       1.38     rmind 		    "/stand/%s/%d.%d.%d/modules", machine,
    685       1.30     joerg 		    netbsd_version / 100000000,
    686       1.30     joerg 		    netbsd_version / 1000000 % 100,
    687       1.30     joerg 		    netbsd_version / 100 % 100);
    688       1.30     joerg 	} else if (netbsd_version != 0) {
    689       1.30     joerg 		/* release */
    690       1.67    nonaka 		snprintf(buf, bufsize,
    691       1.38     rmind 		    "/stand/%s/%d.%d/modules", machine,
    692       1.30     joerg 		    netbsd_version / 100000000,
    693       1.30     joerg 		    netbsd_version / 1000000 % 100);
    694       1.30     joerg 	}
    695       1.76  christos #endif
    696       1.67    nonaka }
    697       1.67    nonaka 
    698       1.67    nonaka static void
    699       1.67    nonaka module_init(const char *kernel_path)
    700       1.67    nonaka {
    701       1.67    nonaka 	struct bi_modulelist_entry *bi;
    702       1.67    nonaka 	struct stat st;
    703       1.67    nonaka 	char kdev[64];
    704       1.67    nonaka 	char *buf;
    705       1.67    nonaka 	boot_module_t *bm;
    706       1.67    nonaka 	ssize_t len;
    707       1.67    nonaka 	off_t off;
    708       1.67    nonaka 	int err, fd, nfail = 0;
    709       1.67    nonaka 
    710       1.67    nonaka 	extract_device(kernel_path, kdev, sizeof(kdev));
    711       1.76  christos 	module_base_path(module_base, sizeof(module_base), kernel_path);
    712       1.30     joerg 
    713       1.23        ad 	/* First, see which modules are valid and calculate btinfo size */
    714       1.23        ad 	len = sizeof(struct btinfo_modulelist);
    715       1.23        ad 	for (bm = boot_modules; bm; bm = bm->bm_next) {
    716       1.67    nonaka 		fd = module_open(bm, 0, kdev, module_base, false);
    717       1.23        ad 		if (fd == -1) {
    718       1.23        ad 			bm->bm_len = -1;
    719       1.41  jmcneill 			++nfail;
    720       1.23        ad 			continue;
    721       1.23        ad 		}
    722       1.23        ad 		err = fstat(fd, &st);
    723       1.24        ad 		if (err == -1 || st.st_size == -1) {
    724       1.28     chris 			printf("WARNING: couldn't stat %s\n", bm->bm_path);
    725       1.23        ad 			close(fd);
    726       1.23        ad 			bm->bm_len = -1;
    727       1.41  jmcneill 			++nfail;
    728       1.23        ad 			continue;
    729       1.23        ad 		}
    730       1.23        ad 		bm->bm_len = st.st_size;
    731       1.23        ad 		close(fd);
    732       1.23        ad 		len += sizeof(struct bi_modulelist_entry);
    733       1.23        ad 	}
    734       1.23        ad 
    735       1.23        ad 	/* Allocate the module list */
    736       1.23        ad 	btinfo_modulelist = alloc(len);
    737       1.23        ad 	if (btinfo_modulelist == NULL) {
    738       1.23        ad 		printf("WARNING: couldn't allocate module list\n");
    739       1.43   tsutsui 		wait_sec(MODULE_WARNING_SEC);
    740       1.23        ad 		return;
    741       1.23        ad 	}
    742       1.23        ad 	memset(btinfo_modulelist, 0, len);
    743       1.23        ad 	btinfo_modulelist_size = len;
    744       1.23        ad 
    745       1.23        ad 	/* Fill in btinfo structure */
    746       1.23        ad 	buf = (char *)btinfo_modulelist;
    747       1.23        ad 	btinfo_modulelist->num = 0;
    748       1.23        ad 	off = sizeof(struct btinfo_modulelist);
    749       1.23        ad 
    750       1.23        ad 	for (bm = boot_modules; bm; bm = bm->bm_next) {
    751       1.23        ad 		if (bm->bm_len == -1)
    752       1.23        ad 			continue;
    753       1.67    nonaka 		fd = module_open(bm, 0, kdev, module_base, true);
    754       1.41  jmcneill 		if (fd == -1)
    755       1.23        ad 			continue;
    756       1.24        ad 		image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
    757       1.52  jakllsch 		len = pread(fd, (void *)(uintptr_t)image_end, SSIZE_MAX);
    758       1.24        ad 		if (len < bm->bm_len) {
    759       1.40        ad 			if ((howto & AB_SILENT) != 0)
    760       1.40        ad 				printf("Loading %s ", bm->bm_path);
    761       1.23        ad 			printf(" FAILED\n");
    762       1.23        ad 		} else {
    763       1.23        ad 			btinfo_modulelist->num++;
    764       1.23        ad 			bi = (struct bi_modulelist_entry *)(buf + off);
    765       1.23        ad 			off += sizeof(struct bi_modulelist_entry);
    766       1.23        ad 			strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1);
    767       1.24        ad 			bi->base = image_end;
    768       1.24        ad 			bi->len = len;
    769       1.49       tls 			switch (bm->bm_type) {
    770       1.49       tls 			    case BM_TYPE_KMOD:
    771       1.49       tls 				bi->type = BI_MODULE_ELF;
    772       1.49       tls 				break;
    773       1.49       tls 			    case BM_TYPE_IMAGE:
    774       1.49       tls 				bi->type = BI_MODULE_IMAGE;
    775       1.49       tls 				break;
    776       1.51  jmcneill 			    case BM_TYPE_FS:
    777       1.51  jmcneill 				bi->type = BI_MODULE_FS;
    778       1.51  jmcneill 				break;
    779       1.49       tls 			    case BM_TYPE_RND:
    780       1.49       tls 			    default:
    781       1.49       tls 				/* safest -- rnd checks the sha1 */
    782       1.49       tls 				bi->type = BI_MODULE_RND;
    783       1.49       tls 				break;
    784       1.49       tls 			}
    785       1.40        ad 			if ((howto & AB_SILENT) == 0)
    786       1.40        ad 				printf(" \n");
    787       1.23        ad 		}
    788       1.24        ad 		if (len > 0)
    789       1.24        ad 			image_end += len;
    790       1.23        ad 		close(fd);
    791       1.23        ad 	}
    792       1.23        ad 	btinfo_modulelist->endpa = image_end;
    793       1.41  jmcneill 
    794       1.41  jmcneill 	if (nfail > 0) {
    795       1.41  jmcneill 		printf("WARNING: %d module%s failed to load\n",
    796       1.41  jmcneill 		    nfail, nfail == 1 ? "" : "s");
    797       1.41  jmcneill #if notyet
    798       1.43   tsutsui 		wait_sec(MODULE_WARNING_SEC);
    799       1.41  jmcneill #endif
    800       1.41  jmcneill 	}
    801       1.23        ad }
    802       1.33     joerg 
    803       1.47  uebayasi static void
    804       1.47  uebayasi userconf_init(void)
    805       1.47  uebayasi {
    806       1.47  uebayasi 	size_t count, len;
    807       1.47  uebayasi 	userconf_command_t *uc;
    808       1.47  uebayasi 	char *buf;
    809       1.47  uebayasi 	off_t off;
    810       1.47  uebayasi 
    811       1.47  uebayasi 	/* Calculate the userconf commands list size */
    812       1.47  uebayasi 	count = 0;
    813       1.47  uebayasi 	for (uc = userconf_commands; uc != NULL; uc = uc->uc_next)
    814       1.47  uebayasi 		count++;
    815       1.55  jakllsch 	len = sizeof(*btinfo_userconfcommands) +
    816       1.47  uebayasi 	      count * sizeof(struct bi_userconfcommand);
    817       1.47  uebayasi 
    818       1.47  uebayasi 	/* Allocate the userconf commands list */
    819       1.47  uebayasi 	btinfo_userconfcommands = alloc(len);
    820       1.47  uebayasi 	if (btinfo_userconfcommands == NULL) {
    821       1.47  uebayasi 		printf("WARNING: couldn't allocate userconf commands list\n");
    822       1.47  uebayasi 		return;
    823       1.47  uebayasi 	}
    824       1.47  uebayasi 	memset(btinfo_userconfcommands, 0, len);
    825       1.47  uebayasi 	btinfo_userconfcommands_size = len;
    826       1.47  uebayasi 
    827       1.47  uebayasi 	/* Fill in btinfo structure */
    828       1.47  uebayasi 	buf = (char *)btinfo_userconfcommands;
    829       1.47  uebayasi 	off = sizeof(*btinfo_userconfcommands);
    830       1.47  uebayasi 	btinfo_userconfcommands->num = 0;
    831       1.47  uebayasi 	for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) {
    832       1.47  uebayasi 		struct bi_userconfcommand *bi;
    833       1.47  uebayasi 		bi = (struct bi_userconfcommand *)(buf + off);
    834       1.47  uebayasi 		strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1);
    835       1.47  uebayasi 
    836       1.47  uebayasi 		off += sizeof(*bi);
    837       1.47  uebayasi 		btinfo_userconfcommands->num++;
    838       1.47  uebayasi 	}
    839       1.47  uebayasi }
    840       1.47  uebayasi 
    841       1.33     joerg int
    842       1.33     joerg exec_multiboot(const char *file, char *args)
    843       1.33     joerg {
    844       1.74      manu 	physaddr_t loadaddr = 0;
    845       1.62      maxv 	u_long marks[MARK_MAX];
    846       1.62      maxv 	u_long extmem;
    847       1.62      maxv 	u_long basemem;
    848       1.74      manu 	struct multiboot_package *mbp = NULL;
    849       1.33     joerg 
    850       1.74      manu #ifndef NO_MULTIBOOT2
    851       1.74      manu 	if ((mbp = probe_multiboot2(file)) != NULL)
    852       1.74      manu 		goto is_multiboot;
    853       1.74      manu #endif
    854       1.33     joerg 
    855       1.74      manu 	if ((mbp = probe_multiboot1(file)) != NULL) {
    856       1.74      manu #ifdef EFIBOOT
    857       1.74      manu 		printf("EFI boot requires multiboot 2 kernel\n");
    858       1.33     joerg 		goto out;
    859       1.74      manu #else
    860       1.74      manu 		goto is_multiboot;
    861       1.74      manu #endif
    862       1.74      manu 	}
    863       1.33     joerg 
    864       1.74      manu #ifndef NO_MULTIBOOT2
    865       1.74      manu 	printf("%s is not a multiboot kernel\n", file);
    866       1.74      manu #else
    867       1.74      manu 	printf("%s is not a multiboot 1 kernel "
    868       1.74      manu 	    "(multiboot 2 support is not built in)\n", file);
    869       1.74      manu #endif
    870       1.74      manu 	goto out;
    871       1.33     joerg 
    872       1.74      manu is_multiboot:
    873       1.74      manu #ifdef EFIBOOT
    874       1.74      manu 	loadaddr = efi_loadaddr;
    875       1.74      manu #endif
    876       1.74      manu 	if (common_load_kernel(file, &basemem, &extmem, loadaddr, 0, marks))
    877       1.74      manu 		goto out;
    878       1.33     joerg 
    879       1.74      manu 	if (boot_modules_enabled)
    880       1.41  jmcneill 		module_init(file);
    881       1.33     joerg 
    882       1.74      manu 	mbp->mbp_args = args;
    883       1.74      manu 	mbp->mbp_basemem = basemem;
    884       1.74      manu 	mbp->mbp_extmem = extmem;
    885       1.74      manu 	mbp->mbp_loadaddr = loadaddr;
    886       1.74      manu 	mbp->mbp_marks = marks;
    887       1.33     joerg 
    888       1.74      manu 	/* Only returns on error */
    889       1.74      manu 	(void)mbp->mbp_exec(mbp);
    890       1.33     joerg 
    891       1.33     joerg out:
    892       1.74      manu 	if (mbp != NULL)
    893       1.74      manu 		mbp->mbp_cleanup(mbp);
    894       1.74      manu 
    895       1.33     joerg 	return -1;
    896       1.33     joerg }
    897       1.40        ad 
    898       1.40        ad void
    899       1.40        ad x86_progress(const char *fmt, ...)
    900       1.40        ad {
    901       1.40        ad 	va_list ap;
    902       1.40        ad 
    903       1.40        ad 	if ((howto & AB_SILENT) != 0)
    904       1.40        ad 		return;
    905       1.40        ad 	va_start(ap, fmt);
    906       1.40        ad 	vprintf(fmt, ap);
    907       1.40        ad 	va_end(ap);
    908       1.40        ad }
    909