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