zfsboot.c (185029) | zfsboot.c (185096) |
---|---|
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> | 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 185029 2008-11-17 20:49:29Z pjd $"); | 17__FBSDID("$FreeBSD: head/sys/boot/i386/zfsboot/zfsboot.c 185096 2008-11-19 16:39:01Z dfr $"); |
18 19#include <sys/param.h> 20#include <sys/errno.h> 21#include <sys/diskmbr.h> | 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 |
|
22#include <sys/reboot.h> 23#include <sys/queue.h> 24 25#include <machine/bootinfo.h> 26#include <machine/elf.h> 27 28#include <stdarg.h> 29#include <stddef.h> 30 31#include <a.out.h> 32 33#include <btxv86.h> 34 | 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 |
|
35#include "zfsboot.h" | 39#include "zfsboot.h" |
40#endif |
|
36#include "lib.h" 37 38#define IO_KEYBOARD 1 39#define IO_SERIAL 2 40 41#define SECOND 18 /* Circa that many ticks in a second. */ 42 43#define RBX_ASKNAME 0x0 /* -a */ --- 54 unchanged lines hidden (view full) --- 98#define TYPE_MAXHARD TYPE_DA 99#define TYPE_FD 2 100 101#define OPT_SET(opt) (1 << (opt)) 102#define OPT_CHECK(opt) ((opts) & OPT_SET(opt)) 103 104extern uint32_t _end; 105 | 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 */ --- 54 unchanged lines hidden (view full) --- 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 |
|
106static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */ 107static const unsigned char flags[NOPT] = { 108 RBX_DUAL, 109 RBX_SERIAL, 110 RBX_ASKNAME, 111 RBX_CDROM, 112 RBX_CONFIG, 113 RBX_KDB, --- 289 unchanged lines hidden (view full) --- 403 return (1); 404 } 405 return(0); 406} 407 408static void 409probe_drive(struct dsk *dsk, spa_t **spap) 410{ | 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, --- 289 unchanged lines hidden (view full) --- 411 return (1); 412 } 413 return(0); 414} 415 416static void 417probe_drive(struct dsk *dsk, spa_t **spap) 418{ |
419#ifdef GPT 420 struct gpt_hdr hdr; 421 struct gpt_ent *ent; 422 daddr_t slba, elba; 423 unsigned part, entries_per_sec; 424#endif |
|
411 struct dos_partition *dp; 412 char *sec; 413 unsigned i; 414 415 if (!int13probe(dsk->drive)) 416 return; 417 418 /* 419 * If we find a vdev on the whole disk, stop here. Otherwise dig 420 * out the MBR and probe each slice in turn for a vdev. 421 */ 422 if (vdev_probe(vdev_read, dsk, spap) == 0) 423 return; 424 425 sec = dmadat->secbuf; 426 dsk->start = 0; | 425 struct dos_partition *dp; 426 char *sec; 427 unsigned i; 428 429 if (!int13probe(dsk->drive)) 430 return; 431 432 /* 433 * If we find a vdev on the whole disk, stop here. Otherwise dig 434 * out the MBR and probe each slice in turn for a vdev. 435 */ 436 if (vdev_probe(vdev_read, dsk, spap) == 0) 437 return; 438 439 sec = dmadat->secbuf; 440 dsk->start = 0; |
441 442#ifdef GPT 443 /* 444 * First check for GPT. 445 */ 446 if (drvread(dsk, sec, 1, 1)) { 447 return; 448 } 449 memcpy(&hdr, sec, sizeof(hdr)); 450 if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 || 451 hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 || 452 hdr.hdr_entsz < sizeof(*ent) || DEV_BSIZE % hdr.hdr_entsz != 0) { 453 goto trymbr; 454 } 455 456 /* 457 * Probe all GPT partitions for the presense of ZFS pools. We 458 * return the spa_t for the first we find (if requested). This 459 * will have the effect of booting from the first pool on the 460 * disk. 461 */ 462 entries_per_sec = DEV_BSIZE / hdr.hdr_entsz; 463 slba = hdr.hdr_lba_table; 464 elba = slba + hdr.hdr_entries / entries_per_sec; 465 while (slba < elba) { 466 if (drvread(dsk, sec, slba, 1)) 467 return; 468 for (part = 0; part < entries_per_sec; part++) { 469 ent = (struct gpt_ent *)(sec + part * hdr.hdr_entsz); 470 if (memcmp(&ent->ent_type, &freebsd_zfs_uuid, 471 sizeof(uuid_t)) == 0) { 472 dsk->start = ent->ent_lba_start; 473 if (vdev_probe(vdev_read, dsk, spap) == 0) { 474 /* 475 * We record the first pool we find (we will try 476 * to boot from that one. 477 */ 478 spap = 0; 479 480 /* 481 * This slice had a vdev. We need a new dsk 482 * structure now since the vdev now owns this one. 483 */ 484 struct dsk *newdsk; 485 newdsk = malloc(sizeof(struct dsk)); 486 *newdsk = *dsk; 487 dsk = newdsk; 488 } 489 break; 490 } 491 } 492 slba++; 493 } 494 return; 495trymbr: 496#endif 497 |
|
427 if (drvread(dsk, sec, DOSBBSECTOR, 1)) 428 return; 429 dp = (void *)(sec + DOSPARTOFF); 430 431 for (i = 0; i < NDOSPART; i++) { 432 if (!dp[i].dp_typ) 433 continue; 434 dsk->start = dp[i].dp_start; 435 if (vdev_probe(vdev_read, dsk, spap) == 0) { 436 /* 437 * We record the first pool we find (we will try to boot 438 * from that one. 439 */ 440 spap = 0; 441 442 /* 443 * This slice had a vdev. We need a new dsk structure now | 498 if (drvread(dsk, sec, DOSBBSECTOR, 1)) 499 return; 500 dp = (void *)(sec + DOSPARTOFF); 501 502 for (i = 0; i < NDOSPART; i++) { 503 if (!dp[i].dp_typ) 504 continue; 505 dsk->start = dp[i].dp_start; 506 if (vdev_probe(vdev_read, dsk, spap) == 0) { 507 /* 508 * We record the first pool we find (we will try to boot 509 * from that one. 510 */ 511 spap = 0; 512 513 /* 514 * This slice had a vdev. We need a new dsk structure now |
444 * sice the vdev now owns this one. | 515 * since the vdev now owns this one. |
445 */ 446 struct dsk *newdsk; 447 newdsk = malloc(sizeof(struct dsk)); 448 *newdsk = *dsk; 449 dsk = newdsk; 450 } 451 } 452} --- 401 unchanged lines hidden (view full) --- 854static void 855putchar(int c) 856{ 857 if (c == '\n') 858 xputc('\r'); 859 xputc(c); 860} 861 | 516 */ 517 struct dsk *newdsk; 518 newdsk = malloc(sizeof(struct dsk)); 519 *newdsk = *dsk; 520 dsk = newdsk; 521 } 522 } 523} --- 401 unchanged lines hidden (view full) --- 925static void 926putchar(int c) 927{ 928 if (c == '\n') 929 xputc('\r'); 930 xputc(c); 931} 932 |
933#ifdef GPT 934static struct { 935 uint16_t len; 936 uint16_t count; 937 uint16_t seg; 938 uint16_t off; 939 uint64_t lba; 940} packet; 941#endif 942 |
|
862static int 863drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk) 864{ | 943static int 944drvread(struct dsk *dsk, void *buf, unsigned lba, unsigned nblk) 945{ |
946#ifdef GPT 947 static unsigned c = 0x2d5c7c2f; 948 949 if (!OPT_CHECK(RBX_QUIET)) 950 printf("%c\b", c = c << 8 | c >> 24); 951 packet.len = 0x10; 952 packet.count = nblk; 953 packet.seg = VTOPOFF(buf); 954 packet.off = VTOPSEG(buf); 955 packet.lba = lba + dsk->start; 956 v86.ctl = V86_FLAGS; 957 v86.addr = 0x13; 958 v86.eax = 0x4200; 959 v86.edx = dsk->drive; 960 v86.ds = VTOPSEG(&packet); 961 v86.esi = VTOPOFF(&packet); 962 v86int(); 963 if (V86_CY(v86.efl)) { 964 printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); 965 return -1; 966 } 967 return 0; 968#else |
|
865 static unsigned c = 0x2d5c7c2f; 866 867 lba += dsk->start; 868 if (!OPT_CHECK(RBX_QUIET)) 869 printf("%c\b", c = c << 8 | c >> 24); 870 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 871 v86.addr = XREADORG; /* call to xread in boot1 */ 872 v86.es = VTOPSEG(buf); 873 v86.eax = lba; 874 v86.ebx = VTOPOFF(buf); 875 v86.ecx = lba >> 16; 876 v86.edx = nblk << 8 | dsk->drive; 877 v86int(); 878 v86.ctl = V86_FLAGS; 879 if (V86_CY(v86.efl)) { 880 printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); 881 return -1; 882 } 883 return 0; | 969 static unsigned c = 0x2d5c7c2f; 970 971 lba += dsk->start; 972 if (!OPT_CHECK(RBX_QUIET)) 973 printf("%c\b", c = c << 8 | c >> 24); 974 v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 975 v86.addr = XREADORG; /* call to xread in boot1 */ 976 v86.es = VTOPSEG(buf); 977 v86.eax = lba; 978 v86.ebx = VTOPOFF(buf); 979 v86.ecx = lba >> 16; 980 v86.edx = nblk << 8 | dsk->drive; 981 v86int(); 982 v86.ctl = V86_FLAGS; 983 if (V86_CY(v86.efl)) { 984 printf("error %u lba %u\n", v86.eax >> 8 & 0xff, lba); 985 return -1; 986 } 987 return 0; |
988#endif |
|
884} 885 886static int 887keyhit(unsigned ticks) 888{ 889 uint32_t t0, t1; 890 891 if (OPT_CHECK(RBX_NOINTR)) --- 53 unchanged lines hidden --- | 989} 990 991static int 992keyhit(unsigned ticks) 993{ 994 uint32_t t0, t1; 995 996 if (OPT_CHECK(RBX_NOINTR)) --- 53 unchanged lines hidden --- |