1 1.81 andvar /* $NetBSD: exec.c,v 1.81 2024/09/11 20:15:36 andvar 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.1 perry */ 93 1.8 christos 94 1.1 perry #include <sys/param.h> 95 1.1 perry #include <sys/reboot.h> 96 1.1 perry 97 1.1 perry #include <lib/libsa/stand.h> 98 1.23 ad #include <lib/libkern/libkern.h> 99 1.4 drochner 100 1.6 christos #include "loadfile.h" 101 1.1 perry #include "libi386.h" 102 1.4 drochner #include "bootinfo.h" 103 1.23 ad #include "bootmod.h" 104 1.42 jmcneill #include "vbe.h" 105 1.16 jdolecek #ifdef SUPPORT_PS2 106 1.16 jdolecek #include "biosmca.h" 107 1.16 jdolecek #endif 108 1.63 nonaka #ifdef EFIBOOT 109 1.63 nonaka #include "efiboot.h" 110 1.80 mlelstv #include "biosdisk.h" 111 1.80 mlelstv #include "efidisk.h" 112 1.63 nonaka #undef DEBUG /* XXX */ 113 1.63 nonaka #endif 114 1.1 perry 115 1.6 christos #define BOOT_NARGS 6 116 1.1 perry 117 1.23 ad #ifndef PAGE_SIZE 118 1.23 ad #define PAGE_SIZE 4096 119 1.23 ad #endif 120 1.23 ad 121 1.43 tsutsui #define MODULE_WARNING_SEC 5 122 1.41 jmcneill 123 1.72 pgoyette #define MAXMODNAME 32 /* from <sys/module.h> */ 124 1.72 pgoyette 125 1.4 drochner extern struct btinfo_console btinfo_console; 126 1.77 mlelstv extern struct btinfo_rootdevice bi_root; 127 1.4 drochner 128 1.23 ad boot_module_t *boot_modules; 129 1.23 ad bool boot_modules_enabled = true; 130 1.23 ad bool kernel_loaded; 131 1.23 ad 132 1.47 uebayasi typedef struct userconf_command { 133 1.47 uebayasi char *uc_text; 134 1.47 uebayasi size_t uc_len; 135 1.47 uebayasi struct userconf_command *uc_next; 136 1.47 uebayasi } userconf_command_t; 137 1.47 uebayasi userconf_command_t *userconf_commands = NULL; 138 1.47 uebayasi 139 1.74 manu struct btinfo_framebuffer btinfo_framebuffer; 140 1.39 jmcneill 141 1.74 manu struct btinfo_modulelist *btinfo_modulelist; 142 1.23 ad static size_t btinfo_modulelist_size; 143 1.23 ad static uint32_t image_end; 144 1.26 ad static char module_base[64] = "/"; 145 1.40 ad static int howto; 146 1.23 ad 147 1.47 uebayasi static struct btinfo_userconfcommands *btinfo_userconfcommands = NULL; 148 1.47 uebayasi static size_t btinfo_userconfcommands_size = 0; 149 1.47 uebayasi 150 1.41 jmcneill static void module_init(const char *); 151 1.57 jakllsch static void module_add_common(const char *, uint8_t); 152 1.23 ad 153 1.47 uebayasi static void userconf_init(void); 154 1.47 uebayasi 155 1.67 nonaka static void extract_device(const char *, char *, size_t); 156 1.76 christos static void module_base_path(char *, size_t, const char *); 157 1.67 nonaka static int module_open(boot_module_t *, int, const char *, const char *, 158 1.67 nonaka bool); 159 1.67 nonaka 160 1.34 ad void 161 1.39 jmcneill framebuffer_configure(struct btinfo_framebuffer *fb) 162 1.39 jmcneill { 163 1.39 jmcneill if (fb) 164 1.39 jmcneill btinfo_framebuffer = *fb; 165 1.39 jmcneill else { 166 1.39 jmcneill btinfo_framebuffer.physaddr = 0; 167 1.39 jmcneill btinfo_framebuffer.flags = 0; 168 1.39 jmcneill } 169 1.39 jmcneill } 170 1.39 jmcneill 171 1.39 jmcneill void 172 1.34 ad module_add(char *name) 173 1.34 ad { 174 1.46 jmcneill return module_add_common(name, BM_TYPE_KMOD); 175 1.46 jmcneill } 176 1.46 jmcneill 177 1.46 jmcneill void 178 1.46 jmcneill splash_add(char *name) 179 1.46 jmcneill { 180 1.46 jmcneill return module_add_common(name, BM_TYPE_IMAGE); 181 1.46 jmcneill } 182 1.46 jmcneill 183 1.49 tls void 184 1.49 tls rnd_add(char *name) 185 1.49 tls { 186 1.49 tls return module_add_common(name, BM_TYPE_RND); 187 1.49 tls } 188 1.49 tls 189 1.51 jmcneill void 190 1.51 jmcneill fs_add(char *name) 191 1.51 jmcneill { 192 1.51 jmcneill return module_add_common(name, BM_TYPE_FS); 193 1.51 jmcneill } 194 1.51 jmcneill 195 1.72 pgoyette /* 196 1.72 pgoyette * Add a /-separated list of module names to the boot list 197 1.72 pgoyette */ 198 1.72 pgoyette void 199 1.72 pgoyette module_add_split(const char *name, uint8_t type) 200 1.72 pgoyette { 201 1.72 pgoyette char mod_name[MAXMODNAME]; 202 1.72 pgoyette int i; 203 1.72 pgoyette const char *mp = name; 204 1.72 pgoyette char *ep; 205 1.72 pgoyette 206 1.72 pgoyette while (*mp) { /* scan list of module names */ 207 1.72 pgoyette i = MAXMODNAME; 208 1.72 pgoyette ep = mod_name; 209 1.72 pgoyette while (--i) { /* scan for end of first name */ 210 1.72 pgoyette *ep = *mp; 211 1.72 pgoyette if (*ep == '/') /* NUL-terminate the name */ 212 1.72 pgoyette *ep = '\0'; 213 1.72 pgoyette 214 1.72 pgoyette if (*ep == 0 ) { /* add non-empty name */ 215 1.72 pgoyette if (ep != mod_name) 216 1.72 pgoyette module_add_common(mod_name, type); 217 1.72 pgoyette break; 218 1.72 pgoyette } 219 1.72 pgoyette ep++; mp++; 220 1.72 pgoyette } 221 1.72 pgoyette if (*ep != 0) { 222 1.72 pgoyette printf("module name too long\n"); 223 1.72 pgoyette return; 224 1.72 pgoyette } 225 1.72 pgoyette if (*mp == '/') { /* skip separator if more */ 226 1.72 pgoyette mp++; 227 1.72 pgoyette } 228 1.72 pgoyette } 229 1.72 pgoyette } 230 1.72 pgoyette 231 1.46 jmcneill static void 232 1.57 jakllsch module_add_common(const char *name, uint8_t type) 233 1.46 jmcneill { 234 1.34 ad boot_module_t *bm, *bmp; 235 1.34 ad size_t len; 236 1.34 ad char *str; 237 1.34 ad 238 1.35 ad while (*name == ' ' || *name == '\t') 239 1.35 ad ++name; 240 1.35 ad 241 1.67 nonaka for (bm = boot_modules; bm != NULL; bm = bm->bm_next) 242 1.67 nonaka if (bm->bm_type == type && strcmp(bm->bm_path, name) == 0) 243 1.67 nonaka return; 244 1.67 nonaka 245 1.34 ad bm = alloc(sizeof(boot_module_t)); 246 1.34 ad len = strlen(name) + 1; 247 1.34 ad str = alloc(len); 248 1.34 ad if (bm == NULL || str == NULL) { 249 1.34 ad printf("couldn't allocate module\n"); 250 1.34 ad return; 251 1.34 ad } 252 1.34 ad memcpy(str, name, len); 253 1.34 ad bm->bm_path = str; 254 1.34 ad bm->bm_next = NULL; 255 1.46 jmcneill bm->bm_type = type; 256 1.34 ad if (boot_modules == NULL) 257 1.34 ad boot_modules = bm; 258 1.34 ad else { 259 1.34 ad for (bmp = boot_modules; bmp->bm_next; 260 1.34 ad bmp = bmp->bm_next) 261 1.34 ad ; 262 1.34 ad bmp->bm_next = bm; 263 1.34 ad } 264 1.34 ad } 265 1.34 ad 266 1.47 uebayasi void 267 1.47 uebayasi userconf_add(char *cmd) 268 1.47 uebayasi { 269 1.47 uebayasi userconf_command_t *uc; 270 1.47 uebayasi size_t len; 271 1.47 uebayasi char *text; 272 1.47 uebayasi 273 1.47 uebayasi while (*cmd == ' ' || *cmd == '\t') 274 1.47 uebayasi ++cmd; 275 1.47 uebayasi 276 1.47 uebayasi uc = alloc(sizeof(*uc)); 277 1.47 uebayasi if (uc == NULL) { 278 1.47 uebayasi printf("couldn't allocate command\n"); 279 1.47 uebayasi return; 280 1.47 uebayasi } 281 1.47 uebayasi 282 1.47 uebayasi len = strlen(cmd) + 1; 283 1.47 uebayasi text = alloc(len); 284 1.47 uebayasi if (text == NULL) { 285 1.47 uebayasi dealloc(uc, sizeof(*uc)); 286 1.47 uebayasi printf("couldn't allocate command\n"); 287 1.47 uebayasi return; 288 1.47 uebayasi } 289 1.47 uebayasi memcpy(text, cmd, len); 290 1.47 uebayasi 291 1.47 uebayasi uc->uc_text = text; 292 1.47 uebayasi uc->uc_len = len; 293 1.47 uebayasi uc->uc_next = NULL; 294 1.47 uebayasi 295 1.47 uebayasi if (userconf_commands == NULL) 296 1.47 uebayasi userconf_commands = uc; 297 1.47 uebayasi else { 298 1.47 uebayasi userconf_command_t *ucp; 299 1.47 uebayasi for (ucp = userconf_commands; ucp->uc_next != NULL; 300 1.47 uebayasi ucp = ucp->uc_next) 301 1.47 uebayasi ; 302 1.47 uebayasi ucp->uc_next = uc; 303 1.47 uebayasi } 304 1.47 uebayasi } 305 1.47 uebayasi 306 1.69 maxv struct btinfo_prekern bi_prekern; 307 1.69 maxv int has_prekern = 0; 308 1.69 maxv 309 1.69 maxv static int 310 1.69 maxv common_load_prekern(const char *file, u_long *basemem, u_long *extmem, 311 1.69 maxv physaddr_t loadaddr, int floppy, u_long marks[MARK_MAX]) 312 1.69 maxv { 313 1.69 maxv paddr_t kernpa_start, kernpa_end; 314 1.69 maxv char prekernpath[] = "/prekern"; 315 1.70 maxv u_long prekern_start; 316 1.69 maxv int fd, flags; 317 1.69 maxv 318 1.69 maxv *extmem = getextmem(); 319 1.69 maxv *basemem = getbasemem(); 320 1.69 maxv 321 1.69 maxv marks[MARK_START] = loadaddr; 322 1.69 maxv 323 1.69 maxv /* Load the prekern (static) */ 324 1.70 maxv flags = LOAD_KERNEL & ~(LOAD_HDR|LOAD_SYM); 325 1.69 maxv if ((fd = loadfile(prekernpath, marks, flags)) == -1) 326 1.75 christos return errno; 327 1.69 maxv close(fd); 328 1.69 maxv 329 1.70 maxv prekern_start = marks[MARK_START]; 330 1.70 maxv 331 1.70 maxv /* The kernel starts at 2MB. */ 332 1.70 maxv marks[MARK_START] = loadaddr; 333 1.70 maxv marks[MARK_END] = loadaddr + (1UL << 21); 334 1.70 maxv kernpa_start = (1UL << 21); 335 1.69 maxv 336 1.69 maxv /* Load the kernel (dynamic) */ 337 1.69 maxv flags = (LOAD_KERNEL | LOAD_DYN) & ~(floppy ? LOAD_BACKWARDS : 0); 338 1.69 maxv if ((fd = loadfile(file, marks, flags)) == -1) 339 1.75 christos return errno; 340 1.69 maxv close(fd); 341 1.69 maxv 342 1.70 maxv kernpa_end = marks[MARK_END] - loadaddr; 343 1.69 maxv 344 1.69 maxv /* If the root fs type is unusual, load its module. */ 345 1.69 maxv if (fsmod != NULL) 346 1.72 pgoyette module_add_split(fsmod, BM_TYPE_KMOD); 347 1.69 maxv 348 1.69 maxv bi_prekern.kernpa_start = kernpa_start; 349 1.69 maxv bi_prekern.kernpa_end = kernpa_end; 350 1.69 maxv BI_ADD(&bi_prekern, BTINFO_PREKERN, sizeof(struct btinfo_prekern)); 351 1.69 maxv 352 1.69 maxv /* 353 1.69 maxv * Gather some information for the kernel. Do this after the 354 1.69 maxv * "point of no return" to avoid memory leaks. 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 378 1.32 joerg *extmem = getextmem(); 379 1.32 joerg *basemem = getbasemem(); 380 1.8 christos 381 1.7 christos marks[MARK_START] = loadaddr; 382 1.29 christos if ((fd = loadfile(file, marks, 383 1.44 christos LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1) 384 1.75 christos return errno; 385 1.1 perry 386 1.8 christos close(fd); 387 1.10 drochner 388 1.50 dsl /* If the root fs type is unusual, load its module. */ 389 1.50 dsl if (fsmod != NULL) 390 1.72 pgoyette module_add_split(fsmod, BM_TYPE_KMOD); 391 1.34 ad 392 1.10 drochner /* 393 1.10 drochner * Gather some information for the kernel. Do this after the 394 1.10 drochner * "point of no return" to avoid memory leaks. 395 1.10 drochner */ 396 1.10 drochner #ifdef PASS_BIOSGEOM 397 1.10 drochner bi_getbiosgeom(); 398 1.10 drochner #endif 399 1.10 drochner #ifdef PASS_MEMMAP 400 1.10 drochner bi_getmemmap(); 401 1.10 drochner #endif 402 1.8 christos 403 1.8 christos marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) & 404 1.8 christos (-sizeof(int)); 405 1.23 ad image_end = marks[MARK_END]; 406 1.23 ad kernel_loaded = true; 407 1.1 perry 408 1.32 joerg return 0; 409 1.32 joerg } 410 1.32 joerg 411 1.32 joerg int 412 1.40 ad exec_netbsd(const char *file, physaddr_t loadaddr, int boothowto, int floppy, 413 1.62 maxv void (*callback)(void)) 414 1.32 joerg { 415 1.62 maxv uint32_t boot_argv[BOOT_NARGS]; 416 1.62 maxv u_long marks[MARK_MAX]; 417 1.32 joerg struct btinfo_symtab btinfo_symtab; 418 1.62 maxv u_long extmem; 419 1.62 maxv u_long basemem; 420 1.79 manu u_long entry; 421 1.63 nonaka int error; 422 1.64 nonaka #ifdef EFIBOOT 423 1.64 nonaka int i; 424 1.64 nonaka #endif 425 1.32 joerg 426 1.32 joerg #ifdef DEBUG 427 1.62 maxv printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL", 428 1.62 maxv loadaddr); 429 1.32 joerg #endif 430 1.32 joerg 431 1.61 maxv BI_ALLOC(BTINFO_MAX); 432 1.32 joerg 433 1.32 joerg BI_ADD(&btinfo_console, BTINFO_CONSOLE, sizeof(struct btinfo_console)); 434 1.77 mlelstv if (bi_root.devname[0]) 435 1.77 mlelstv BI_ADD(&bi_root, BTINFO_ROOTDEVICE, sizeof(struct btinfo_rootdevice)); 436 1.32 joerg 437 1.40 ad howto = boothowto; 438 1.40 ad 439 1.56 jakllsch memset(marks, 0, sizeof(marks)); 440 1.56 jakllsch 441 1.69 maxv if (has_prekern) { 442 1.69 maxv error = common_load_prekern(file, &basemem, &extmem, loadaddr, 443 1.69 maxv floppy, marks); 444 1.69 maxv } else { 445 1.69 maxv error = common_load_kernel(file, &basemem, &extmem, loadaddr, 446 1.69 maxv floppy, marks); 447 1.69 maxv } 448 1.63 nonaka if (error) { 449 1.63 nonaka errno = error; 450 1.32 joerg goto out; 451 1.63 nonaka } 452 1.67 nonaka #ifdef EFIBOOT 453 1.80 mlelstv BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); 454 1.80 mlelstv BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge)); 455 1.80 mlelstv efidisk_getbiosgeom(); 456 1.80 mlelstv 457 1.79 manu efi_load_start = marks[MARK_START]; 458 1.79 manu 459 1.67 nonaka /* adjust to the real load address */ 460 1.67 nonaka marks[MARK_START] -= efi_loadaddr; 461 1.67 nonaka marks[MARK_ENTRY] -= efi_loadaddr; 462 1.67 nonaka marks[MARK_DATA] -= efi_loadaddr; 463 1.67 nonaka /* MARK_NSYM */ 464 1.67 nonaka marks[MARK_SYM] -= efi_loadaddr; 465 1.67 nonaka marks[MARK_END] -= efi_loadaddr; 466 1.67 nonaka #endif 467 1.32 joerg 468 1.31 joerg boot_argv[0] = boothowto; 469 1.31 joerg boot_argv[1] = 0; 470 1.31 joerg boot_argv[2] = vtophys(bootinfo); /* old cyl offset */ 471 1.31 joerg boot_argv[3] = marks[MARK_END]; 472 1.31 joerg boot_argv[4] = extmem; 473 1.31 joerg boot_argv[5] = basemem; 474 1.31 joerg 475 1.23 ad /* pull in any modules if necessary */ 476 1.23 ad if (boot_modules_enabled) { 477 1.41 jmcneill module_init(file); 478 1.23 ad if (btinfo_modulelist) { 479 1.67 nonaka #ifdef EFIBOOT 480 1.67 nonaka /* convert module loaded address to paddr */ 481 1.67 nonaka struct bi_modulelist_entry *bim; 482 1.67 nonaka bim = (void *)(btinfo_modulelist + 1); 483 1.67 nonaka for (i = 0; i < btinfo_modulelist->num; i++, bim++) 484 1.67 nonaka bim->base -= efi_loadaddr; 485 1.67 nonaka btinfo_modulelist->endpa -= efi_loadaddr; 486 1.67 nonaka #endif 487 1.23 ad BI_ADD(btinfo_modulelist, BTINFO_MODULELIST, 488 1.23 ad btinfo_modulelist_size); 489 1.23 ad } 490 1.23 ad } 491 1.1 perry 492 1.47 uebayasi userconf_init(); 493 1.47 uebayasi if (btinfo_userconfcommands != NULL) 494 1.47 uebayasi BI_ADD(btinfo_userconfcommands, BTINFO_USERCONFCOMMANDS, 495 1.58 jakllsch btinfo_userconfcommands_size); 496 1.47 uebayasi 497 1.1 perry #ifdef DEBUG 498 1.8 christos printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY], 499 1.7 christos marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); 500 1.1 perry #endif 501 1.1 perry 502 1.8 christos btinfo_symtab.nsym = marks[MARK_NSYM]; 503 1.8 christos btinfo_symtab.ssym = marks[MARK_SYM]; 504 1.8 christos btinfo_symtab.esym = marks[MARK_END]; 505 1.8 christos BI_ADD(&btinfo_symtab, BTINFO_SYMTAB, sizeof(struct btinfo_symtab)); 506 1.8 christos 507 1.42 jmcneill /* set new video mode if necessary */ 508 1.42 jmcneill vbe_commit(); 509 1.42 jmcneill BI_ADD(&btinfo_framebuffer, BTINFO_FRAMEBUFFER, 510 1.42 jmcneill sizeof(struct btinfo_framebuffer)); 511 1.42 jmcneill 512 1.40 ad if (callback != NULL) 513 1.40 ad (*callback)(); 514 1.79 manu 515 1.79 manu entry = marks[MARK_ENTRY]; 516 1.63 nonaka #ifdef EFIBOOT 517 1.64 nonaka /* Copy bootinfo to safe arena. */ 518 1.64 nonaka for (i = 0; i < bootinfo->nentries; i++) { 519 1.64 nonaka struct btinfo_common *bi = (void *)(u_long)bootinfo->entry[i]; 520 1.64 nonaka char *p = alloc(bi->len); 521 1.64 nonaka memcpy(p, bi, bi->len); 522 1.64 nonaka bootinfo->entry[i] = vtophys(p); 523 1.64 nonaka } 524 1.64 nonaka 525 1.65 nonaka efi_kernel_start = marks[MARK_START]; 526 1.70 maxv efi_kernel_size = image_end - (efi_loadaddr + efi_kernel_start); 527 1.79 manu 528 1.79 manu switch (efi_reloc_type) { 529 1.79 manu case RELOC_NONE: 530 1.79 manu entry += (efi_load_start - efi_kernel_start); 531 1.79 manu efi_kernel_start = efi_load_start; 532 1.79 manu break; 533 1.79 manu case RELOC_ADDR: 534 1.79 manu entry += (efi_kernel_reloc - efi_kernel_start); 535 1.79 manu efi_kernel_start = efi_kernel_reloc; 536 1.79 manu break; 537 1.79 manu case RELOC_DEFAULT: 538 1.79 manu default: 539 1.79 manu break; 540 1.79 manu } 541 1.63 nonaka #endif 542 1.79 manu startprog(entry, BOOT_NARGS, boot_argv, 543 1.62 maxv x86_trunc_page(basemem * 1024)); 544 1.1 perry panic("exec returned"); 545 1.1 perry 546 1.4 drochner out: 547 1.4 drochner BI_FREE(); 548 1.60 maxv bootinfo = NULL; 549 1.21 junyoung return -1; 550 1.1 perry } 551 1.23 ad 552 1.41 jmcneill static void 553 1.41 jmcneill extract_device(const char *path, char *buf, size_t buflen) 554 1.41 jmcneill { 555 1.59 jakllsch size_t i; 556 1.41 jmcneill 557 1.41 jmcneill if (strchr(path, ':') != NULL) { 558 1.41 jmcneill for (i = 0; i < buflen - 2 && path[i] != ':'; i++) 559 1.41 jmcneill buf[i] = path[i]; 560 1.41 jmcneill buf[i++] = ':'; 561 1.41 jmcneill buf[i] = '\0'; 562 1.41 jmcneill } else 563 1.41 jmcneill buf[0] = '\0'; 564 1.41 jmcneill } 565 1.41 jmcneill 566 1.26 ad static const char * 567 1.67 nonaka module_path(boot_module_t *bm, const char *kdev, const char *base_path) 568 1.26 ad { 569 1.26 ad static char buf[256]; 570 1.41 jmcneill char name_buf[256], dev_buf[64]; 571 1.41 jmcneill const char *name, *name2, *p; 572 1.26 ad 573 1.26 ad name = bm->bm_path; 574 1.33 joerg for (name2 = name; *name2; ++name2) { 575 1.33 joerg if (*name2 == ' ' || *name2 == '\t') { 576 1.33 joerg strlcpy(name_buf, name, sizeof(name_buf)); 577 1.59 jakllsch if ((uintptr_t)name2 - (uintptr_t)name < sizeof(name_buf)) 578 1.33 joerg name_buf[name2 - name] = '\0'; 579 1.33 joerg name = name_buf; 580 1.33 joerg break; 581 1.33 joerg } 582 1.33 joerg } 583 1.41 jmcneill if ((p = strchr(name, ':')) != NULL) { 584 1.41 jmcneill /* device specified, use it */ 585 1.41 jmcneill if (p[1] == '/') 586 1.41 jmcneill snprintf(buf, sizeof(buf), "%s", name); 587 1.41 jmcneill else { 588 1.41 jmcneill p++; 589 1.41 jmcneill extract_device(name, dev_buf, sizeof(dev_buf)); 590 1.41 jmcneill snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", 591 1.67 nonaka dev_buf, base_path, p, p); 592 1.41 jmcneill } 593 1.41 jmcneill } else { 594 1.41 jmcneill /* device not specified; load from kernel device if known */ 595 1.58 jakllsch if (name[0] == '/') 596 1.41 jmcneill snprintf(buf, sizeof(buf), "%s%s", kdev, name); 597 1.41 jmcneill else 598 1.41 jmcneill snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod", 599 1.67 nonaka kdev, base_path, name, name); 600 1.41 jmcneill } 601 1.33 joerg 602 1.26 ad return buf; 603 1.26 ad } 604 1.26 ad 605 1.36 christos static int 606 1.67 nonaka module_open(boot_module_t *bm, int mode, const char *kdev, 607 1.67 nonaka const char *base_path, bool doload) 608 1.28 chris { 609 1.28 chris int fd; 610 1.28 chris const char *path; 611 1.36 christos 612 1.28 chris /* check the expanded path first */ 613 1.67 nonaka path = module_path(bm, kdev, base_path); 614 1.28 chris fd = open(path, mode); 615 1.41 jmcneill if (fd != -1) { 616 1.41 jmcneill if ((howto & AB_SILENT) == 0 && doload) 617 1.41 jmcneill printf("Loading %s ", path); 618 1.41 jmcneill } else { 619 1.28 chris /* now attempt the raw path provided */ 620 1.28 chris fd = open(bm->bm_path, mode); 621 1.41 jmcneill if (fd != -1 && (howto & AB_SILENT) == 0 && doload) 622 1.41 jmcneill printf("Loading %s ", bm->bm_path); 623 1.41 jmcneill } 624 1.41 jmcneill if (!doload && fd == -1) { 625 1.41 jmcneill printf("WARNING: couldn't open %s", bm->bm_path); 626 1.41 jmcneill if (strcmp(bm->bm_path, path) != 0) 627 1.41 jmcneill printf(" (%s)", path); 628 1.41 jmcneill printf("\n"); 629 1.28 chris } 630 1.28 chris return fd; 631 1.28 chris } 632 1.28 chris 633 1.23 ad static void 634 1.76 christos module_base_path(char *buf, size_t bufsize, const char *kernel_path) 635 1.23 ad { 636 1.76 christos #ifdef KERNEL_DIR 637 1.76 christos /* we cheat here, because %.* does not work with the mini printf */ 638 1.76 christos char *ptr = strrchr(kernel_path, '/'); 639 1.76 christos if (ptr) *ptr = '\0'; 640 1.76 christos snprintf(buf, bufsize, "%s/modules", kernel_path); 641 1.76 christos if (ptr) *ptr = '/'; 642 1.76 christos #else 643 1.30 joerg const char *machine; 644 1.23 ad 645 1.30 joerg switch (netbsd_elf_class) { 646 1.30 joerg case ELFCLASS32: 647 1.30 joerg machine = "i386"; 648 1.30 joerg break; 649 1.30 joerg case ELFCLASS64: 650 1.30 joerg machine = "amd64"; 651 1.30 joerg break; 652 1.30 joerg default: 653 1.30 joerg machine = "generic"; 654 1.30 joerg break; 655 1.30 joerg } 656 1.30 joerg if (netbsd_version / 1000000 % 100 == 99) { 657 1.30 joerg /* -current */ 658 1.67 nonaka snprintf(buf, bufsize, 659 1.38 rmind "/stand/%s/%d.%d.%d/modules", machine, 660 1.30 joerg netbsd_version / 100000000, 661 1.30 joerg netbsd_version / 1000000 % 100, 662 1.78 riastrad netbsd_version / 100 % 10000); 663 1.30 joerg } else if (netbsd_version != 0) { 664 1.30 joerg /* release */ 665 1.67 nonaka snprintf(buf, bufsize, 666 1.38 rmind "/stand/%s/%d.%d/modules", machine, 667 1.30 joerg netbsd_version / 100000000, 668 1.30 joerg netbsd_version / 1000000 % 100); 669 1.30 joerg } 670 1.76 christos #endif 671 1.67 nonaka } 672 1.67 nonaka 673 1.67 nonaka static void 674 1.67 nonaka module_init(const char *kernel_path) 675 1.67 nonaka { 676 1.67 nonaka struct bi_modulelist_entry *bi; 677 1.67 nonaka struct stat st; 678 1.67 nonaka char kdev[64]; 679 1.67 nonaka char *buf; 680 1.67 nonaka boot_module_t *bm; 681 1.67 nonaka ssize_t len; 682 1.67 nonaka off_t off; 683 1.67 nonaka int err, fd, nfail = 0; 684 1.67 nonaka 685 1.67 nonaka extract_device(kernel_path, kdev, sizeof(kdev)); 686 1.76 christos module_base_path(module_base, sizeof(module_base), kernel_path); 687 1.30 joerg 688 1.23 ad /* First, see which modules are valid and calculate btinfo size */ 689 1.23 ad len = sizeof(struct btinfo_modulelist); 690 1.23 ad for (bm = boot_modules; bm; bm = bm->bm_next) { 691 1.67 nonaka fd = module_open(bm, 0, kdev, module_base, false); 692 1.23 ad if (fd == -1) { 693 1.23 ad bm->bm_len = -1; 694 1.41 jmcneill ++nfail; 695 1.23 ad continue; 696 1.23 ad } 697 1.23 ad err = fstat(fd, &st); 698 1.24 ad if (err == -1 || st.st_size == -1) { 699 1.28 chris printf("WARNING: couldn't stat %s\n", bm->bm_path); 700 1.23 ad close(fd); 701 1.23 ad bm->bm_len = -1; 702 1.41 jmcneill ++nfail; 703 1.23 ad continue; 704 1.23 ad } 705 1.23 ad bm->bm_len = st.st_size; 706 1.23 ad close(fd); 707 1.23 ad len += sizeof(struct bi_modulelist_entry); 708 1.23 ad } 709 1.23 ad 710 1.23 ad /* Allocate the module list */ 711 1.23 ad btinfo_modulelist = alloc(len); 712 1.23 ad if (btinfo_modulelist == NULL) { 713 1.23 ad printf("WARNING: couldn't allocate module list\n"); 714 1.43 tsutsui wait_sec(MODULE_WARNING_SEC); 715 1.23 ad return; 716 1.23 ad } 717 1.23 ad memset(btinfo_modulelist, 0, len); 718 1.23 ad btinfo_modulelist_size = len; 719 1.23 ad 720 1.23 ad /* Fill in btinfo structure */ 721 1.23 ad buf = (char *)btinfo_modulelist; 722 1.23 ad btinfo_modulelist->num = 0; 723 1.23 ad off = sizeof(struct btinfo_modulelist); 724 1.23 ad 725 1.23 ad for (bm = boot_modules; bm; bm = bm->bm_next) { 726 1.23 ad if (bm->bm_len == -1) 727 1.23 ad continue; 728 1.67 nonaka fd = module_open(bm, 0, kdev, module_base, true); 729 1.41 jmcneill if (fd == -1) 730 1.23 ad continue; 731 1.24 ad image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 732 1.52 jakllsch len = pread(fd, (void *)(uintptr_t)image_end, SSIZE_MAX); 733 1.24 ad if (len < bm->bm_len) { 734 1.40 ad if ((howto & AB_SILENT) != 0) 735 1.40 ad printf("Loading %s ", bm->bm_path); 736 1.23 ad printf(" FAILED\n"); 737 1.23 ad } else { 738 1.23 ad btinfo_modulelist->num++; 739 1.23 ad bi = (struct bi_modulelist_entry *)(buf + off); 740 1.23 ad off += sizeof(struct bi_modulelist_entry); 741 1.23 ad strncpy(bi->path, bm->bm_path, sizeof(bi->path) - 1); 742 1.24 ad bi->base = image_end; 743 1.24 ad bi->len = len; 744 1.49 tls switch (bm->bm_type) { 745 1.49 tls case BM_TYPE_KMOD: 746 1.49 tls bi->type = BI_MODULE_ELF; 747 1.49 tls break; 748 1.49 tls case BM_TYPE_IMAGE: 749 1.49 tls bi->type = BI_MODULE_IMAGE; 750 1.49 tls break; 751 1.51 jmcneill case BM_TYPE_FS: 752 1.51 jmcneill bi->type = BI_MODULE_FS; 753 1.51 jmcneill break; 754 1.49 tls case BM_TYPE_RND: 755 1.49 tls default: 756 1.49 tls /* safest -- rnd checks the sha1 */ 757 1.49 tls bi->type = BI_MODULE_RND; 758 1.49 tls break; 759 1.49 tls } 760 1.40 ad if ((howto & AB_SILENT) == 0) 761 1.40 ad printf(" \n"); 762 1.23 ad } 763 1.24 ad if (len > 0) 764 1.24 ad image_end += len; 765 1.23 ad close(fd); 766 1.23 ad } 767 1.23 ad btinfo_modulelist->endpa = image_end; 768 1.41 jmcneill 769 1.41 jmcneill if (nfail > 0) { 770 1.41 jmcneill printf("WARNING: %d module%s failed to load\n", 771 1.41 jmcneill nfail, nfail == 1 ? "" : "s"); 772 1.41 jmcneill #if notyet 773 1.43 tsutsui wait_sec(MODULE_WARNING_SEC); 774 1.41 jmcneill #endif 775 1.41 jmcneill } 776 1.23 ad } 777 1.33 joerg 778 1.47 uebayasi static void 779 1.47 uebayasi userconf_init(void) 780 1.47 uebayasi { 781 1.47 uebayasi size_t count, len; 782 1.47 uebayasi userconf_command_t *uc; 783 1.47 uebayasi char *buf; 784 1.47 uebayasi off_t off; 785 1.47 uebayasi 786 1.47 uebayasi /* Calculate the userconf commands list size */ 787 1.47 uebayasi count = 0; 788 1.47 uebayasi for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) 789 1.47 uebayasi count++; 790 1.55 jakllsch len = sizeof(*btinfo_userconfcommands) + 791 1.47 uebayasi count * sizeof(struct bi_userconfcommand); 792 1.47 uebayasi 793 1.47 uebayasi /* Allocate the userconf commands list */ 794 1.47 uebayasi btinfo_userconfcommands = alloc(len); 795 1.47 uebayasi if (btinfo_userconfcommands == NULL) { 796 1.47 uebayasi printf("WARNING: couldn't allocate userconf commands list\n"); 797 1.47 uebayasi return; 798 1.47 uebayasi } 799 1.47 uebayasi memset(btinfo_userconfcommands, 0, len); 800 1.47 uebayasi btinfo_userconfcommands_size = len; 801 1.47 uebayasi 802 1.47 uebayasi /* Fill in btinfo structure */ 803 1.47 uebayasi buf = (char *)btinfo_userconfcommands; 804 1.47 uebayasi off = sizeof(*btinfo_userconfcommands); 805 1.47 uebayasi btinfo_userconfcommands->num = 0; 806 1.47 uebayasi for (uc = userconf_commands; uc != NULL; uc = uc->uc_next) { 807 1.47 uebayasi struct bi_userconfcommand *bi; 808 1.47 uebayasi bi = (struct bi_userconfcommand *)(buf + off); 809 1.47 uebayasi strncpy(bi->text, uc->uc_text, sizeof(bi->text) - 1); 810 1.47 uebayasi 811 1.47 uebayasi off += sizeof(*bi); 812 1.47 uebayasi btinfo_userconfcommands->num++; 813 1.47 uebayasi } 814 1.47 uebayasi } 815 1.47 uebayasi 816 1.33 joerg int 817 1.33 joerg exec_multiboot(const char *file, char *args) 818 1.33 joerg { 819 1.74 manu physaddr_t loadaddr = 0; 820 1.62 maxv u_long marks[MARK_MAX]; 821 1.62 maxv u_long extmem; 822 1.62 maxv u_long basemem; 823 1.74 manu struct multiboot_package *mbp = NULL; 824 1.33 joerg 825 1.74 manu #ifndef NO_MULTIBOOT2 826 1.74 manu if ((mbp = probe_multiboot2(file)) != NULL) 827 1.74 manu goto is_multiboot; 828 1.74 manu #endif 829 1.33 joerg 830 1.74 manu if ((mbp = probe_multiboot1(file)) != NULL) { 831 1.74 manu #ifdef EFIBOOT 832 1.74 manu printf("EFI boot requires multiboot 2 kernel\n"); 833 1.33 joerg goto out; 834 1.74 manu #else 835 1.74 manu goto is_multiboot; 836 1.74 manu #endif 837 1.74 manu } 838 1.33 joerg 839 1.74 manu #ifndef NO_MULTIBOOT2 840 1.74 manu printf("%s is not a multiboot kernel\n", file); 841 1.74 manu #else 842 1.74 manu printf("%s is not a multiboot 1 kernel " 843 1.74 manu "(multiboot 2 support is not built in)\n", file); 844 1.74 manu #endif 845 1.74 manu goto out; 846 1.33 joerg 847 1.74 manu is_multiboot: 848 1.74 manu #ifdef EFIBOOT 849 1.74 manu loadaddr = efi_loadaddr; 850 1.74 manu #endif 851 1.74 manu if (common_load_kernel(file, &basemem, &extmem, loadaddr, 0, marks)) 852 1.74 manu goto out; 853 1.33 joerg 854 1.74 manu if (boot_modules_enabled) 855 1.41 jmcneill module_init(file); 856 1.33 joerg 857 1.74 manu mbp->mbp_args = args; 858 1.74 manu mbp->mbp_basemem = basemem; 859 1.74 manu mbp->mbp_extmem = extmem; 860 1.74 manu mbp->mbp_loadaddr = loadaddr; 861 1.74 manu mbp->mbp_marks = marks; 862 1.33 joerg 863 1.74 manu /* Only returns on error */ 864 1.74 manu (void)mbp->mbp_exec(mbp); 865 1.33 joerg 866 1.33 joerg out: 867 1.74 manu if (mbp != NULL) 868 1.74 manu mbp->mbp_cleanup(mbp); 869 1.74 manu 870 1.33 joerg return -1; 871 1.33 joerg } 872 1.40 ad 873 1.40 ad void 874 1.40 ad x86_progress(const char *fmt, ...) 875 1.40 ad { 876 1.40 ad va_list ap; 877 1.40 ad 878 1.40 ad if ((howto & AB_SILENT) != 0) 879 1.40 ad return; 880 1.40 ad va_start(ap, fmt); 881 1.40 ad vprintf(fmt, ap); 882 1.40 ad va_end(ap); 883 1.40 ad } 884