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