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