1 /*- 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 */ 15 16 #include <sys/cdefs.h> 17 __FBSDID("$FreeBSD$"); 18 19 #include <sys/param.h> 20 #include <sys/gpt.h> 21 #include <sys/dirent.h> 22 #include <sys/reboot.h> 23 24 #include <machine/bootinfo.h> 25 #include <machine/elf.h> 26 #include <machine/pc/bios.h> 27 #include <machine/psl.h> 28 29 #include <stdarg.h> 30 31 #include <a.out.h> 32 33 #include <btxv86.h> 34 35 /* Forward declared to avoid warnings -- these shouldn't be needed */ 36 int strcasecmp(const char *s1, const char *s2); 37 void explicit_bzero(void *b, size_t len); 38 39 #include "bootargs.h" 40 #include "lib.h" 41 #include "rbx.h" 42 #include "drv.h" 43 #include "util.h" 44 #include "cons.h" 45 #include "gpt.h" 46 #include "paths.h" 47 48 #define ARGS 0x900 49 #define NOPT 14 50 #define NDEV 3 51 #define MEM_BASE 0x12 52 #define MEM_EXT 0x15 53 54 #define DRV_HARD 0x80 55 #define DRV_MASK 0x7f 56 57 #define TYPE_AD 0 58 #define TYPE_DA 1 59 #define TYPE_MAXHARD TYPE_DA 60 #define TYPE_FD 2 61 62 extern uint32_t _end; 63 64 static const uuid_t freebsd_ufs_uuid = GPT_ENT_TYPE_FREEBSD_UFS; 65 static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ 66 static const unsigned char flags[NOPT] = { 67 RBX_DUAL, 68 RBX_SERIAL, 69 RBX_ASKNAME, 70 RBX_CDROM, 71 RBX_CONFIG, 72 RBX_KDB, 73 RBX_GDB, 74 RBX_MUTE, 75 RBX_NOINTR, 76 RBX_PAUSE, 77 RBX_QUIET, 78 RBX_DFLTROOT, 79 RBX_SINGLE, 80 RBX_VERBOSE 81 }; 82 uint32_t opts; 83 84 static const char *const dev_nm[NDEV] = {"ad", "da", "fd"}; 85 static const unsigned char dev_maj[NDEV] = {30, 4, 2}; 86 87 static struct dsk dsk; 88 static char kname[1024]; 89 static int comspeed = SIOSPD; 90 static struct bootinfo bootinfo; 91 #ifdef LOADER_GELI_SUPPORT 92 static struct geli_boot_args geliargs; 93 #endif 94 95 static vm_offset_t high_heap_base; 96 static uint32_t bios_basemem, bios_extmem, high_heap_size; 97 98 static struct bios_smap smap; 99 100 /* 101 * The minimum amount of memory to reserve in bios_extmem for the heap. 102 */ 103 #define HEAP_MIN (3 * 1024 * 1024) 104 105 static char *heap_next; 106 static char *heap_end; 107 108 void exit(int); 109 static void load(void); 110 static int parse_cmds(char *, int *); 111 static int dskread(void *, daddr_t, unsigned); 112 void *malloc(size_t n); 113 void free(void *ptr); 114 #ifdef LOADER_GELI_SUPPORT 115 static int vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, 116 size_t bytes); 117 #endif 118 119 void * 120 malloc(size_t n) 121 { 122 char *p = heap_next; 123 if (p + n > heap_end) { 124 printf("malloc failure\n"); 125 for (;;) 126 ; 127 /* NOTREACHED */ 128 return (0); 129 } 130 heap_next += n; 131 return (p); 132 } 133 134 void 135 free(void *ptr) 136 { 137 138 return; 139 } 140 141 #include "ufsread.c" 142 #include "gpt.c" 143 #ifdef LOADER_GELI_SUPPORT 144 #include "geliboot.c" 145 static char gelipw[GELI_PW_MAXLEN]; 146 static struct keybuf *gelibuf; 147 #endif 148 149 static inline int 150 xfsread(ufs_ino_t inode, void *buf, size_t nbyte) 151 { 152 153 if ((size_t)fsread(inode, buf, nbyte) != nbyte) { 154 printf("Invalid %s\n", "format"); 155 return (-1); 156 } 157 return (0); 158 } 159 160 static void 161 bios_getmem(void) 162 { 163 uint64_t size; 164 165 /* Parse system memory map */ 166 v86.ebx = 0; 167 do { 168 v86.ctl = V86_FLAGS; 169 v86.addr = MEM_EXT; /* int 0x15 function 0xe820*/ 170 v86.eax = 0xe820; 171 v86.ecx = sizeof(struct bios_smap); 172 v86.edx = SMAP_SIG; 173 v86.es = VTOPSEG(&smap); 174 v86.edi = VTOPOFF(&smap); 175 v86int(); 176 if ((v86.efl & 1) || (v86.eax != SMAP_SIG)) 177 break; 178 /* look for a low-memory segment that's large enough */ 179 if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) && 180 (smap.length >= (512 * 1024))) 181 bios_basemem = smap.length; 182 /* look for the first segment in 'extended' memory */ 183 if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) { 184 bios_extmem = smap.length; 185 } 186 187 /* 188 * Look for the largest segment in 'extended' memory beyond 189 * 1MB but below 4GB. 190 */ 191 if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) && 192 (smap.base < 0x100000000ull)) { 193 size = smap.length; 194 195 /* 196 * If this segment crosses the 4GB boundary, truncate it. 197 */ 198 if (smap.base + size > 0x100000000ull) 199 size = 0x100000000ull - smap.base; 200 201 if (size > high_heap_size) { 202 high_heap_size = size; 203 high_heap_base = smap.base; 204 } 205 } 206 } while (v86.ebx != 0); 207 208 /* Fall back to the old compatibility function for base memory */ 209 if (bios_basemem == 0) { 210 v86.ctl = 0; 211 v86.addr = 0x12; /* int 0x12 */ 212 v86int(); 213 214 bios_basemem = (v86.eax & 0xffff) * 1024; 215 } 216 217 /* Fall back through several compatibility functions for extended memory */ 218 if (bios_extmem == 0) { 219 v86.ctl = V86_FLAGS; 220 v86.addr = 0x15; /* int 0x15 function 0xe801*/ 221 v86.eax = 0xe801; 222 v86int(); 223 if (!(v86.efl & 1)) { 224 bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024; 225 } 226 } 227 if (bios_extmem == 0) { 228 v86.ctl = 0; 229 v86.addr = 0x15; /* int 0x15 function 0x88*/ 230 v86.eax = 0x8800; 231 v86int(); 232 bios_extmem = (v86.eax & 0xffff) * 1024; 233 } 234 235 /* 236 * If we have extended memory and did not find a suitable heap 237 * region in the SMAP, use the last 3MB of 'extended' memory as a 238 * high heap candidate. 239 */ 240 if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) { 241 high_heap_size = HEAP_MIN; 242 high_heap_base = bios_extmem + 0x100000 - HEAP_MIN; 243 } 244 } 245 246 static int 247 gptinit(void) 248 { 249 250 if (gptread(&freebsd_ufs_uuid, &dsk, dmadat->secbuf) == -1) { 251 printf("%s: unable to load GPT\n", BOOTPROG); 252 return (-1); 253 } 254 if (gptfind(&freebsd_ufs_uuid, &dsk, dsk.part) == -1) { 255 printf("%s: no UFS partition was found\n", BOOTPROG); 256 return (-1); 257 } 258 #ifdef LOADER_GELI_SUPPORT 259 if (geli_taste(vdev_read, &dsk, (gpttable[curent].ent_lba_end - 260 gpttable[curent].ent_lba_start)) == 0) { 261 if (geli_havekey(&dsk) != 0 && geli_passphrase(gelipw, 262 dsk.unit, 'p', curent + 1, &dsk) != 0) { 263 printf("%s: unable to decrypt GELI key\n", BOOTPROG); 264 return (-1); 265 } 266 } 267 #endif 268 269 dsk_meta = 0; 270 return (0); 271 } 272 273 int main(void); 274 275 int 276 main(void) 277 { 278 char cmd[512], cmdtmp[512]; 279 ssize_t sz; 280 int autoboot, dskupdated; 281 ufs_ino_t ino; 282 283 dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base); 284 285 bios_getmem(); 286 287 if (high_heap_size > 0) { 288 heap_end = PTOV(high_heap_base + high_heap_size); 289 heap_next = PTOV(high_heap_base); 290 } else { 291 heap_next = (char *)dmadat + sizeof(*dmadat); 292 heap_end = (char *)PTOV(bios_basemem); 293 } 294 295 v86.ctl = V86_FLAGS; 296 v86.efl = PSL_RESERVED_DEFAULT | PSL_I; 297 dsk.drive = *(uint8_t *)PTOV(ARGS); 298 dsk.type = dsk.drive & DRV_HARD ? TYPE_AD : TYPE_FD; 299 dsk.unit = dsk.drive & DRV_MASK; 300 dsk.part = -1; 301 dsk.start = 0; 302 bootinfo.bi_version = BOOTINFO_VERSION; 303 bootinfo.bi_size = sizeof(bootinfo); 304 bootinfo.bi_basemem = bios_basemem / 1024; 305 bootinfo.bi_extmem = bios_extmem / 1024; 306 bootinfo.bi_memsizes_valid++; 307 bootinfo.bi_bios_dev = dsk.drive; 308 309 #ifdef LOADER_GELI_SUPPORT 310 geli_init(); 311 #endif 312 /* Process configuration file */ 313 314 if (gptinit() != 0) 315 return (-1); 316 317 autoboot = 1; 318 *cmd = '\0'; 319 320 for (;;) { 321 *kname = '\0'; 322 if ((ino = lookup(PATH_CONFIG)) || 323 (ino = lookup(PATH_DOTCONFIG))) { 324 sz = fsread(ino, cmd, sizeof(cmd) - 1); 325 cmd[(sz < 0) ? 0 : sz] = '\0'; 326 } 327 if (*cmd != '\0') { 328 memcpy(cmdtmp, cmd, sizeof(cmdtmp)); 329 if (parse_cmds(cmdtmp, &dskupdated)) 330 break; 331 if (dskupdated && gptinit() != 0) 332 break; 333 if (!OPT_CHECK(RBX_QUIET)) 334 printf("%s: %s", PATH_CONFIG, cmd); 335 *cmd = '\0'; 336 } 337 338 if (autoboot && keyhit(3)) { 339 if (*kname == '\0') 340 memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER)); 341 break; 342 } 343 autoboot = 0; 344 345 /* 346 * Try to exec stage 3 boot loader. If interrupted by a 347 * keypress, or in case of failure, try to load a kernel 348 * directly instead. 349 */ 350 if (*kname != '\0') 351 load(); 352 memcpy(kname, PATH_LOADER, sizeof(PATH_LOADER)); 353 load(); 354 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 355 load(); 356 gptbootfailed(&dsk); 357 if (gptfind(&freebsd_ufs_uuid, &dsk, -1) == -1) 358 break; 359 dsk_meta = 0; 360 } 361 362 /* Present the user with the boot2 prompt. */ 363 364 for (;;) { 365 if (!OPT_CHECK(RBX_QUIET)) { 366 printf("\nFreeBSD/x86 boot\n" 367 "Default: %u:%s(%up%u)%s\n" 368 "boot: ", 369 dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 370 dsk.part, kname); 371 } 372 if (ioctrl & IO_SERIAL) 373 sio_flush(); 374 *cmd = '\0'; 375 if (keyhit(0)) 376 getstr(cmd, sizeof(cmd)); 377 else if (!OPT_CHECK(RBX_QUIET)) 378 putchar('\n'); 379 if (parse_cmds(cmd, &dskupdated)) { 380 putchar('\a'); 381 continue; 382 } 383 if (dskupdated && gptinit() != 0) 384 continue; 385 load(); 386 } 387 /* NOTREACHED */ 388 } 389 390 /* XXX - Needed for btxld to link the boot2 binary; do not remove. */ 391 void 392 exit(int x) 393 { 394 } 395 396 static void 397 load(void) 398 { 399 union { 400 struct exec ex; 401 Elf32_Ehdr eh; 402 } hdr; 403 static Elf32_Phdr ep[2]; 404 static Elf32_Shdr es[2]; 405 caddr_t p; 406 ufs_ino_t ino; 407 uint32_t addr, x; 408 int fmt, i, j; 409 410 if (!(ino = lookup(kname))) { 411 if (!ls) { 412 printf("%s: No %s on %u:%s(%up%u)\n", BOOTPROG, 413 kname, dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit, 414 dsk.part); 415 } 416 return; 417 } 418 if (xfsread(ino, &hdr, sizeof(hdr))) 419 return; 420 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 421 fmt = 0; 422 else if (IS_ELF(hdr.eh)) 423 fmt = 1; 424 else { 425 printf("Invalid %s\n", "format"); 426 return; 427 } 428 if (fmt == 0) { 429 addr = hdr.ex.a_entry & 0xffffff; 430 p = PTOV(addr); 431 fs_off = PAGE_SIZE; 432 if (xfsread(ino, p, hdr.ex.a_text)) 433 return; 434 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 435 if (xfsread(ino, p, hdr.ex.a_data)) 436 return; 437 p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); 438 bootinfo.bi_symtab = VTOP(p); 439 memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 440 p += sizeof(hdr.ex.a_syms); 441 if (hdr.ex.a_syms) { 442 if (xfsread(ino, p, hdr.ex.a_syms)) 443 return; 444 p += hdr.ex.a_syms; 445 if (xfsread(ino, p, sizeof(int))) 446 return; 447 x = *(uint32_t *)p; 448 p += sizeof(int); 449 x -= sizeof(int); 450 if (xfsread(ino, p, x)) 451 return; 452 p += x; 453 } 454 } else { 455 fs_off = hdr.eh.e_phoff; 456 for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { 457 if (xfsread(ino, ep + j, sizeof(ep[0]))) 458 return; 459 if (ep[j].p_type == PT_LOAD) 460 j++; 461 } 462 for (i = 0; i < 2; i++) { 463 p = PTOV(ep[i].p_paddr & 0xffffff); 464 fs_off = ep[i].p_offset; 465 if (xfsread(ino, p, ep[i].p_filesz)) 466 return; 467 } 468 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 469 bootinfo.bi_symtab = VTOP(p); 470 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 471 fs_off = hdr.eh.e_shoff + sizeof(es[0]) * 472 (hdr.eh.e_shstrndx + 1); 473 if (xfsread(ino, &es, sizeof(es))) 474 return; 475 for (i = 0; i < 2; i++) { 476 memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); 477 p += sizeof(es[i].sh_size); 478 fs_off = es[i].sh_offset; 479 if (xfsread(ino, p, es[i].sh_size)) 480 return; 481 p += es[i].sh_size; 482 } 483 } 484 addr = hdr.eh.e_entry & 0xffffff; 485 } 486 bootinfo.bi_esymtab = VTOP(p); 487 bootinfo.bi_kernelname = VTOP(kname); 488 bootinfo.bi_bios_dev = dsk.drive; 489 #ifdef LOADER_GELI_SUPPORT 490 geliargs.size = sizeof(geliargs); 491 explicit_bzero(gelipw, sizeof(gelipw)); 492 gelibuf = malloc(sizeof(struct keybuf) + (GELI_MAX_KEYS * sizeof(struct keybuf_ent))); 493 geli_fill_keybuf(gelibuf); 494 geliargs.notapw = '\0'; 495 geliargs.keybuf_sentinel = KEYBUF_SENTINEL; 496 geliargs.keybuf = gelibuf; 497 #endif 498 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), 499 MAKEBOOTDEV(dev_maj[dsk.type], dsk.part + 1, dsk.unit, 0xff), 500 KARGS_FLAGS_EXTARG, 0, 0, VTOP(&bootinfo) 501 #ifdef LOADER_GELI_SUPPORT 502 , geliargs 503 #endif 504 ); 505 } 506 507 static int 508 parse_cmds(char *cmdstr, int *dskupdated) 509 { 510 char *arg = cmdstr; 511 char *ep, *p, *q; 512 const char *cp; 513 unsigned int drv; 514 int c, i, j; 515 516 *dskupdated = 0; 517 while ((c = *arg++)) { 518 if (c == ' ' || c == '\t' || c == '\n') 519 continue; 520 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); 521 ep = p; 522 if (*p) 523 *p++ = 0; 524 if (c == '-') { 525 while ((c = *arg++)) { 526 if (c == 'P') { 527 if (*(uint8_t *)PTOV(0x496) & 0x10) { 528 cp = "yes"; 529 } else { 530 opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL); 531 cp = "no"; 532 } 533 printf("Keyboard: %s\n", cp); 534 continue; 535 } else if (c == 'S') { 536 j = 0; 537 while ((unsigned int)(i = *arg++ - '0') <= 9) 538 j = j * 10 + i; 539 if (j > 0 && i == -'0') { 540 comspeed = j; 541 break; 542 } 543 /* Fall through to error below ('S' not in optstr[]). */ 544 } 545 for (i = 0; c != optstr[i]; i++) 546 if (i == NOPT - 1) 547 return -1; 548 opts ^= OPT_SET(flags[i]); 549 } 550 ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : 551 OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; 552 if (ioctrl & IO_SERIAL) { 553 if (sio_init(115200 / comspeed) != 0) 554 ioctrl &= ~IO_SERIAL; 555 } 556 } else { 557 for (q = arg--; *q && *q != '('; q++); 558 if (*q) { 559 drv = -1; 560 if (arg[1] == ':') { 561 drv = *arg - '0'; 562 if (drv > 9) 563 return (-1); 564 arg += 2; 565 } 566 if (q - arg != 2) 567 return -1; 568 for (i = 0; arg[0] != dev_nm[i][0] || 569 arg[1] != dev_nm[i][1]; i++) 570 if (i == NDEV - 1) 571 return -1; 572 dsk.type = i; 573 arg += 3; 574 dsk.unit = *arg - '0'; 575 if (arg[1] != 'p' || dsk.unit > 9) 576 return -1; 577 arg += 2; 578 dsk.part = *arg - '0'; 579 if (dsk.part < 1 || dsk.part > 9) 580 return -1; 581 arg++; 582 if (arg[0] != ')') 583 return -1; 584 arg++; 585 if (drv == -1) 586 drv = dsk.unit; 587 dsk.drive = (dsk.type <= TYPE_MAXHARD 588 ? DRV_HARD : 0) + drv; 589 *dskupdated = 1; 590 } 591 if ((i = ep - arg)) { 592 if ((size_t)i >= sizeof(kname)) 593 return -1; 594 memcpy(kname, arg, i + 1); 595 } 596 } 597 arg = p; 598 } 599 return 0; 600 } 601 602 static int 603 dskread(void *buf, daddr_t lba, unsigned nblk) 604 { 605 int err; 606 607 err = drvread(&dsk, buf, lba + dsk.start, nblk); 608 609 #ifdef LOADER_GELI_SUPPORT 610 if (err == 0 && is_geli(&dsk) == 0) { 611 /* Decrypt */ 612 if (geli_read(&dsk, lba * DEV_BSIZE, buf, nblk * DEV_BSIZE)) 613 return (err); 614 } 615 #endif 616 617 return (err); 618 } 619 620 #ifdef LOADER_GELI_SUPPORT 621 /* 622 * Read function compartible with the ZFS callback, required to keep the GELI 623 * Implementation the same for both UFS and ZFS 624 */ 625 static int 626 vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, size_t bytes) 627 { 628 char *p; 629 daddr_t lba; 630 unsigned int nb; 631 struct dsk *dskp = (struct dsk *) priv; 632 633 if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1))) 634 return (-1); 635 636 p = buf; 637 lba = off / DEV_BSIZE; 638 lba += dskp->start; 639 640 while (bytes > 0) { 641 nb = bytes / DEV_BSIZE; 642 if (nb > VBLKSIZE / DEV_BSIZE) 643 nb = VBLKSIZE / DEV_BSIZE; 644 if (drvread(dskp, dmadat->blkbuf, lba, nb)) 645 return (-1); 646 memcpy(p, dmadat->blkbuf, nb * DEV_BSIZE); 647 p += nb * DEV_BSIZE; 648 lba += nb; 649 bytes -= nb * DEV_BSIZE; 650 } 651 652 return (0); 653 } 654 #endif /* LOADER_GELI_SUPPORT */ 655