zfsboot.c revision 198079
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 198079 2009-10-14 14:13:42Z jhb $"); 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 31#include <stdarg.h> 32#include <stddef.h> 33 34#include <a.out.h> 35 36#include <btxv86.h> 37 38#ifndef GPT 39#include "zfsboot.h" 40#endif 41#include "lib.h" 42 43#define IO_KEYBOARD 1 44#define IO_SERIAL 2 45 46#define SECOND 18 /* Circa that many ticks in a second. */ 47 48#define RBX_ASKNAME 0x0 /* -a */ 49#define RBX_SINGLE 0x1 /* -s */ 50/* 0x2 is reserved for log2(RB_NOSYNC). */ 51/* 0x3 is reserved for log2(RB_HALT). */ 52/* 0x4 is reserved for log2(RB_INITNAME). */ 53#define RBX_DFLTROOT 0x5 /* -r */ 54#define RBX_KDB 0x6 /* -d */ 55/* 0x7 is reserved for log2(RB_RDONLY). */ 56/* 0x8 is reserved for log2(RB_DUMP). */ 57/* 0x9 is reserved for log2(RB_MINIROOT). */ 58#define RBX_CONFIG 0xa /* -c */ 59#define RBX_VERBOSE 0xb /* -v */ 60#define RBX_SERIAL 0xc /* -h */ 61#define RBX_CDROM 0xd /* -C */ 62/* 0xe is reserved for log2(RB_POWEROFF). */ 63#define RBX_GDB 0xf /* -g */ 64#define RBX_MUTE 0x10 /* -m */ 65/* 0x11 is reserved for log2(RB_SELFTEST). */ 66/* 0x12 is reserved for boot programs. */ 67/* 0x13 is reserved for boot programs. */ 68#define RBX_PAUSE 0x14 /* -p */ 69#define RBX_QUIET 0x15 /* -q */ 70#define RBX_NOINTR 0x1c /* -n */ 71/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */ 72#define RBX_DUAL 0x1d /* -D */ 73/* 0x1f is reserved for log2(RB_BOOTINFO). */ 74 75/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */ 76#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \ 77 OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \ 78 OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \ 79 OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \ 80 OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \ 81 OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL)) 82 83/* Hint to loader that we came from ZFS */ 84#define KARGS_FLAGS_ZFS 0x4 85 86#define PATH_CONFIG "/boot.config" 87#define PATH_BOOT3 "/boot/loader" 88#define PATH_KERNEL "/boot/kernel/kernel" 89 90#define ARGS 0x900 91#define NOPT 14 92#define NDEV 3 93#define MEM_BASE 0x12 94#define MEM_EXT 0x15 95#define V86_CY(x) ((x) & 1) 96#define V86_ZR(x) ((x) & 0x40) 97 98#define DRV_HARD 0x80 99#define DRV_MASK 0x7f 100 101#define TYPE_AD 0 102#define TYPE_DA 1 103#define TYPE_MAXHARD TYPE_DA 104#define TYPE_FD 2 105 106#define OPT_SET(opt) (1 << (opt)) 107#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) 108 109extern uint32_t _end; 110 111#ifdef GPT 112static const uuid_t freebsd_zfs_uuid = GPT_ENT_TYPE_FREEBSD_ZFS; 113#endif 114static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ 115static const unsigned char flags[NOPT] = { 116 RBX_DUAL, 117 RBX_SERIAL, 118 RBX_ASKNAME, 119 RBX_CDROM, 120 RBX_CONFIG, 121 RBX_KDB, 122 RBX_GDB, 123 RBX_MUTE, 124 RBX_NOINTR, 125 RBX_PAUSE, 126 RBX_QUIET, 127 RBX_DFLTROOT, 128 RBX_SINGLE, 129 RBX_VERBOSE 130}; 131 132static const char *const dev_nm[NDEV] = {"ad", "da", "fd"}; 133static const unsigned char dev_maj[NDEV] = {30, 4, 2}; 134 135struct dsk { 136 unsigned drive; 137 unsigned type; 138 unsigned unit; 139 unsigned slice; 140 unsigned part; 141 unsigned start; 142 int init; 143}; 144static char cmd[512]; 145static char kname[1024]; 146static uint32_t opts; 147static int comspeed = SIOSPD; 148static struct bootinfo bootinfo; 149static uint32_t bootdev; 150static uint8_t ioctrl = IO_KEYBOARD; 151 152/* Buffers that must not span a 64k boundary. */ 153#define READ_BUF_SIZE 8192 154struct dmadat { 155 char rdbuf[READ_BUF_SIZE]; /* for reading large things */ 156 char secbuf[READ_BUF_SIZE]; /* for MBR/disklabel */ 157}; 158static struct dmadat *dmadat; 159 160void exit(int); 161static void load(void); 162static int parse(void); 163static void printf(const char *,...); 164static void putchar(int); 165static uint32_t memsize(void); 166static int drvread(struct dsk *, void *, unsigned, unsigned); 167static int keyhit(unsigned); 168static int xputc(int); 169static int xgetc(int); 170static int getc(int); 171 172static void memcpy(void *, const void *, int); 173static void 174memcpy(void *dst, const void *src, int len) 175{ 176 const char *s = src; 177 char *d = dst; 178 179 while (len--) 180 *d++ = *s++; 181} 182 183static void 184strcpy(char *dst, const char *src) 185{ 186 while (*src) 187 *dst++ = *src++; 188 *dst++ = 0; 189} 190 191static void 192strcat(char *dst, const char *src) 193{ 194 while (*dst) 195 dst++; 196 while (*src) 197 *dst++ = *src++; 198 *dst++ = 0; 199} 200 201static int 202strcmp(const char *s1, const char *s2) 203{ 204 for (; *s1 == *s2 && *s1; s1++, s2++); 205 return (unsigned char)*s1 - (unsigned char)*s2; 206} 207 208static const char * 209strchr(const char *s, char ch) 210{ 211 for (; *s; s++) 212 if (*s == ch) 213 return s; 214 return 0; 215} 216 217static int 218memcmp(const void *p1, const void *p2, size_t n) 219{ 220 const char *s1 = (const char *) p1; 221 const char *s2 = (const char *) p2; 222 for (; n > 0 && *s1 == *s2; s1++, s2++, n--); 223 if (n) 224 return (unsigned char)*s1 - (unsigned char)*s2; 225 else 226 return 0; 227} 228 229static void 230memset(void *p, char val, size_t n) 231{ 232 char *s = (char *) p; 233 while (n--) 234 *s++ = val; 235} 236 237static void * 238malloc(size_t n) 239{ 240 static char *heap_next; 241 static char *heap_end; 242 243 if (!heap_next) { 244 heap_next = (char *) dmadat + sizeof(*dmadat); 245 heap_end = (char *) (640*1024); 246 } 247 248 char *p = heap_next; 249 if (p + n > heap_end) { 250 printf("malloc failure\n"); 251 for (;;) 252 ; 253 return 0; 254 } 255 heap_next += n; 256 return p; 257} 258 259static size_t 260strlen(const char *s) 261{ 262 size_t len = 0; 263 while (*s++) 264 len++; 265 return len; 266} 267 268static char * 269strdup(const char *s) 270{ 271 char *p = malloc(strlen(s) + 1); 272 strcpy(p, s); 273 return p; 274} 275 276#include "zfsimpl.c" 277 278/* 279 * Read from a dnode (which must be from a ZPL filesystem). 280 */ 281static int 282zfs_read(spa_t *spa, const dnode_phys_t *dnode, off_t *offp, void *start, size_t size) 283{ 284 const znode_phys_t *zp = (const znode_phys_t *) dnode->dn_bonus; 285 size_t n; 286 int rc; 287 288 n = size; 289 if (*offp + n > zp->zp_size) 290 n = zp->zp_size - *offp; 291 292 rc = dnode_read(spa, dnode, *offp, start, n); 293 if (rc) 294 return (-1); 295 *offp += n; 296 297 return (n); 298} 299 300/* 301 * Current ZFS pool 302 */ 303spa_t *spa; 304 305/* 306 * A wrapper for dskread that doesn't have to worry about whether the 307 * buffer pointer crosses a 64k boundary. 308 */ 309static int 310vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes) 311{ 312 char *p; 313 unsigned int lba, nb; 314 struct dsk *dsk = (struct dsk *) priv; 315 316 if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1))) 317 return -1; 318 319 p = buf; 320 lba = off / DEV_BSIZE; 321 while (bytes > 0) { 322 nb = bytes / DEV_BSIZE; 323 if (nb > READ_BUF_SIZE / DEV_BSIZE) 324 nb = READ_BUF_SIZE / DEV_BSIZE; 325 if (drvread(dsk, dmadat->rdbuf, lba, nb)) 326 return -1; 327 memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE); 328 p += nb * DEV_BSIZE; 329 lba += nb; 330 bytes -= nb * DEV_BSIZE; 331 } 332 333 return 0; 334} 335 336static int 337xfsread(const dnode_phys_t *dnode, off_t *offp, void *buf, size_t nbyte) 338{ 339 if ((size_t)zfs_read(spa, dnode, offp, buf, nbyte) != nbyte) { 340 printf("Invalid %s\n", "format"); 341 return -1; 342 } 343 return 0; 344} 345 346static inline uint32_t 347memsize(void) 348{ 349 v86.addr = MEM_EXT; 350 v86.eax = 0x8800; 351 v86int(); 352 return v86.eax; 353} 354 355static inline void 356getstr(void) 357{ 358 char *s; 359 int c; 360 361 s = cmd; 362 for (;;) { 363 switch (c = xgetc(0)) { 364 case 0: 365 break; 366 case '\177': 367 case '\b': 368 if (s > cmd) { 369 s--; 370 printf("\b \b"); 371 } 372 break; 373 case '\n': 374 case '\r': 375 *s = 0; 376 return; 377 default: 378 if (s - cmd < sizeof(cmd) - 1) 379 *s++ = c; 380 putchar(c); 381 } 382 } 383} 384 385static inline void 386putc(int c) 387{ 388 v86.addr = 0x10; 389 v86.eax = 0xe00 | (c & 0xff); 390 v86.ebx = 0x7; 391 v86int(); 392} 393 394/* 395 * Try to detect a device supported by the legacy int13 BIOS 396 */ 397static int 398int13probe(int drive) 399{ 400 v86.ctl = V86_FLAGS; 401 v86.addr = 0x13; 402 v86.eax = 0x800; 403 v86.edx = drive; 404 v86int(); 405 406 if (!(v86.efl & 0x1) && /* carry clear */ 407 ((v86.edx & 0xff) != (drive & DRV_MASK))) { /* unit # OK */ 408 if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */ 409 return(0); /* skip device */ 410 } 411 return (1); 412 } 413 return(0); 414} 415 416/* 417 * We call this when we find a ZFS vdev - ZFS consumes the dsk 418 * structure so we must make a new one. 419 */ 420static struct dsk * 421copy_dsk(struct dsk *dsk) 422{ 423 struct dsk *newdsk; 424 425 newdsk = malloc(sizeof(struct dsk)); 426 *newdsk = *dsk; 427 return (newdsk); 428} 429 430static void 431probe_drive(struct dsk *dsk, spa_t **spap) 432{ 433#ifdef GPT 434 struct gpt_hdr hdr; 435 struct gpt_ent *ent; 436 daddr_t slba, elba; 437 unsigned part, entries_per_sec; 438#endif 439 struct dos_partition *dp; 440 char *sec; 441 unsigned i; 442 443 /* 444 * If we find a vdev on the whole disk, stop here. Otherwise dig 445 * out the MBR and probe each slice in turn for a vdev. 446 */ 447 if (vdev_probe(vdev_read, dsk, spap) == 0) 448 return; 449 450 sec = dmadat->secbuf; 451 dsk->start = 0; 452 453#ifdef GPT 454 /* 455 * First check for GPT. 456 */ 457 if (drvread(dsk, sec, 1, 1)) { 458 return; 459 } 460 memcpy(&hdr, sec, sizeof(hdr)); 461 if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 || 462 hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || 463 hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { 464 goto trymbr; 465 } 466 467 /* 468 * Probe all GPT partitions for the presense of ZFS pools. We 469 * return the spa_t for the first we find (if requested). This 470 * will have the effect of booting from the first pool on the 471 * disk. 472 */ 473 entries_per_sec = DEV_BSIZE / hdr.hdr_entsz; 474 slba = hdr.hdr_lba_table; 475 elba = slba + hdr.hdr_entries / entries_per_sec; 476 while (slba < elba) { 477 if (drvread(dsk, sec, slba, 1)) 478 return; 479 for (part = 0; part < entries_per_sec; part++) { 480 ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz); 481 if (memcmp(&ent->ent_type, &freebsd_zfs_uuid, 482 sizeof(uuid_t)) == 0) { 483 dsk->start = ent->ent_lba_start; 484 if (vdev_probe(vdev_read, dsk, spap) == 0) { 485 /* 486 * We record the first pool we find (we will try 487 * to boot from that one). 488 */ 489 spap = 0; 490 491 /* 492 * This slice had a vdev. We need a new dsk 493 * structure now since the vdev now owns this one. 494 */ 495 dsk = copy_dsk(dsk); 496 } 497 break; 498 } 499 } 500 slba++; 501 } 502 return; 503trymbr: 504#endif 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 if (vdev_probe(vdev_read, dsk, spap) == 0) { 515 /* 516 * We record the first pool we find (we will try to boot 517 * from that one. 518 */ 519 spap = 0; 520 521 /* 522 * This slice had a vdev. We need a new dsk structure now 523 * since the vdev now owns this one. 524 */ 525 dsk = copy_dsk(dsk); 526 } 527 } 528} 529 530int 531main(void) 532{ 533 int autoboot, i; 534 dnode_phys_t dn; 535 off_t off; 536 struct dsk *dsk; 537 538 dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base); 539 v86.ctl = V86_FLAGS; 540 541 dsk = malloc(sizeof(struct dsk)); 542 dsk->drive = *(uint8_t *)PTOV(ARGS); 543 dsk->type = dsk->drive & DRV_HARD ? TYPE_AD : TYPE_FD; 544 dsk->unit = dsk->drive & DRV_MASK; 545 dsk->slice = *(uint8_t *)PTOV(ARGS + 1) + 1; 546 dsk->part = 0; 547 dsk->start = 0; 548 dsk->init = 0; 549 550 bootinfo.bi_version = BOOTINFO_VERSION; 551 bootinfo.bi_size = sizeof(bootinfo); 552 bootinfo.bi_basemem = 0; /* XXX will be filled by loader or kernel */ 553 bootinfo.bi_extmem = memsize(); 554 bootinfo.bi_memsizes_valid++; 555 bootinfo.bi_bios_dev = dsk->drive; 556 557 bootdev = MAKEBOOTDEV(dev_maj[dsk->type], 558 dsk->slice, dsk->unit, dsk->part), 559 560 /* Process configuration file */ 561 562 autoboot = 1; 563 564 zfs_init(); 565 566 /* 567 * Probe the boot drive first - we will try to boot from whatever 568 * pool we find on that drive. 569 */ 570 probe_drive(dsk, &spa); 571 572 /* 573 * Probe the rest of the drives that the bios knows about. This 574 * will find any other available pools and it may fill in missing 575 * vdevs for the boot pool. 576 */ 577 for (i = 0; i < 128; i++) { 578 if ((i | DRV_HARD) == *(uint8_t *)PTOV(ARGS)) 579 continue; 580 581 if (!int13probe(i | DRV_HARD)) 582 break; 583 584 dsk = malloc(sizeof(struct dsk)); 585 dsk->drive = i | DRV_HARD; 586 dsk->type = dsk->drive & TYPE_AD; 587 dsk->unit = i; 588 dsk->slice = 0; 589 dsk->part = 0; 590 dsk->start = 0; 591 dsk->init = 0; 592 probe_drive(dsk, 0); 593 } 594 595 /* 596 * If we didn't find a pool on the boot drive, default to the 597 * first pool we found, if any. 598 */ 599 if (!spa) { 600 spa = STAILQ_FIRST(&zfs_pools); 601 if (!spa) { 602 printf("No ZFS pools located, can't boot\n"); 603 for (;;) 604 ; 605 } 606 } 607 608 zfs_mount_pool(spa); 609 610 if (zfs_lookup(spa, PATH_CONFIG, &dn) == 0) { 611 off = 0; 612 zfs_read(spa, &dn, &off, cmd, sizeof(cmd)); 613 } 614 615 if (*cmd) { 616 if (parse()) 617 autoboot = 0; 618 if (!OPT_CHECK(RBX_QUIET)) 619 printf("%s: %s", PATH_CONFIG, cmd); 620 /* Do not process this command twice */ 621 *cmd = 0; 622 } 623 624 /* 625 * Try to exec stage 3 boot loader. If interrupted by a keypress, 626 * or in case of failure, try to load a kernel directly instead. 627 */ 628 629 if (autoboot && !*kname) { 630 memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3)); 631 if (!keyhit(3*SECOND)) { 632 load(); 633 memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL)); 634 } 635 } 636 637 /* Present the user with the boot2 prompt. */ 638 639 for (;;) { 640 if (!autoboot || !OPT_CHECK(RBX_QUIET)) 641 printf("\nFreeBSD/i386 boot\n" 642 "Default: %s:%s\n" 643 "boot: ", 644 spa->spa_name, kname); 645 if (ioctrl & IO_SERIAL) 646 sio_flush(); 647 if (!autoboot || keyhit(5*SECOND)) 648 getstr(); 649 else if (!autoboot || !OPT_CHECK(RBX_QUIET)) 650 putchar('\n'); 651 autoboot = 0; 652 if (parse()) 653 putchar('\a'); 654 else 655 load(); 656 } 657} 658 659/* XXX - Needed for btxld to link the boot2 binary; do not remove. */ 660void 661exit(int x) 662{ 663} 664 665static void 666load(void) 667{ 668 union { 669 struct exec ex; 670 Elf32_Ehdr eh; 671 } hdr; 672 static Elf32_Phdr ep[2]; 673 static Elf32_Shdr es[2]; 674 caddr_t p; 675 dnode_phys_t dn; 676 off_t off; 677 uint32_t addr, x; 678 int fmt, i, j; 679 680 if (zfs_lookup(spa, kname, &dn)) { 681 return; 682 } 683 off = 0; 684 if (xfsread(&dn, &off, &hdr, sizeof(hdr))) 685 return; 686 if (N_GETMAGIC(hdr.ex) == ZMAGIC) 687 fmt = 0; 688 else if (IS_ELF(hdr.eh)) 689 fmt = 1; 690 else { 691 printf("Invalid %s\n", "format"); 692 return; 693 } 694 if (fmt == 0) { 695 addr = hdr.ex.a_entry & 0xffffff; 696 p = PTOV(addr); 697 off = PAGE_SIZE; 698 if (xfsread(&dn, &off, p, hdr.ex.a_text)) 699 return; 700 p += roundup2(hdr.ex.a_text, PAGE_SIZE); 701 if (xfsread(&dn, &off, p, hdr.ex.a_data)) 702 return; 703 p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); 704 bootinfo.bi_symtab = VTOP(p); 705 memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); 706 p += sizeof(hdr.ex.a_syms); 707 if (hdr.ex.a_syms) { 708 if (xfsread(&dn, &off, p, hdr.ex.a_syms)) 709 return; 710 p += hdr.ex.a_syms; 711 if (xfsread(&dn, &off, p, sizeof(int))) 712 return; 713 x = *(uint32_t *)p; 714 p += sizeof(int); 715 x -= sizeof(int); 716 if (xfsread(&dn, &off, p, x)) 717 return; 718 p += x; 719 } 720 } else { 721 off = hdr.eh.e_phoff; 722 for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { 723 if (xfsread(&dn, &off, ep + j, sizeof(ep[0]))) 724 return; 725 if (ep[j].p_type == PT_LOAD) 726 j++; 727 } 728 for (i = 0; i < 2; i++) { 729 p = PTOV(ep[i].p_paddr & 0xffffff); 730 off = ep[i].p_offset; 731 if (xfsread(&dn, &off, p, ep[i].p_filesz)) 732 return; 733 } 734 p += roundup2(ep[1].p_memsz, PAGE_SIZE); 735 bootinfo.bi_symtab = VTOP(p); 736 if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { 737 off = hdr.eh.e_shoff + sizeof(es[0]) * 738 (hdr.eh.e_shstrndx + 1); 739 if (xfsread(&dn, &off, &es, sizeof(es))) 740 return; 741 for (i = 0; i < 2; i++) { 742 memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); 743 p += sizeof(es[i].sh_size); 744 off = es[i].sh_offset; 745 if (xfsread(&dn, &off, p, es[i].sh_size)) 746 return; 747 p += es[i].sh_size; 748 } 749 } 750 addr = hdr.eh.e_entry & 0xffffff; 751 } 752 bootinfo.bi_esymtab = VTOP(p); 753 bootinfo.bi_kernelname = VTOP(kname); 754 __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK), 755 bootdev, 756 KARGS_FLAGS_ZFS, 757 (uint32_t) spa->spa_guid, 758 (uint32_t) (spa->spa_guid >> 32), 759 VTOP(&bootinfo)); 760} 761 762static int 763parse() 764{ 765 char *arg = cmd; 766 char *ep, *p, *q; 767 const char *cp; 768 //unsigned int drv; 769 int c, i, j; 770 771 while ((c = *arg++)) { 772 if (c == ' ' || c == '\t' || c == '\n') 773 continue; 774 for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++); 775 ep = p; 776 if (*p) 777 *p++ = 0; 778 if (c == '-') { 779 while ((c = *arg++)) { 780 if (c == 'P') { 781 if (*(uint8_t *)PTOV(0x496) & 0x10) { 782 cp = "yes"; 783 } else { 784 opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL); 785 cp = "no"; 786 } 787 printf("Keyboard: %s\n", cp); 788 continue; 789 } else if (c == 'S') { 790 j = 0; 791 while ((unsigned int)(i = *arg++ - '0') <= 9) 792 j = j * 10 + i; 793 if (j > 0 && i == -'0') { 794 comspeed = j; 795 break; 796 } 797 /* Fall through to error below ('S' not in optstr[]). */ 798 } 799 for (i = 0; c != optstr[i]; i++) 800 if (i == NOPT - 1) 801 return -1; 802 opts ^= OPT_SET(flags[i]); 803 } 804 ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) : 805 OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD; 806 if (ioctrl & IO_SERIAL) 807 sio_init(115200 / comspeed); 808 } if (c == '?') { 809 dnode_phys_t dn; 810 811 if (zfs_lookup(spa, arg, &dn) == 0) { 812 zap_list(spa, &dn); 813 } 814 return -1; 815 } else { 816 arg--; 817 818 /* 819 * Report pool status if the comment is 'status'. Lets 820 * hope no-one wants to load /status as a kernel. 821 */ 822 if (!strcmp(arg, "status")) { 823 spa_all_status(); 824 return -1; 825 } 826 827 /* 828 * If there is a colon, switch pools. 829 */ 830 q = (char *) strchr(arg, ':'); 831 if (q) { 832 spa_t *newspa; 833 834 *q++ = 0; 835 newspa = spa_find_by_name(arg); 836 if (newspa) { 837 spa = newspa; 838 zfs_mount_pool(spa); 839 } else { 840 printf("\nCan't find ZFS pool %s\n", arg); 841 return -1; 842 } 843 arg = q; 844 } 845 if ((i = ep - arg)) { 846 if ((size_t)i >= sizeof(kname)) 847 return -1; 848 memcpy(kname, arg, i + 1); 849 } 850 } 851 arg = p; 852 } 853 return 0; 854} 855 856static void 857printf(const char *fmt,...) 858{ 859 va_list ap; 860 char buf[10]; 861 char *s; 862 unsigned u; 863 int c; 864 int minus; 865 int prec; 866 int len; 867 int pad; 868 869 va_start(ap, fmt); 870 while ((c = *fmt++)) { 871 if (c == '%') { 872 minus = 0; 873 prec = 0; 874 nextfmt: 875 c = *fmt++; 876 switch (c) { 877 case '-': 878 minus = 1; 879 goto nextfmt; 880 case '0': 881 case '1': 882 case '2': 883 case '3': 884 case '4': 885 case '5': 886 case '6': 887 case '7': 888 case '8': 889 case '9': 890 prec = 10 * prec + (c - '0'); 891 goto nextfmt; 892 case 'c': 893 putchar(va_arg(ap, int)); 894 continue; 895 case 's': 896 s = va_arg(ap, char *); 897 if (prec) { 898 len = strlen(s); 899 if (len < prec) 900 pad = prec - len; 901 else 902 pad = 0; 903 if (minus) 904 while (pad--) 905 putchar(' '); 906 for (; *s; s++) 907 putchar(*s); 908 if (!minus) 909 while (pad--) 910 putchar(' '); 911 } else { 912 for (; *s; s++) 913 putchar(*s); 914 } 915 continue; 916 case 'u': 917 u = va_arg(ap, unsigned); 918 s = buf; 919 do 920 *s++ = '0' + u % 10U; 921 while (u /= 10U); 922 while (--s >= buf) 923 putchar(*s); 924 continue; 925 } 926 } 927 putchar(c); 928 } 929 va_end(ap); 930 return; 931} 932 933static void 934putchar(int c) 935{ 936 if (c == '\n') 937 xputc('\r'); 938 xputc(c); 939} 940 941#ifdef GPT 942static struct { 943 uint16_t len; 944 uint16_t count; 945 uint16_t seg; 946 uint16_t off; 947 uint64_t lba; 948} packet; 949#endif 950 951static int 952drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk) 953{ 954#ifdef GPT 955 static unsigned c = 0x2d5c7c2f; 956 957 if (!OPT_CHECK(RBX_QUIET)) 958 printf("%c\b", c = c << 8 | c >> 24); 959 packet.len = 0x10; 960 packet.count = nblk; 961 packet.seg = VTOPOFF(buf); 962 packet.off = VTOPSEG(buf); 963 packet.lba = lba + dsk->start; 964 v86.ctl = V86_FLAGS; 965 v86.addr = 0x13; 966 v86.eax = 0x4200; 967 v86.edx = dsk->drive; 968 v86.ds = VTOPSEG(&packet); 969 v86.esi = VTOPOFF(&packet); 970 v86int(); 971 if (V86_CY(v86.efl)) { 972 printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); 973 return -1; 974 } 975 return 0; 976#else 977 static unsigned c = 0x2d5c7c2f; 978 979 lba += dsk->start; 980 if (!OPT_CHECK(RBX_QUIET)) 981 printf("%c\b", c = c << 8 | c >> 24); 982 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 983 v86.addr = XREADORG; /* call to xread in boot1 */ 984 v86.es = VTOPSEG(buf); 985 v86.eax = lba; 986 v86.ebx = VTOPOFF(buf); 987 v86.ecx = lba >> 16; 988 v86.edx = nblk << 8 | dsk->drive; 989 v86int(); 990 v86.ctl = V86_FLAGS; 991 if (V86_CY(v86.efl)) { 992 printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); 993 return -1; 994 } 995 return 0; 996#endif 997} 998 999static int 1000keyhit(unsigned ticks) 1001{ 1002 uint32_t t0, t1; 1003 1004 if (OPT_CHECK(RBX_NOINTR)) 1005 return 0; 1006 t0 = 0; 1007 for (;;) { 1008 if (xgetc(1)) 1009 return 1; 1010 t1 = *(uint32_t *)PTOV(0x46c); 1011 if (!t0) 1012 t0 = t1; 1013 if (t1 < t0 || t1 >= t0 + ticks) 1014 return 0; 1015 } 1016} 1017 1018static int 1019xputc(int c) 1020{ 1021 if (ioctrl & IO_KEYBOARD) 1022 putc(c); 1023 if (ioctrl & IO_SERIAL) 1024 sio_putc(c); 1025 return c; 1026} 1027 1028static int 1029xgetc(int fn) 1030{ 1031 if (OPT_CHECK(RBX_NOINTR)) 1032 return 0; 1033 for (;;) { 1034 if (ioctrl & IO_KEYBOARD && getc(1)) 1035 return fn ? 1 : getc(0); 1036 if (ioctrl & IO_SERIAL && sio_ischar()) 1037 return fn ? 1 : sio_getc(); 1038 if (fn) 1039 return 0; 1040 } 1041} 1042 1043static int 1044getc(int fn) 1045{ 1046 /* 1047 * The extra comparison against zero is an attempt to work around 1048 * what appears to be a bug in QEMU and Bochs. Both emulators 1049 * sometimes report a key-press with scancode one and ascii zero 1050 * when no such key is pressed in reality. As far as I can tell, 1051 * this only happens shortly after a reboot. 1052 */ 1053 v86.addr = 0x16; 1054 v86.eax = fn << 8; 1055 v86int(); 1056 return fn == 0 ? v86.eax & 0xff : (!V86_ZR(v86.efl) && (v86.eax & 0xff)); 1057} 1058