biosdisk.c (172927) | biosdisk.c (172940) |
---|---|
1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 172927 2007-10-24 12:49:55Z jhb $"); | 28__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 172940 2007-10-24 21:33:00Z jhb $"); |
29 30/* 31 * BIOS disk device handling. 32 * 33 * Ideas and algorithms from: 34 * 35 * - NetBSD libi386/biosdisk.c 36 * - FreeBSD biosboot/disk.c 37 * 38 */ 39 40#include <stand.h> 41 42#include <sys/disklabel.h> 43#include <sys/diskmbr.h> | 29 30/* 31 * BIOS disk device handling. 32 * 33 * Ideas and algorithms from: 34 * 35 * - NetBSD libi386/biosdisk.c 36 * - FreeBSD biosboot/disk.c 37 * 38 */ 39 40#include <stand.h> 41 42#include <sys/disklabel.h> 43#include <sys/diskmbr.h> |
44#include <sys/gpt.h> |
|
44#include <machine/bootinfo.h> 45 46#include <stdarg.h> | 45#include <machine/bootinfo.h> 46 47#include <stdarg.h> |
48#include <uuid.h> |
|
47 48#include <bootstrap.h> 49#include <btxv86.h> 50#include "libi386.h" 51 52#define BIOS_NUMDRIVES 0x475 53#define BIOSDISK_SECSIZE 512 54#define BUFSIZE (1 * BIOSDISK_SECSIZE) --- 6 unchanged lines hidden (view full) --- 61#define DAMAJOR 4 62 63#ifdef DISK_DEBUG 64# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args) 65#else 66# define DEBUG(fmt, args...) 67#endif 68 | 49 50#include <bootstrap.h> 51#include <btxv86.h> 52#include "libi386.h" 53 54#define BIOS_NUMDRIVES 0x475 55#define BIOSDISK_SECSIZE 512 56#define BUFSIZE (1 * BIOSDISK_SECSIZE) --- 6 unchanged lines hidden (view full) --- 63#define DAMAJOR 4 64 65#ifdef DISK_DEBUG 66# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args) 67#else 68# define DEBUG(fmt, args...) 69#endif 70 |
71struct gpt_part { 72 int gp_index; 73 uuid_t gp_type; 74 uint64_t gp_start; 75 uint64_t gp_end; 76}; 77 |
|
69struct open_disk { 70 int od_dkunit; /* disk unit number */ 71 int od_unit; /* BIOS unit number */ 72 int od_cyl; /* BIOS geometry */ 73 int od_hds; 74 int od_sec; 75 int od_boff; /* block offset from beginning of BIOS disk */ 76 int od_flags; 77#define BD_MODEINT13 0x0000 78#define BD_MODEEDD1 0x0001 79#define BD_MODEEDD3 0x0002 80#define BD_MODEMASK 0x0003 81#define BD_FLOPPY 0x0004 82#define BD_LABELOK 0x0008 83#define BD_PARTTABOK 0x0010 | 78struct open_disk { 79 int od_dkunit; /* disk unit number */ 80 int od_unit; /* BIOS unit number */ 81 int od_cyl; /* BIOS geometry */ 82 int od_hds; 83 int od_sec; 84 int od_boff; /* block offset from beginning of BIOS disk */ 85 int od_flags; 86#define BD_MODEINT13 0x0000 87#define BD_MODEEDD1 0x0001 88#define BD_MODEEDD3 0x0002 89#define BD_MODEMASK 0x0003 90#define BD_FLOPPY 0x0004 91#define BD_LABELOK 0x0008 92#define BD_PARTTABOK 0x0010 |
84 struct disklabel od_disklabel; 85 int od_nslices; /* slice count */ 86 struct dos_partition od_slicetab[NEXTDOSPART]; | 93#define BD_GPTOK 0x0020 94 union { 95 struct { 96 struct disklabel mbr_disklabel; 97 int mbr_nslices; /* slice count */ 98 struct dos_partition mbr_slicetab[NEXTDOSPART]; 99 } _mbr; 100 struct { 101 int gpt_nparts; 102 struct gpt_part *gpt_partitions; 103 } _gpt; 104 } _data; |
87}; 88 | 105}; 106 |
107#define od_disklabel _data._mbr.mbr_disklabel 108#define od_nslices _data._mbr.mbr_nslices 109#define od_slicetab _data._mbr.mbr_slicetab 110#define od_nparts _data._gpt.gpt_nparts 111#define od_partitions _data._gpt.gpt_partitions 112 |
|
89/* 90 * List of BIOS devices, translation from disk unit number to 91 * BIOS unit number. 92 */ 93static struct bdinfo 94{ 95 int bd_unit; /* BIOS unit number */ 96 int bd_flags; --- 4 unchanged lines hidden (view full) --- 101static int bd_getgeom(struct open_disk *od); 102static int bd_read(struct open_disk *od, daddr_t dblk, int blks, 103 caddr_t dest); 104static int bd_write(struct open_disk *od, daddr_t dblk, int blks, 105 caddr_t dest); 106 107static int bd_int13probe(struct bdinfo *bd); 108 | 113/* 114 * List of BIOS devices, translation from disk unit number to 115 * BIOS unit number. 116 */ 117static struct bdinfo 118{ 119 int bd_unit; /* BIOS unit number */ 120 int bd_flags; --- 4 unchanged lines hidden (view full) --- 125static int bd_getgeom(struct open_disk *od); 126static int bd_read(struct open_disk *od, daddr_t dblk, int blks, 127 caddr_t dest); 128static int bd_write(struct open_disk *od, daddr_t dblk, int blks, 129 caddr_t dest); 130 131static int bd_int13probe(struct bdinfo *bd); 132 |
133static void bd_printgptpart(struct open_disk *od, struct gpt_part *gp, 134 char *prefix, int verbose); |
|
109static void bd_printslice(struct open_disk *od, struct dos_partition *dp, 110 char *prefix, int verbose); 111static void bd_printbsdslice(struct open_disk *od, daddr_t offset, 112 char *prefix, int verbose); 113 114static int bd_init(void); 115static int bd_strategy(void *devdata, int flag, daddr_t dblk, 116 size_t size, char *buf, size_t *rsize); --- 12 unchanged lines hidden (view full) --- 129 bd_close, 130 noioctl, 131 bd_print, 132 NULL 133}; 134 135static int bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev); 136static void bd_closedisk(struct open_disk *od); | 135static void bd_printslice(struct open_disk *od, struct dos_partition *dp, 136 char *prefix, int verbose); 137static void bd_printbsdslice(struct open_disk *od, daddr_t offset, 138 char *prefix, int verbose); 139 140static int bd_init(void); 141static int bd_strategy(void *devdata, int flag, daddr_t dblk, 142 size_t size, char *buf, size_t *rsize); --- 12 unchanged lines hidden (view full) --- 155 bd_close, 156 noioctl, 157 bd_print, 158 NULL 159}; 160 161static int bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev); 162static void bd_closedisk(struct open_disk *od); |
163static int bd_open_mbr(struct open_disk *od, struct i386_devdesc *dev); |
|
137static int bd_bestslice(struct open_disk *od); 138static void bd_checkextended(struct open_disk *od, int slicenum); | 164static int bd_bestslice(struct open_disk *od); 165static void bd_checkextended(struct open_disk *od, int slicenum); |
166static int bd_open_gpt(struct open_disk *od, struct i386_devdesc *dev); 167static struct gpt_part *bd_best_gptpart(struct open_disk *od); |
|
139 140/* 141 * Translate between BIOS device numbers and our private unit numbers. 142 */ 143int 144bd_bios2unit(int biosdev) 145{ 146 int i; --- 105 unchanged lines hidden (view full) --- 252 253 /* try to open the whole disk */ 254 dev.d_unit = i; 255 dev.d_kind.biosdisk.slice = -1; 256 dev.d_kind.biosdisk.partition = -1; 257 258 if (!bd_opendisk(&od, &dev)) { 259 | 168 169/* 170 * Translate between BIOS device numbers and our private unit numbers. 171 */ 172int 173bd_bios2unit(int biosdev) 174{ 175 int i; --- 105 unchanged lines hidden (view full) --- 281 282 /* try to open the whole disk */ 283 dev.d_unit = i; 284 dev.d_kind.biosdisk.slice = -1; 285 dev.d_kind.biosdisk.partition = -1; 286 287 if (!bd_opendisk(&od, &dev)) { 288 |
289 /* Do we have a GPT table? */ 290 if (od->od_flags & BD_GPTOK) { 291 for (j = 0; j < od->od_nparts; j++) { 292 sprintf(line, " disk%dp%d", i, 293 od->od_partitions[j].gp_index); 294 bd_printgptpart(od, &od->od_partitions[j], line, verbose); 295 } 296 |
|
260 /* Do we have a partition table? */ | 297 /* Do we have a partition table? */ |
261 if (od->od_flags & BD_PARTTABOK) { | 298 } else if (od->od_flags & BD_PARTTABOK) { |
262 dptr = &od->od_slicetab[0]; 263 264 /* Check for a "dedicated" disk */ 265 if ((dptr[3].dp_typ == DOSPTYP_386BSD) && 266 (dptr[3].dp_start == 0) && 267 (dptr[3].dp_size == 50000)) { 268 sprintf(line, " disk%d", i); 269 bd_printbsdslice(od, 0, line, verbose); --- 4 unchanged lines hidden (view full) --- 274 } 275 } 276 } 277 bd_closedisk(od); 278 } 279 } 280} 281 | 299 dptr = &od->od_slicetab[0]; 300 301 /* Check for a "dedicated" disk */ 302 if ((dptr[3].dp_typ == DOSPTYP_386BSD) && 303 (dptr[3].dp_start == 0) && 304 (dptr[3].dp_size == 50000)) { 305 sprintf(line, " disk%d", i); 306 bd_printbsdslice(od, 0, line, verbose); --- 4 unchanged lines hidden (view full) --- 311 } 312 } 313 } 314 bd_closedisk(od); 315 } 316 } 317} 318 |
319static uuid_t efi = GPT_ENT_TYPE_EFI; 320static uuid_t freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; 321static uuid_t freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; 322static uuid_t freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; 323static uuid_t freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; 324static uuid_t ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; 325 326static void 327bd_printgptpart(struct open_disk *od, struct gpt_part *gp, char *prefix, 328 int verbose) 329{ 330 char stats[80]; 331 char line[96]; 332 uint64_t size; 333 char unit; 334 335 if (verbose) { 336 size = (gp->gp_end + 1 - gp->gp_start) / 2048; 337 unit = 'M'; 338 if (size >= 10240000) { 339 size /= 1048576; 340 unit = 'T'; 341 } else if (size >= 10000) { 342 size /= 1024; 343 unit = 'G'; 344 } 345 sprintf(stats, " %.6ld%cB", (long)size, unit); 346 } else 347 stats[0] = '\0'; 348 349 if (uuid_equal(&gp->gp_type, &efi, NULL)) 350 sprintf(line, "%s: EFI%s\n", prefix, stats); 351 else if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL)) 352 sprintf(line, "%s: FAT/NTFS%s\n", prefix, stats); 353 else if (uuid_equal(&gp->gp_type, &freebsd_boot, NULL)) 354 sprintf(line, "%s: FreeBSD boot%s\n", prefix, stats); 355 else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL)) 356 sprintf(line, "%s: FreeBSD UFS%s\n", prefix, stats); 357 else if (uuid_equal(&gp->gp_type, &freebsd_zfs, NULL)) 358 sprintf(line, "%s: FreeBSD ZFS%s\n", prefix, stats); 359 else if (uuid_equal(&gp->gp_type, &freebsd_swap, NULL)) 360 sprintf(line, "%s: FreeBSD swap%s\n", prefix, stats); 361 else 362 sprintf(line, "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n", 363 gp->gp_type.time_low, gp->gp_type.time_mid, 364 gp->gp_type.time_hi_and_version, 365 gp->gp_type.clock_seq_hi_and_reserved, gp->gp_type.clock_seq_low, 366 gp->gp_type.node[0], gp->gp_type.node[1], gp->gp_type.node[2], 367 gp->gp_type.node[3], gp->gp_type.node[4], gp->gp_type.node[5], 368 stats); 369 pager_output(line); 370} 371 |
|
282/* 283 * Print information about slices on a disk. For the size calculations we 284 * assume a 512 byte sector. 285 */ 286static void 287bd_printslice(struct open_disk *od, struct dos_partition *dp, char *prefix, 288 int verbose) 289{ --- 152 unchanged lines hidden (view full) --- 442 ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od; 443 DEBUG("open_disk %p, partition at 0x%x", od, od->od_boff); 444 return(0); 445} 446 447static int 448bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev) 449{ | 372/* 373 * Print information about slices on a disk. For the size calculations we 374 * assume a 512 byte sector. 375 */ 376static void 377bd_printslice(struct open_disk *od, struct dos_partition *dp, char *prefix, 378 int verbose) 379{ --- 152 unchanged lines hidden (view full) --- 532 ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od; 533 DEBUG("open_disk %p, partition at 0x%x", od, od->od_boff); 534 return(0); 535} 536 537static int 538bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev) 539{ |
450 struct dos_partition *dptr; 451 struct disklabel *lp; | |
452 struct open_disk *od; | 540 struct open_disk *od; |
453 int sector, slice, i; | |
454 int error; | 541 int error; |
455 char buf[BUFSIZE]; | |
456 457 if (dev->d_unit >= nbdinfo) { 458 DEBUG("attempt to open nonexistent disk"); 459 return(ENXIO); 460 } 461 462 od = (struct open_disk *)malloc(sizeof(struct open_disk)); 463 if (!od) { 464 DEBUG("no memory"); 465 return (ENOMEM); 466 } 467 468 /* Look up BIOS unit number, intialise open_disk structure */ 469 od->od_dkunit = dev->d_unit; 470 od->od_unit = bdinfo[od->od_dkunit].bd_unit; 471 od->od_flags = bdinfo[od->od_dkunit].bd_flags; 472 od->od_boff = 0; | 542 543 if (dev->d_unit >= nbdinfo) { 544 DEBUG("attempt to open nonexistent disk"); 545 return(ENXIO); 546 } 547 548 od = (struct open_disk *)malloc(sizeof(struct open_disk)); 549 if (!od) { 550 DEBUG("no memory"); 551 return (ENOMEM); 552 } 553 554 /* Look up BIOS unit number, intialise open_disk structure */ 555 od->od_dkunit = dev->d_unit; 556 od->od_unit = bdinfo[od->od_dkunit].bd_unit; 557 od->od_flags = bdinfo[od->od_dkunit].bd_flags; 558 od->od_boff = 0; |
473 od->od_nslices = 0; | |
474 error = 0; | 559 error = 0; |
475 DEBUG("open '%s', unit 0x%x slice %d partition %c", | 560 DEBUG("open '%s', unit 0x%x slice %d partition %d", |
476 i386_fmtdev(dev), dev->d_unit, | 561 i386_fmtdev(dev), dev->d_unit, |
477 dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition + 'a'); | 562 dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition); |
478 479 /* Get geometry for this open (removable device may have changed) */ 480 if (bd_getgeom(od)) { 481 DEBUG("can't get geometry"); 482 error = ENXIO; 483 goto out; 484 } 485 | 563 564 /* Get geometry for this open (removable device may have changed) */ 565 if (bd_getgeom(od)) { 566 DEBUG("can't get geometry"); 567 error = ENXIO; 568 goto out; 569 } 570 |
571 /* Determine disk layout. */ 572 error = bd_open_gpt(od, dev); 573 if (error) 574 error = bd_open_mbr(od, dev); 575 576 out: 577 if (error) { 578 free(od); 579 } else { 580 *odp = od; /* return the open disk */ 581 } 582 return(error); 583} 584 585static int 586bd_open_mbr(struct open_disk *od, struct i386_devdesc *dev) 587{ 588 struct dos_partition *dptr; 589 struct disklabel *lp; 590 int sector, slice, i; 591 int error; 592 char buf[BUFSIZE]; 593 |
|
486 /* 487 * Following calculations attempt to determine the correct value 488 * for d->od_boff by looking for the slice and partition specified, 489 * or searching for reasonable defaults. 490 */ 491 492 /* 493 * Find the slice in the DOS slice table. 494 */ | 594 /* 595 * Following calculations attempt to determine the correct value 596 * for d->od_boff by looking for the slice and partition specified, 597 * or searching for reasonable defaults. 598 */ 599 600 /* 601 * Find the slice in the DOS slice table. 602 */ |
603 od->od_nslices = 0; |
|
495 if (bd_read(od, 0, 1, buf)) { 496 DEBUG("error reading MBR"); | 604 if (bd_read(od, 0, 1, buf)) { 605 DEBUG("error reading MBR"); |
497 error = EIO; 498 goto out; | 606 return (EIO); |
499 } 500 501 /* 502 * Check the slice table magic. 503 */ 504 if (((u_char)buf[0x1fe] != 0x55) || ((u_char)buf[0x1ff] != 0xaa)) { 505 /* If a slice number was explicitly supplied, this is an error */ 506 if (dev->d_kind.biosdisk.slice > 0) { 507 DEBUG("no slice table/MBR (no magic)"); | 607 } 608 609 /* 610 * Check the slice table magic. 611 */ 612 if (((u_char)buf[0x1fe] != 0x55) || ((u_char)buf[0x1ff] != 0xaa)) { 613 /* If a slice number was explicitly supplied, this is an error */ 614 if (dev->d_kind.biosdisk.slice > 0) { 615 DEBUG("no slice table/MBR (no magic)"); |
508 error = ENOENT; 509 goto out; | 616 return (ENOENT); |
510 } 511 sector = 0; 512 goto unsliced; /* may be a floppy */ 513 } 514 515 /* 516 * copy the partition table, then pick up any extended partitions. 517 */ --- 13 unchanged lines hidden (view full) --- 531 532 /* 533 * if a slice number was supplied but not found, this is an error. 534 */ 535 if (dev->d_kind.biosdisk.slice > 0) { 536 slice = dev->d_kind.biosdisk.slice - 1; 537 if (slice >= od->od_nslices) { 538 DEBUG("slice %d not found", slice); | 617 } 618 sector = 0; 619 goto unsliced; /* may be a floppy */ 620 } 621 622 /* 623 * copy the partition table, then pick up any extended partitions. 624 */ --- 13 unchanged lines hidden (view full) --- 638 639 /* 640 * if a slice number was supplied but not found, this is an error. 641 */ 642 if (dev->d_kind.biosdisk.slice > 0) { 643 slice = dev->d_kind.biosdisk.slice - 1; 644 if (slice >= od->od_nslices) { 645 DEBUG("slice %d not found", slice); |
539 error = ENOENT; 540 goto out; | 646 return (ENOENT); |
541 } 542 } 543 544 /* 545 * Check for the historically bogus MBR found on true dedicated disks 546 */ 547 if ((dptr[3].dp_typ == DOSPTYP_386BSD) && 548 (dptr[3].dp_start == 0) && 549 (dptr[3].dp_size == 50000)) { 550 sector = 0; 551 goto unsliced; 552 } 553 554 /* Try to auto-detect the best slice; this should always give a slice number */ 555 if (dev->d_kind.biosdisk.slice == 0) { 556 slice = bd_bestslice(od); 557 if (slice == -1) { | 647 } 648 } 649 650 /* 651 * Check for the historically bogus MBR found on true dedicated disks 652 */ 653 if ((dptr[3].dp_typ == DOSPTYP_386BSD) && 654 (dptr[3].dp_start == 0) && 655 (dptr[3].dp_size == 50000)) { 656 sector = 0; 657 goto unsliced; 658 } 659 660 /* Try to auto-detect the best slice; this should always give a slice number */ 661 if (dev->d_kind.biosdisk.slice == 0) { 662 slice = bd_bestslice(od); 663 if (slice == -1) { |
558 error = ENOENT; 559 goto out; | 664 return (ENOENT); |
560 } 561 dev->d_kind.biosdisk.slice = slice; 562 } 563 564 dptr = &od->od_slicetab[0]; 565 /* 566 * Accept the supplied slice number unequivocally (we may be looking 567 * at a DOS partition). --- 17 unchanged lines hidden (view full) --- 585 */ 586 if (dev->d_kind.biosdisk.partition < 0) { 587 od->od_boff = sector; /* no partition, must be after the slice */ 588 DEBUG("opening raw slice"); 589 } else { 590 591 if (bd_read(od, sector + LABELSECTOR, 1, buf)) { 592 DEBUG("error reading disklabel"); | 665 } 666 dev->d_kind.biosdisk.slice = slice; 667 } 668 669 dptr = &od->od_slicetab[0]; 670 /* 671 * Accept the supplied slice number unequivocally (we may be looking 672 * at a DOS partition). --- 17 unchanged lines hidden (view full) --- 690 */ 691 if (dev->d_kind.biosdisk.partition < 0) { 692 od->od_boff = sector; /* no partition, must be after the slice */ 693 DEBUG("opening raw slice"); 694 } else { 695 696 if (bd_read(od, sector + LABELSECTOR, 1, buf)) { 697 DEBUG("error reading disklabel"); |
593 error = EIO; 594 goto out; | 698 return (EIO); |
595 } 596 DEBUG("copy %d bytes of label from %p to %p", sizeof(struct disklabel), buf + LABELOFFSET, &od->od_disklabel); 597 bcopy(buf + LABELOFFSET, &od->od_disklabel, sizeof(struct disklabel)); 598 lp = &od->od_disklabel; 599 od->od_flags |= BD_LABELOK; 600 601 if (lp->d_magic != DISKMAGIC) { 602 DEBUG("no disklabel"); | 699 } 700 DEBUG("copy %d bytes of label from %p to %p", sizeof(struct disklabel), buf + LABELOFFSET, &od->od_disklabel); 701 bcopy(buf + LABELOFFSET, &od->od_disklabel, sizeof(struct disklabel)); 702 lp = &od->od_disklabel; 703 od->od_flags |= BD_LABELOK; 704 705 if (lp->d_magic != DISKMAGIC) { 706 DEBUG("no disklabel"); |
603 error = ENOENT; 604 goto out; | 707 return (ENOENT); |
605 } 606 if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) { 607 DEBUG("partition '%c' exceeds partitions in table (a-'%c')", 608 'a' + dev->d_kind.biosdisk.partition, 'a' + lp->d_npartitions); | 708 } 709 if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) { 710 DEBUG("partition '%c' exceeds partitions in table (a-'%c')", 711 'a' + dev->d_kind.biosdisk.partition, 'a' + lp->d_npartitions); |
609 error = EPART; 610 goto out; 611 | 712 return (EPART); |
612 } 613 614#ifdef DISK_DEBUG 615 /* Complain if the partition is unused unless this is a floppy. */ 616 if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) && 617 !(od->od_flags & BD_FLOPPY)) 618 DEBUG("warning, partition marked as unused"); 619#endif 620 621 od->od_boff = 622 lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset - 623 lp->d_partitions[RAW_PART].p_offset + 624 sector; 625 } | 713 } 714 715#ifdef DISK_DEBUG 716 /* Complain if the partition is unused unless this is a floppy. */ 717 if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) && 718 !(od->od_flags & BD_FLOPPY)) 719 DEBUG("warning, partition marked as unused"); 720#endif 721 722 od->od_boff = 723 lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset - 724 lp->d_partitions[RAW_PART].p_offset + 725 sector; 726 } |
626 627 out: 628 if (error) { 629 free(od); 630 } else { 631 *odp = od; /* return the open disk */ 632 } 633 return(error); | 727 return (0); |
634} 635 636static void 637bd_checkextended(struct open_disk *od, int slicenum) 638{ 639 char buf[BIOSDISK_SECSIZE]; 640 struct dos_partition *dp; 641 u_int base; --- 92 unchanged lines hidden (view full) --- 734 } 735 if (pref < preflevel) { 736 preflevel = pref; 737 prefslice = i + 1; 738 } 739 } 740 return (prefslice); 741} | 728} 729 730static void 731bd_checkextended(struct open_disk *od, int slicenum) 732{ 733 char buf[BIOSDISK_SECSIZE]; 734 struct dos_partition *dp; 735 u_int base; --- 92 unchanged lines hidden (view full) --- 828 } 829 if (pref < preflevel) { 830 preflevel = pref; 831 prefslice = i + 1; 832 } 833 } 834 return (prefslice); 835} |
742 | 836 837static int 838bd_open_gpt(struct open_disk *od, struct i386_devdesc *dev) 839{ 840 struct dos_partition *dp; 841 struct gpt_hdr *hdr; 842 struct gpt_ent *ent; 843 struct gpt_part *gp; 844 int entries_per_sec, error, i, part; 845 daddr_t lba, elba; 846 char gpt[BIOSDISK_SECSIZE], tbl[BIOSDISK_SECSIZE]; 847 848 /* 849 * Following calculations attempt to determine the correct value 850 * for d->od_boff by looking for the slice and partition specified, 851 * or searching for reasonable defaults. 852 */ 853 error = 0; 854 855 /* First, read the MBR and see if we have a PMBR. */ 856 if (bd_read(od, 0, 1, tbl)) { 857 DEBUG("error reading MBR"); 858 return (EIO); 859 } 860 861 /* Check the slice table magic. */ 862 if (((u_char)tbl[0x1fe] != 0x55) || ((u_char)tbl[0x1ff] != 0xaa)) 863 return (ENXIO); 864 865 /* Check for GPT slice. */ 866 part = 0; 867 dp = (struct dos_partition *)(tbl + DOSPARTOFF); 868 for (i = 0; i < NDOSPART; i++) { 869 if (dp[i].dp_typ == 0xee) 870 part++; 871 else if (dp[i].dp_typ != 0x00) 872 return (EINVAL); 873 } 874 if (part != 1) 875 return (EINVAL); 876 877 /* Read primary GPT table header. */ 878 if (bd_read(od, 1, 1, gpt)) { 879 DEBUG("error reading GPT header"); 880 return (EIO); 881 } 882 hdr = (struct gpt_hdr *)gpt; 883 if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 || 884 hdr->hdr_lba_self != 1 || hdr->hdr_revision < 0x00010000 || 885 hdr->hdr_entsz < sizeof(*ent) || 886 BIOSDISK_SECSIZE % hdr->hdr_entsz != 0) { 887 DEBUG("Invalid GPT header\n"); 888 return (EINVAL); 889 } 890 891 /* Now walk the partition table to count the number of valid partitions. */ 892 part = 0; 893 entries_per_sec = BIOSDISK_SECSIZE / hdr->hdr_entsz; 894 elba = hdr->hdr_lba_table + hdr->hdr_entries / entries_per_sec; 895 for (lba = hdr->hdr_lba_table; lba < elba; lba++) { 896 if (bd_read(od, lba, 1, tbl)) { 897 DEBUG("error reading GPT table"); 898 return (EIO); 899 } 900 for (i = 0; i < entries_per_sec; i++) { 901 ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz); 902 if (uuid_is_nil(&ent->ent_type, NULL) || ent->ent_lba_start == 0 || 903 ent->ent_lba_end < ent->ent_lba_start) 904 continue; 905 part++; 906 } 907 } 908 909 /* Save the important information about all the valid partitions. */ 910 od->od_nparts = part; 911 if (part != 0) { 912 od->od_partitions = malloc(part * sizeof(struct gpt_part)); 913 part = 0; 914 for (lba = hdr->hdr_lba_table; lba < elba; lba++) { 915 if (bd_read(od, lba, 1, tbl)) { 916 DEBUG("error reading GPT table"); 917 error = EIO; 918 goto out; 919 } 920 for (i = 0; i < entries_per_sec; i++) { 921 ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz); 922 if (uuid_is_nil(&ent->ent_type, NULL) || 923 ent->ent_lba_start == 0 || 924 ent->ent_lba_end < ent->ent_lba_start) 925 continue; 926 od->od_partitions[part].gp_index = (lba - hdr->hdr_lba_table) * 927 entries_per_sec + i + 1; 928 od->od_partitions[part].gp_type = ent->ent_type; 929 od->od_partitions[part].gp_start = ent->ent_lba_start; 930 od->od_partitions[part].gp_end = ent->ent_lba_end; 931 part++; 932 } 933 } 934 } 935 od->od_flags |= BD_GPTOK; 936 937 /* Is this a request for the whole disk? */ 938 if (dev->d_kind.biosdisk.slice < 0) { 939 od->od_boff = 0; 940 return (0); 941 } 942 943 /* 944 * If a partition number was supplied, then the user is trying to use 945 * an MBR address rather than a GPT address, so fail. 946 */ 947 if (dev->d_kind.biosdisk.partition != 0xff) { 948 error = ENOENT; 949 goto out; 950 } 951 952 /* If a slice number was supplied but not found, this is an error. */ 953 gp = NULL; 954 if (dev->d_kind.biosdisk.slice > 0) { 955 for (i = 0; i < od->od_nparts; i++) { 956 if (od->od_partitions[i].gp_index == dev->d_kind.biosdisk.slice) { 957 gp = &od->od_partitions[i]; 958 break; 959 } 960 } 961 if (gp == NULL) { 962 DEBUG("partition %d not found", dev->d_kind.biosdisk.slice); 963 error = ENOENT; 964 goto out; 965 } 966 } 967 968 /* Try to auto-detect the best partition. */ 969 if (dev->d_kind.biosdisk.slice == 0) { 970 gp = bd_best_gptpart(od); 971 if (gp == NULL) { 972 error = ENOENT; 973 goto out; 974 } 975 dev->d_kind.biosdisk.slice = gp->gp_index; 976 } 977 od->od_boff = gp->gp_start; 978 979out: 980 if (error) 981 free(od->od_partitions); 982 return (error); 983} 984 985static struct gpt_part * 986bd_best_gptpart(struct open_disk *od) 987{ 988 struct gpt_part *gp, *prefpart; 989 int i, pref, preflevel; 990 991 prefpart = NULL; 992 preflevel = PREF_NONE; 993 994 gp = od->od_partitions; 995 for (i = 0; i < od->od_nparts; i++, gp++) { 996 /* Windows. XXX: Also Linux. */ 997 if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL)) 998 pref = PREF_DOS; 999 /* FreeBSD */ 1000 else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL) || 1001 uuid_equal(&gp->gp_type, &freebsd_zfs, NULL)) 1002 pref = PREF_FBSD; 1003 else 1004 pref = PREF_NONE; 1005 if (pref < preflevel) { 1006 preflevel = pref; 1007 prefpart = gp; 1008 } 1009 } 1010 return (prefpart); 1011} 1012 |
743static int 744bd_close(struct open_file *f) 745{ 746 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data); 747 748 bd_closedisk(od); 749 return(0); 750} 751 752static void 753bd_closedisk(struct open_disk *od) 754{ 755 DEBUG("open_disk %p", od); 756#if 0 757 /* XXX is this required? (especially if disk already open...) */ 758 if (od->od_flags & BD_FLOPPY) 759 delay(3000000); 760#endif | 1013static int 1014bd_close(struct open_file *f) 1015{ 1016 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data); 1017 1018 bd_closedisk(od); 1019 return(0); 1020} 1021 1022static void 1023bd_closedisk(struct open_disk *od) 1024{ 1025 DEBUG("open_disk %p", od); 1026#if 0 1027 /* XXX is this required? (especially if disk already open...) */ 1028 if (od->od_flags & BD_FLOPPY) 1029 delay(3000000); 1030#endif |
1031 if (od->od_flags & BD_GPTOK) 1032 free(od->od_partitions); |
|
761 free(od); 762} 763 764static int 765bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) 766{ 767 struct bcache_devdata bcd; 768 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data); --- 367 unchanged lines hidden --- | 1033 free(od); 1034} 1035 1036static int 1037bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) 1038{ 1039 struct bcache_devdata bcd; 1040 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data); --- 367 unchanged lines hidden --- |