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