zfsboot.c revision 299660
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: head/sys/boot/i386/zfsboot/zfsboot.c 299660 2016-05-13 11:20:21Z ngie $"); 18 19#include <sys/param.h> 20#include <sys/errno.h> 21#include <sys/diskmbr.h> 22#ifdef GPT 23#include <sys/gpt.h> 24#endif 25#include <sys/reboot.h> 26#include <sys/queue.h> 27 28#include <machine/bootinfo.h> 29#include <machine/elf.h> 30#include <machine/pc/bios.h> 31 32#include <stdarg.h> 33#include <stddef.h> 34 35#include <a.out.h> 36 37#include <btxv86.h> 38 39#include "lib.h" 40#include "rbx.h" 41#include "drv.h" 42#include "util.h" 43#include "cons.h" 44#include "bootargs.h" 45#include "paths.h" 46 47#include "libzfs.h" 48 49#define ARGS 0x900 50#define NOPT 14 51#define NDEV 3 52 53#define BIOS_NUMDRIVES 0x475 54#define DRV_HARD 0x80 55#define DRV_MASK 0x7f 56 57#define TYPE_AD 0 58#define TYPE_DA 1 59#define TYPE_MAXHARD TYPE_DA 60#define TYPE_FD 2 61 62#define DEV_GELIBOOT_BSIZE 4096 63 64extern uint32_t _end; 65 66#ifdef GPT 67static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS; 68#endif 69static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ 70static const unsigned char flags[NOPT] = { 71 RBX_DUAL, 72 RBX_SERIAL, 73 RBX_ASKNAME, 74 RBX_CDROM, 75 RBX_CONFIG, 76 RBX_KDB, 77 RBX_GDB, 78 RBX_MUTE, 79 RBX_NOINTR, 80 RBX_PAUSE, 81 RBX_QUIET, 82 RBX_DFLTROOT, 83 RBX_SINGLE, 84 RBX_VERBOSE 85}; 86uint32_t opts; 87 88static const unsigned char dev_maj[NDEV] = {30, 4, 2}; 89 90static char cmd[512]; 91static char cmddup[512]; 92static char kname[1024]; 93static char rootname[256]; 94static int comspeed = SIOSPD; 95static struct bootinfo bootinfo; 96static uint32_t bootdev; 97static struct zfs_boot_args zfsargs; 98static struct zfsmount zfsmount; 99 100vm_offset_t high_heap_base; 101uint32_t bios_basemem, bios_extmem, high_heap_size; 102 103static struct bios_smap smap; 104 105/* 106 * The minimum amount of memory to reserve in bios_extmem for the heap. 107 */ 108#define HEAP_MIN (3 * 1024 * 1024) 109 110static char *heap_next; 111static char *heap_end; 112 113/* Buffers that must not span a 64k boundary. */ 114#define READ_BUF_SIZE 8192 115struct dmadat { 116 char rdbuf[READ_BUF_SIZE]; /* for reading large things */ 117 char secbuf[READ_BUF_SIZE]; /* for MBR/disklabel */ 118}; 119static struct dmadat *dmadat; 120 121void exit(int); 122static void load(void); 123static int parse(void); 124static void bios_getmem(void); 125void *malloc(size_t n); 126void free(void *ptr); 127 128void * 129malloc(size_t n) 130{ 131 char *p = heap_next; 132 if (p + n > heap_end) { 133 printf("malloc failure\n"); 134 for (;;) 135 ; 136 /* NOTREACHED */ 137 return (0); 138 } 139 heap_next += n; 140 return (p); 141} 142 143void 144free(void *ptr) 145{ 146 147 return; 148} 149 150static char * 151strdup(const char *s) 152{ 153 char *p = malloc(strlen(s) + 1); 154 strcpy(p, s); 155 return (p); 156} 157 158#ifdef LOADER_GELI_SUPPORT 159#include "geliboot.c" 160static char gelipw[GELI_PW_MAXLEN]; 161#endif 162 163#include "zfsimpl.c" 164 165/* 166 * Read from a dnode (which must be from a ZPL filesystem). 167 */ 168static int 169zfs_read(spa_t *spa, const dnode_phys_t *dnode, off_t *offp, void *start, size_t size) 170{ 171 const znode_phys_t *zp = (const znode_phys_t *) dnode->dn_bonus; 172 size_t n; 173 int rc; 174 175 n = size; 176 if (*offp + n > zp->zp_size) 177 n = zp->zp_size - *offp; 178 179 rc = dnode_read(spa, dnode, *offp, start, n); 180 if (rc) 181 return (-1); 182 *offp += n; 183 184 return (n); 185} 186 187/* 188 * Current ZFS pool 189 */ 190static spa_t *spa; 191static spa_t *primary_spa; 192static vdev_t *primary_vdev; 193 194/* 195 * A wrapper for dskread that doesn't have to worry about whether the 196 * buffer pointer crosses a 64k boundary. 197 */ 198static int 199vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) 200{ 201 char *p; 202 daddr_t lba, alignlba; 203 off_t alignoff, diff; 204 unsigned int nb, alignnb; 205 struct dsk *dsk = (struct dsk *) priv; 206 207 if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1))) 208 return -1; 209 210 p = buf; 211 lba = off / DEV_BSIZE; 212 lba += dsk->start; 213 /* Align reads to 4k else 4k sector GELIs will not decrypt. */ 214 alignoff = off & ~ (off_t)(DEV_GELIBOOT_BSIZE - 1); 215 /* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes. */ 216 alignlba = alignoff / DEV_BSIZE; 217 /* 218 * The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the 219 * start of the GELI partition, not the start of the actual disk. 220 */ 221 alignlba += dsk->start; 222 diff = (lba - alignlba) * DEV_BSIZE; 223 224 while (bytes > 0) { 225 nb = bytes / DEV_BSIZE; 226 /* 227 * Ensure that the read size plus the leading offset does not 228 * exceed the size of the read buffer. 229 */ 230 if (nb > (READ_BUF_SIZE - diff) / DEV_BSIZE) 231 nb = (READ_BUF_SIZE - diff) / DEV_BSIZE; 232 /* 233 * Round the number of blocks to read up to the nearest multiple 234 * of DEV_GELIBOOT_BSIZE. 235 */ 236 alignnb = roundup2(nb * DEV_BSIZE + diff, DEV_GELIBOOT_BSIZE) 237 / DEV_BSIZE; 238 239 if (drvread(dsk, dmadat->rdbuf, alignlba, alignnb)) 240 return -1; 241#ifdef LOADER_GELI_SUPPORT 242 /* decrypt */ 243 if (is_geli(dsk) == 0) { 244 if (geli_read(dsk, ((alignlba - dsk->start) * 245 DEV_BSIZE), dmadat->rdbuf, alignnb * DEV_BSIZE)) 246 return (-1); 247 } 248#endif 249 memcpy(p, dmadat->rdbuf + diff, nb * DEV_BSIZE); 250 p += nb * DEV_BSIZE; 251 lba += nb; 252 alignlba += alignnb; 253 bytes -= nb * DEV_BSIZE; 254 /* Don't need the leading offset after the first block. */ 255 diff = 0; 256 } 257 258 return 0; 259} 260 261static int 262xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte) 263{ 264 if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) { 265 printf("Invalid format\n"); 266 return -1; 267 } 268 return 0; 269} 270 271static void 272bios_getmem(void) 273{ 274 uint64_t size; 275 276 /* Parse system memory map */ 277 v86.ebx = 0; 278 do { 279 v86.ctl = V86_FLAGS; 280 v86.addr = 0x15; /* int 0x15 function 0xe820*/ 281 v86.eax = 0xe820; 282 v86.ecx = sizeof(struct bios_smap); 283 v86.edx = SMAP_SIG; 284 v86.es = VTOPSEG(&smap); 285 v86.edi = VTOPOFF(&smap); 286 v86int(); 287 if (V86_CY(v86.efl) || (v86.eax != SMAP_SIG)) 288 break; 289 /* look for a low-memory segment that's large enough */ 290 if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) && 291 (smap.length >= (512 * 1024))) 292 bios_basemem = smap.length; 293 /* look for the first segment in 'extended' memory */ 294 if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) { 295 bios_extmem = smap.length; 296 } 297 298 /* 299 * Look for the largest segment in 'extended' memory beyond 300 * 1MB but below 4GB. 301 */ 302 if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) && 303 (smap.base < 0x100000000ull)) { 304 size = smap.length; 305 306 /* 307 * If this segment crosses the 4GB boundary, truncate it. 308 */ 309 if (smap.base + size > 0x100000000ull) 310 size = 0x100000000ull - smap.base; 311 312 if (size > high_heap_size) { 313 high_heap_size = size; 314 high_heap_base = smap.base; 315 } 316 } 317 } while (v86.ebx != 0); 318 319 /* Fall back to the old compatibility function for base memory */ 320 if (bios_basemem == 0) { 321 v86.ctl = 0; 322 v86.addr = 0x12; /* int 0x12 */ 323 v86int(); 324 325 bios_basemem = (v86.eax & 0xffff) * 1024; 326 } 327 328 /* Fall back through several compatibility functions for extended memory */ 329 if (bios_extmem == 0) { 330 v86.ctl = V86_FLAGS; 331 v86.addr = 0x15; /* int 0x15 function 0xe801*/ 332 v86.eax = 0xe801; 333 v86int(); 334 if (!V86_CY(v86.efl)) { 335 bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024; 336 } 337 } 338 if (bios_extmem == 0) { 339 v86.ctl = 0; 340 v86.addr = 0x15; /* int 0x15 function 0x88*/ 341 v86.eax = 0x8800; 342 v86int(); 343 bios_extmem = (v86.eax & 0xffff) * 1024; 344 } 345 346 /* 347 * If we have extended memory and did not find a suitable heap 348 * region in the SMAP, use the last 3MB of 'extended' memory as a 349 * high heap candidate. 350 */ 351 if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) { 352 high_heap_size = HEAP_MIN; 353 high_heap_base = bios_extmem + 0x100000 - HEAP_MIN; 354 } 355} 356 357/* 358 * Try to detect a device supported by the legacy int13 BIOS 359 */ 360static int 361int13probe(int drive) 362{ 363 v86.ctl = V86_FLAGS; 364 v86.addr = 0x13; 365 v86.eax = 0x800; 366 v86.edx = drive; 367 v86int(); 368 369 if (!V86_CY(v86.efl) && /* carry clear */ 370 ((v86.edx & 0xff) != (drive & DRV_MASK))) { /* unit # OK */ 371 if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */ 372 return(0); /* skip device */ 373 } 374 return (1); 375 } 376 return(0); 377} 378 379/* 380 * We call this when we find a ZFS vdev - ZFS consumes the dsk 381 * structure so we must make a new one. 382 */ 383static struct dsk * 384copy_dsk(struct dsk *dsk) 385{ 386 struct dsk *newdsk; 387 388 newdsk = malloc(sizeof(struct dsk)); 389 *newdsk = *dsk; 390 return (newdsk); 391} 392 393static void 394probe_drive(struct dsk *dsk) 395{ 396#ifdef GPT 397 struct gpt_hdr hdr; 398 struct gpt_ent *ent; 399 unsigned part, entries_per_sec; 400#endif 401#ifdef LOADER_GELI_SUPPORT 402 daddr_t slba, elba; 403#endif 404 struct dos_partition *dp; 405 char *sec; 406 unsigned i; 407 408 /* 409 * If we find a vdev on the whole disk, stop here. 410 */ 411 if (vdev_probe(vdev_read, dsk, NULL) == 0) 412 return; 413 414#ifdef LOADER_GELI_SUPPORT 415 /* 416 * Taste the disk, if it is GELI encrypted, decrypt it and check to see if 417 * it is a usable vdev then. Otherwise dig 418 * out the partition table and probe each slice/partition 419 * in turn for a vdev or GELI encrypted vdev. 420 */ 421 elba = drvsize(dsk); 422 if (elba > 0) { 423 elba--; 424 } 425 if (geli_taste(vdev_read, dsk, elba) == 0) { 426 if (geli_passphrase(&gelipw, dsk->unit, ':', 0, dsk) == 0) { 427 if (vdev_probe(vdev_read, dsk, NULL) == 0) { 428 return; 429 } 430 } 431 } 432#endif /* LOADER_GELI_SUPPORT */ 433 434 sec = dmadat->secbuf; 435 dsk->start = 0; 436 437#ifdef GPT 438 /* 439 * First check for GPT. 440 */ 441 if (drvread(dsk, sec, 1, 1)) { 442 return; 443 } 444 memcpy(&hdr, sec, sizeof(hdr)); 445 if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 || 446 hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || 447 hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { 448 goto trymbr; 449 } 450 451 /* 452 * Probe all GPT partitions for the presence of ZFS pools. We 453 * return the spa_t for the first we find (if requested). This 454 * will have the effect of booting from the first pool on the 455 * disk. 456 * 457 * If no vdev is found, GELI decrypting the device and try again 458 */ 459 entries_per_sec = DEV_BSIZE / hdr.hdr_entsz; 460 slba = hdr.hdr_lba_table; 461 elba = slba + hdr.hdr_entries / entries_per_sec; 462 while (slba < elba) { 463 dsk->start = 0; 464 if (drvread(dsk, sec, slba, 1)) 465 return; 466 for (part = 0; part < entries_per_sec; part++) { 467 ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz); 468 if (memcmp(&ent->ent_type, &freebsd_zfs_uuid, 469 sizeof(uuid_t)) == 0) { 470 dsk->start = ent->ent_lba_start; 471 dsk->slice = part + 1; 472 dsk->part = 255; 473 if (vdev_probe(vdev_read, dsk, NULL) == 0) { 474 /* 475 * This slice had a vdev. We need a new dsk 476 * structure now since the vdev now owns this one. 477 */ 478 dsk = copy_dsk(dsk); 479 } 480#ifdef LOADER_GELI_SUPPORT 481 else if (geli_taste(vdev_read, dsk, ent->ent_lba_end - 482 ent->ent_lba_start) == 0) { 483 if (geli_passphrase(&gelipw, dsk->unit, 'p', dsk->slice, dsk) == 0) { 484 /* 485 * This slice has GELI, check it for ZFS. 486 */ 487 if (vdev_probe(vdev_read, dsk, NULL) == 0) { 488 /* 489 * This slice had a vdev. We need a new dsk 490 * structure now since the vdev now owns this one. 491 */ 492 dsk = copy_dsk(dsk); 493 } 494 break; 495 } 496 } 497#endif /* LOADER_GELI_SUPPORT */ 498 } 499 } 500 slba++; 501 } 502 return; 503trymbr: 504#endif /* GPT */ 505 506 if (drvread(dsk, sec, DOSBBSECTOR, 1)) 507 return; 508 dp = (void *)(sec + DOSPARTOFF); 509 510 for (i = 0; i < NDOSPART; i++) { 511 if (!dp[i].dp_typ) 512 continue; 513 dsk->start = dp[i].dp_start; 514 dsk->slice = i + 1; 515 if (vdev_probe(vdev_read, dsk, NULL) == 0) { 516 dsk = copy_dsk(dsk); 517 } 518#ifdef LOADER_GELI_SUPPORT 519 else if (geli_taste(vdev_read, dsk, dp[i].dp_size - 520 dp[i].dp_start) == 0) { 521 if (geli_passphrase(&gelipw, dsk->unit, 's', i, dsk) == 0) { 522 /* 523 * This slice has GELI, check it for ZFS. 524 */ 525 if (vdev_probe(vdev_read, dsk, NULL) == 0) { 526 /* 527 * This slice had a vdev. We need a new dsk 528 * structure now since the vdev now owns this one. 529 */ 530 dsk = copy_dsk(dsk); 531 } 532 break; 533 } 534 } 535#endif /* LOADER_GELI_SUPPORT */ 536 } 537} 538 539int 540main(void) 541{ 542 int autoboot, i; 543 dnode_phys_t dn; 544 off_t off; 545 struct dsk *dsk; 546 547 dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base); 548 549 bios_getmem(); 550 551 if (high_heap_size > 0) { 552 heap_end = PTOV(high_heap_base + high_heap_size); 553 heap_next = PTOV(high_heap_base); 554 } else { 555 heap_next = (char *)dmadat + sizeof(*dmadat); 556 heap_end = (char *)PTOV(bios_basemem); 557 } 558 559 dsk = malloc(sizeof(struct dsk)); 560 dsk->drive = *(uint8_t *)PTOV(ARGS); 561 dsk->type = dsk->drive & DRV_HARD ? TYPE_AD : TYPE_FD; 562 dsk->unit = dsk->drive & DRV_MASK; 563 dsk->slice = *(uint8_t *)PTOV(ARGS + 1) + 1; 564 dsk->part = 0; 565 dsk->start = 0; 566 dsk->init = 0; 567 568 bootinfo.bi_version = BOOTINFO_VERSION; 569 bootinfo.bi_size = sizeof(bootinfo); 570 bootinfo.bi_basemem = bios_basemem / 1024; 571 bootinfo.bi_extmem = bios_extmem / 1024; 572 bootinfo.bi_memsizes_valid++; 573 bootinfo.bi_bios_dev = dsk->drive; 574 575 bootdev = MAKEBOOTDEV(dev_maj[dsk->type], 576 dsk->slice, dsk->unit, dsk->part), 577 578 /* Process configuration file */ 579 580 autoboot = 1; 581 582#ifdef LOADER_GELI_SUPPORT 583 geli_init(); 584#endif 585 zfs_init(); 586 587 /* 588 * Probe the boot drive first - we will try to boot from whatever 589 * pool we find on that drive. 590 */ 591 probe_drive(dsk); 592 593 /* 594 * Probe the rest of the drives that the bios knows about. This 595 * will find any other available pools and it may fill in missing 596 * vdevs for the boot pool. 597 */ 598#ifndef VIRTUALBOX 599 for (i = 0; i < *(unsigned char *)PTOV(BIOS_NUMDRIVES); i++) 600#else 601 for (i = 0; i < MAXBDDEV; i++) 602#endif 603 { 604 if ((i | DRV_HARD) == *(uint8_t *)PTOV(ARGS)) 605 continue; 606 607 if (!int13probe(i | DRV_HARD)) 608 break; 609 610 dsk = malloc(sizeof(struct dsk)); 611 dsk->drive = i | DRV_HARD; 612 dsk->type = dsk->drive & TYPE_AD; 613 dsk->unit = i; 614 dsk->slice = 0; 615 dsk->part = 0; 616 dsk->start = 0; 617 dsk->init = 0; 618 probe_drive(dsk); 619 } 620 621 /* 622 * The first discovered pool, if any, is the pool. 623 */ 624 spa = spa_get_primary(); 625 if (!spa) { 626 printf("%s: No ZFS pools located, can't boot\n", BOOTPROG); 627 for (;;) 628 ; 629 } 630 631 primary_spa = spa; 632 primary_vdev = spa_get_primary_vdev(spa); 633 634 if (zfs_spa_init(spa) != 0 || zfs_mount(spa, 0, &zfsmount) != 0) { 635 printf("%s: failed to mount default pool %s\n", 636 BOOTPROG, spa->spa_name); 637 autoboot = 0; 638 } else if (zfs_lookup(&zfsmount, PATH_CONFIG, &dn) == 0 || 639 zfs_lookup(&zfsmount, PATH_DOTCONFIG, &dn) == 0) { 640 off = 0; 641 zfs_read(spa, &dn, &off, cmd, sizeof(cmd)); 642 } 643 644 if (*cmd) { 645 /* 646 * Note that parse() is destructive to cmd[] and we also want 647 * to honor RBX_QUIET option that could be present in cmd[]. 648 */ 649 memcpy(cmddup, cmd, sizeof(cmd)); 650 if (parse()) 651 autoboot = 0; 652 if (!OPT_CHECK(RBX_QUIET)) 653 printf("%s: %s\n", PATH_CONFIG, cmddup); 654 /* Do not process this command twice */ 655 *cmd = 0; 656 } 657 658 /* 659 * Try to exec /boot/loader. If interrupted by a keypress, 660 * or in case of failure, try to load a kernel directly instead. 661 */ 662 663 if (autoboot && !*kname) { 664 memcpy(kname, PATH_LOADER_ZFS, sizeof(PATH_LOADER_ZFS)); 665 if (!keyhit(3)) { 666 load(); 667 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 668 } 669 } 670 671 /* Present the user with the boot2 prompt. */ 672 673 for (;;) { 674 if (!autoboot || !OPT_CHECK(RBX_QUIET)) { 675 printf("\nFreeBSD/x86 boot\n"); 676 if (zfs_rlookup(spa, zfsmount.rootobj, rootname) != 0) 677 printf("Default: %s/<0x%llx>:%s\n" 678 "boot: ", 679 spa->spa_name, zfsmount.rootobj, kname); 680 else if (rootname[0] != '\0') 681 printf("Default: %s/%s:%s\n" 682 "boot: ", 683 spa->spa_name, rootname, kname); 684 else 685 printf("Default: %s:%s\n" 686 "boot: ", 687 spa->spa_name, kname); 688 } 689 if (ioctrl & IO_SERIAL) 690 sio_flush(); 691 if (!autoboot || keyhit(5)) 692 getstr(cmd, sizeof(cmd)); 693 else if (!autoboot || !OPT_CHECK(RBX_QUIET)) 694 putchar('\n'); 695 autoboot = 0; 696 if (parse()) 697 putchar('\a'); 698 else 699 load(); 700 } 701} 702 703/* XXX - Needed for btxld to link the boot2 binary; do not remove. */ 704void 705exit(int x) 706{ 707} 708 709static void 710load(void) 711{ 712 union { 713 struct exec ex; 714 Elf32_Ehdr eh; 715 } hdr; 716 static Elf32_Phdr ep[2]; 717 static Elf32_Shdr es[2]; 718 caddr_t p; 719 dnode_phys_t dn; 720 off_t off; 721 uint32_t addr, x; 722 int fmt, i, j; 723 724 if (zfs_lookup(&zfsmount, kname, &dn)) { 725 printf("\nCan't find %s\n", kname); 726 return; 727 } 728 off = 0; 729 if (xfsread(&dn, &off, &hdr, sizeof(hdr))) 730 return; 731 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 732 fmt = 0; 733 else if (IS_ELF(hdr.eh)) 734 fmt = 1; 735 else { 736 printf("Invalid %s\n", "format"); 737 return; 738 } 739 if (fmt == 0) { 740 addr = hdr.ex.a_entry & 0xffffff; 741 p = PTOV(addr); 742 off = PAGE_SIZE; 743 if (xfsread(&dn, &off, p, hdr.ex.a_text)) 744 return; 745 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 746 if (xfsread(&dn, &off, p, hdr.ex.a_data)) 747 return; 748 p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); 749 bootinfo.bi_symtab = VTOP(p); 750 memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 751 p += sizeof(hdr.ex.a_syms); 752 if (hdr.ex.a_syms) { 753 if (xfsread(&dn, &off, p, hdr.ex.a_syms)) 754 return; 755 p += hdr.ex.a_syms; 756 if (xfsread(&dn, &off, p, sizeof(int))) 757 return; 758 x = *(uint32_t *)p; 759 p += sizeof(int); 760 x -= sizeof(int); 761 if (xfsread(&dn, &off, p, x)) 762 return; 763 p += x; 764 } 765 } else { 766 off = hdr.eh.e_phoff; 767 for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { 768 if (xfsread(&dn, &off, ep + j, sizeof(ep[0]))) 769 return; 770 if (ep[j].p_type == PT_LOAD) 771 j++; 772 } 773 for (i = 0; i < 2; i++) { 774 p = PTOV(ep[i].p_paddr & 0xffffff); 775 off = ep[i].p_offset; 776 if (xfsread(&dn, &off, p, ep[i].p_filesz)) 777 return; 778 } 779 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 780 bootinfo.bi_symtab = VTOP(p); 781 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 782 off = hdr.eh.e_shoff + sizeof(es[0]) * 783 (hdr.eh.e_shstrndx + 1); 784 if (xfsread(&dn, &off, &es, sizeof(es))) 785 return; 786 for (i = 0; i < 2; i++) { 787 memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); 788 p += sizeof(es[i].sh_size); 789 off = es[i].sh_offset; 790 if (xfsread(&dn, &off, p, es[i].sh_size)) 791 return; 792 p += es[i].sh_size; 793 } 794 } 795 addr = hdr.eh.e_entry & 0xffffff; 796 } 797 bootinfo.bi_esymtab = VTOP(p); 798 bootinfo.bi_kernelname = VTOP(kname); 799 zfsargs.size = sizeof(zfsargs); 800 zfsargs.pool = zfsmount.spa->spa_guid; 801 zfsargs.root = zfsmount.rootobj; 802 zfsargs.primary_pool = primary_spa->spa_guid; 803#ifdef LOADER_GELI_SUPPORT 804 bcopy(gelipw, zfsargs.gelipw, sizeof(zfsargs.gelipw)); 805 bzero(gelipw, sizeof(gelipw)); 806#else 807 zfsargs.gelipw[0] = '\0'; 808#endif 809 if (primary_vdev != NULL) 810 zfsargs.primary_vdev = primary_vdev->v_guid; 811 else 812 printf("failed to detect primary vdev\n"); 813 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), 814 bootdev, 815 KARGS_FLAGS_ZFS | KARGS_FLAGS_EXTARG, 816 (uint32_t) spa->spa_guid, 817 (uint32_t) (spa->spa_guid >> 32), 818 VTOP(&bootinfo), 819 zfsargs); 820} 821 822static int 823zfs_mount_ds(char *dsname) 824{ 825 uint64_t newroot; 826 spa_t *newspa; 827 char *q; 828 829 q = strchr(dsname, '/'); 830 if (q) 831 *q++ = '\0'; 832 newspa = spa_find_by_name(dsname); 833 if (newspa == NULL) { 834 printf("\nCan't find ZFS pool %s\n", dsname); 835 return -1; 836 } 837 838 if (zfs_spa_init(newspa)) 839 return -1; 840 841 newroot = 0; 842 if (q) { 843 if (zfs_lookup_dataset(newspa, q, &newroot)) { 844 printf("\nCan't find dataset %s in ZFS pool %s\n", 845 q, newspa->spa_name); 846 return -1; 847 } 848 } 849 if (zfs_mount(newspa, newroot, &zfsmount)) { 850 printf("\nCan't mount ZFS dataset\n"); 851 return -1; 852 } 853 spa = newspa; 854 return (0); 855} 856 857static int 858parse(void) 859{ 860 char *arg = cmd; 861 char *ep, *p, *q; 862 const char *cp; 863 int c, i, j; 864 865 while ((c = *arg++)) { 866 if (c == ' ' || c == '\t' || c == '\n') 867 continue; 868 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); 869 ep = p; 870 if (*p) 871 *p++ = 0; 872 if (c == '-') { 873 while ((c = *arg++)) { 874 if (c == 'P') { 875 if (*(uint8_t *)PTOV(0x496) & 0x10) { 876 cp = "yes"; 877 } else { 878 opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL); 879 cp = "no"; 880 } 881 printf("Keyboard: %s\n", cp); 882 continue; 883 } else if (c == 'S') { 884 j = 0; 885 while ((unsigned int)(i = *arg++ - '0') <= 9) 886 j = j * 10 + i; 887 if (j > 0 && i == -'0') { 888 comspeed = j; 889 break; 890 } 891 /* Fall through to error below ('S' not in optstr[]). */ 892 } 893 for (i = 0; c != optstr[i]; i++) 894 if (i == NOPT - 1) 895 return -1; 896 opts ^= OPT_SET(flags[i]); 897 } 898 ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : 899 OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; 900 if (ioctrl & IO_SERIAL) { 901 if (sio_init(115200 / comspeed) != 0) 902 ioctrl &= ~IO_SERIAL; 903 } 904 } if (c == '?') { 905 dnode_phys_t dn; 906 907 if (zfs_lookup(&zfsmount, arg, &dn) == 0) { 908 zap_list(spa, &dn); 909 } 910 return -1; 911 } else { 912 arg--; 913 914 /* 915 * Report pool status if the comment is 'status'. Lets 916 * hope no-one wants to load /status as a kernel. 917 */ 918 if (!strcmp(arg, "status")) { 919 spa_all_status(); 920 return -1; 921 } 922 923 /* 924 * If there is "zfs:" prefix simply ignore it. 925 */ 926 if (strncmp(arg, "zfs:", 4) == 0) 927 arg += 4; 928 929 /* 930 * If there is a colon, switch pools. 931 */ 932 q = strchr(arg, ':'); 933 if (q) { 934 *q++ = '\0'; 935 if (zfs_mount_ds(arg) != 0) 936 return -1; 937 arg = q; 938 } 939 if ((i = ep - arg)) { 940 if ((size_t)i >= sizeof(kname)) 941 return -1; 942 memcpy(kname, arg, i + 1); 943 } 944 } 945 arg = p; 946 } 947 return 0; 948} 949