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