From owner-svn-src-user@FreeBSD.ORG Wed Jun 20 11:53:05 2012 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6A1F61065704; Wed, 20 Jun 2012 11:53:05 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 53DC48FC12; Wed, 20 Jun 2012 11:53:05 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q5KBr5mJ040377; Wed, 20 Jun 2012 11:53:05 GMT (envelope-from ae@svn.freebsd.org) Received: (from ae@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q5KBr5xV040375; Wed, 20 Jun 2012 11:53:05 GMT (envelope-from ae@svn.freebsd.org) Message-Id: <201206201153.q5KBr5xV040375@svn.freebsd.org> From: "Andrey V. Elsukov" Date: Wed, 20 Jun 2012 11:53:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r237300 - user/ae/bootcode/sys/boot/i386/libi386 X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Jun 2012 11:53:05 -0000 Author: ae Date: Wed Jun 20 11:53:04 2012 New Revision: 237300 URL: http://svn.freebsd.org/changeset/base/237300 Log: o Remove the most of code related to partition tables from biosdisk.c in preparation to moving to the MI code from part.c. o Move BIOS CHS fields from "struct open_disk" to "struct bdinfo". o Add sectors and sectorsize fields to "struct bdinfo", also add a pointer to "struct ptable". o Fix the indent according to style(9). Modified: user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c Modified: user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c ============================================================================== --- user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c Wed Jun 20 11:30:15 2012 (r237299) +++ user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c Wed Jun 20 11:53:04 2012 (r237300) @@ -38,14 +38,10 @@ __FBSDID("$FreeBSD$"); */ #include - -#include -#include -#include #include +#include #include -#include #include #include @@ -68,115 +64,69 @@ __FBSDID("$FreeBSD$"); # define DEBUG(fmt, args...) #endif -#ifdef LOADER_GPT_SUPPORT -struct gpt_part { - int gp_index; - uuid_t gp_type; - uint64_t gp_start; - uint64_t gp_end; -}; -#endif - struct open_disk { - int od_dkunit; /* disk unit number */ - int od_unit; /* BIOS unit number */ - int od_cyl; /* BIOS geometry */ - int od_hds; - int od_sec; - daddr_t od_boff; /* block offset from beginning of BIOS disk */ - int od_flags; -#define BD_MODEINT13 0x0000 -#define BD_MODEEDD1 0x0001 -#define BD_MODEEDD3 0x0002 -#define BD_MODEMASK 0x0003 -#define BD_FLOPPY 0x0004 -#define BD_LABELOK 0x0008 -#define BD_PARTTABOK 0x0010 -#ifdef LOADER_GPT_SUPPORT -#define BD_GPTOK 0x0020 -#endif - union { - struct { - struct disklabel mbr_disklabel; - int mbr_nslices; /* slice count */ - struct dos_partition mbr_slicetab[NEXTDOSPART]; - } _mbr; -#ifdef LOADER_GPT_SUPPORT - struct { - int gpt_nparts; - struct gpt_part *gpt_partitions; - } _gpt; -#endif - } _data; + int od_dkunit; /* disk unit number */ + int od_unit; /* BIOS unit number */ + int od_slice; /* slice number of the parent table */ + daddr_t od_boff; /* offset from the beginning */ + daddr_t od_size; /* disk or partition size */ + struct ptable *od_ptable; }; -#define od_disklabel _data._mbr.mbr_disklabel -#define od_nslices _data._mbr.mbr_nslices -#define od_slicetab _data._mbr.mbr_slicetab -#ifdef LOADER_GPT_SUPPORT -#define od_nparts _data._gpt.gpt_nparts -#define od_partitions _data._gpt.gpt_partitions -#endif - /* * List of BIOS devices, translation from disk unit number to * BIOS unit number. */ static struct bdinfo { - int bd_unit; /* BIOS unit number */ - int bd_flags; - int bd_type; /* BIOS 'drive type' (floppy only) */ + int bd_unit; /* BIOS unit number */ + int bd_cyl; /* BIOS geometry */ + int bd_hds; + int bd_sec; + int bd_flags; +#define BD_MODEINT13 0x0000 +#define BD_MODEEDD1 0x0001 +#define BD_MODEEDD3 0x0002 +#define BD_MODEMASK 0x0003 +#define BD_FLOPPY 0x0004 + int bd_type; /* BIOS 'drive type' (floppy only) */ + uint16_t bd_sectorsize; /* Sector size */ + uint64_t bd_sectors; /* Disk size */ + struct ptable *bd_ptable; /* Partition table */ } bdinfo [MAXBDDEV]; static int nbdinfo = 0; -static int bd_getgeom(struct open_disk *od); -static int bd_read(struct open_disk *od, daddr_t dblk, int blks, - caddr_t dest); -static int bd_write(struct open_disk *od, daddr_t dblk, int blks, - caddr_t dest); - -static int bd_int13probe(struct bdinfo *bd); - -#ifdef LOADER_GPT_SUPPORT -static void bd_printgptpart(struct open_disk *od, struct gpt_part *gp, - char *prefix, int verbose); -#endif -static void bd_printslice(struct open_disk *od, struct dos_partition *dp, - char *prefix, int verbose); -static void bd_printbsdslice(struct open_disk *od, daddr_t offset, - char *prefix, int verbose); - -static int bd_init(void); -static int bd_strategy(void *devdata, int flag, daddr_t dblk, - size_t size, char *buf, size_t *rsize); -static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, - size_t size, char *buf, size_t *rsize); -static int bd_open(struct open_file *f, ...); -static int bd_close(struct open_file *f); -static void bd_print(int verbose); +static int bd_getgeom(struct open_disk *od); +static int bd_read(struct open_disk *od, daddr_t dblk, int blks, + caddr_t dest); +static int bd_write(struct open_disk *od, daddr_t dblk, int blks, + caddr_t dest); +static int bd_int13probe(struct bdinfo *bd); + +static int bd_init(void); +static void bd_cleanup(void); +static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, + char *buf, size_t *rsize); +static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, + size_t size, char *buf, size_t *rsize); +static int bd_open(struct open_file *f, ...); +static int bd_close(struct open_file *f); +static void bd_print(int verbose); struct devsw biosdisk = { - "disk", - DEVT_DISK, - bd_init, - bd_strategy, - bd_open, - bd_close, - noioctl, - bd_print, - NULL + "disk", + DEVT_DISK, + bd_init, + bd_strategy, + bd_open, + bd_close, + noioctl, + bd_print, + bd_cleanup }; -static int bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev); -static void bd_closedisk(struct open_disk *od); -static int bd_open_mbr(struct open_disk *od, struct i386_devdesc *dev); -static int bd_bestslice(struct open_disk *od); -static void bd_checkextended(struct open_disk *od, int slicenum); -#ifdef LOADER_GPT_SUPPORT -static int bd_open_gpt(struct open_disk *od, struct i386_devdesc *dev); -static struct gpt_part *bd_best_gptpart(struct open_disk *od); -#endif +static int bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev); +static void bd_closedisk(struct open_disk *od); /* * Translate between BIOS device numbers and our private unit numbers. @@ -355,163 +305,6 @@ display_size(uint64_t size) return (buf); } -#ifdef LOADER_GPT_SUPPORT -static uuid_t efi = GPT_ENT_TYPE_EFI; -static uuid_t freebsd_boot = GPT_ENT_TYPE_FREEBSD_BOOT; -static uuid_t freebsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; -static uuid_t freebsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; -static uuid_t freebsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; -static uuid_t ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; - -static void -bd_printgptpart(struct open_disk *od, struct gpt_part *gp, char *prefix, - int verbose) -{ - char stats[80]; - char line[96]; - - if (verbose) - sprintf(stats, " %s", display_size(gp->gp_end + 1 - gp->gp_start)); - else - stats[0] = '\0'; - - if (uuid_equal(&gp->gp_type, &efi, NULL)) - sprintf(line, "%s: EFI %s\n", prefix, stats); - else if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL)) - sprintf(line, "%s: FAT/NTFS %s\n", prefix, stats); - else if (uuid_equal(&gp->gp_type, &freebsd_boot, NULL)) - sprintf(line, "%s: FreeBSD boot%s\n", prefix, stats); - else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL)) - sprintf(line, "%s: FreeBSD UFS %s\n", prefix, stats); - else if (uuid_equal(&gp->gp_type, &freebsd_zfs, NULL)) - sprintf(line, "%s: FreeBSD ZFS %s\n", prefix, stats); - else if (uuid_equal(&gp->gp_type, &freebsd_swap, NULL)) - sprintf(line, "%s: FreeBSD swap%s\n", prefix, stats); - else - sprintf(line, "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n", - prefix, - gp->gp_type.time_low, gp->gp_type.time_mid, - gp->gp_type.time_hi_and_version, - gp->gp_type.clock_seq_hi_and_reserved, gp->gp_type.clock_seq_low, - gp->gp_type.node[0], gp->gp_type.node[1], gp->gp_type.node[2], - gp->gp_type.node[3], gp->gp_type.node[4], gp->gp_type.node[5], - stats); - pager_output(line); -} -#endif - -/* - * Print information about slices on a disk. For the size calculations we - * assume a 512 byte sector. - */ -static void -bd_printslice(struct open_disk *od, struct dos_partition *dp, char *prefix, - int verbose) -{ - char stats[80]; - char line[80]; - - if (verbose) - sprintf(stats, " %s (%d - %d)", display_size(dp->dp_size), - dp->dp_start, dp->dp_start + dp->dp_size); - else - stats[0] = '\0'; - - switch (dp->dp_typ) { - case DOSPTYP_386BSD: - bd_printbsdslice(od, (daddr_t)dp->dp_start, prefix, verbose); - return; - case DOSPTYP_LINSWP: - sprintf(line, "%s: Linux swap%s\n", prefix, stats); - break; - case DOSPTYP_LINUX: - /* - * XXX - * read the superblock to confirm this is an ext2fs partition? - */ - sprintf(line, "%s: ext2fs%s\n", prefix, stats); - break; - case 0x00: /* unused partition */ - case DOSPTYP_EXT: - return; - case 0x01: - sprintf(line, "%s: FAT-12%s\n", prefix, stats); - break; - case 0x04: - case 0x06: - case 0x0e: - sprintf(line, "%s: FAT-16%s\n", prefix, stats); - break; - case 0x07: - sprintf(line, "%s: NTFS/HPFS%s\n", prefix, stats); - break; - case 0x0b: - case 0x0c: - sprintf(line, "%s: FAT-32%s\n", prefix, stats); - break; - default: - sprintf(line, "%s: Unknown fs: 0x%x %s\n", prefix, dp->dp_typ, - stats); - } - pager_output(line); -} - -/* - * Print out each valid partition in the disklabel of a FreeBSD slice. - * For size calculations, we assume a 512 byte sector size. - */ -static void -bd_printbsdslice(struct open_disk *od, daddr_t offset, char *prefix, - int verbose) -{ - char line[80]; - char buf[BIOSDISK_SECSIZE]; - struct disklabel *lp; - int i; - - /* read disklabel */ - if (bd_read(od, offset + LABELSECTOR, 1, buf)) - return; - lp =(struct disklabel *)(&buf[0]); - if (lp->d_magic != DISKMAGIC) { - sprintf(line, "%s: FFS bad disklabel\n", prefix); - pager_output(line); - return; - } - - /* Print partitions */ - for (i = 0; i < lp->d_npartitions; i++) { - /* - * For each partition, make sure we know what type of fs it is. If - * not, then skip it. However, since floppies often have bogus - * fstypes, print the 'a' partition on a floppy even if it is marked - * unused. - */ - if ((lp->d_partitions[i].p_fstype == FS_BSDFFS) || - (lp->d_partitions[i].p_fstype == FS_SWAP) || - (lp->d_partitions[i].p_fstype == FS_VINUM) || - ((lp->d_partitions[i].p_fstype == FS_UNUSED) && - (od->od_flags & BD_FLOPPY) && (i == 0))) { - - /* Only print out statistics in verbose mode */ - if (verbose) - sprintf(line, " %s%c: %s %s (%d - %d)\n", prefix, 'a' + i, - (lp->d_partitions[i].p_fstype == FS_SWAP) ? "swap " : - (lp->d_partitions[i].p_fstype == FS_VINUM) ? "vinum" : - "FFS ", - display_size(lp->d_partitions[i].p_size), - lp->d_partitions[i].p_offset, - lp->d_partitions[i].p_offset + lp->d_partitions[i].p_size); - else - sprintf(line, " %s%c: %s\n", prefix, 'a' + i, - (lp->d_partitions[i].p_fstype == FS_SWAP) ? "swap" : - (lp->d_partitions[i].p_fstype == FS_VINUM) ? "vinum" : - "FFS"); - pager_output(line); - } - } -} - /* * Attempt to open the disk described by (dev) for use by (f). @@ -580,10 +373,6 @@ bd_opendisk(struct open_disk **odp, stru } /* Determine disk layout. */ -#ifdef LOADER_GPT_SUPPORT - error = bd_open_gpt(od, dev); - if (error) -#endif error = bd_open_mbr(od, dev); out: @@ -595,439 +384,6 @@ bd_opendisk(struct open_disk **odp, stru return(error); } -static int -bd_open_mbr(struct open_disk *od, struct i386_devdesc *dev) -{ - struct dos_partition *dptr; - struct disklabel *lp; - int sector, slice, i; - int error; - char buf[BUFSIZE]; - - /* - * Following calculations attempt to determine the correct value - * for d->od_boff by looking for the slice and partition specified, - * or searching for reasonable defaults. - */ - - /* - * Find the slice in the DOS slice table. - */ - od->od_nslices = 0; - if (bd_read(od, 0, 1, buf)) { - DEBUG("error reading MBR"); - return (EIO); - } - - /* - * Check the slice table magic. - */ - if (((u_char)buf[0x1fe] != 0x55) || ((u_char)buf[0x1ff] != 0xaa)) { - /* If a slice number was explicitly supplied, this is an error */ - if (dev->d_kind.biosdisk.slice > 0) { - DEBUG("no slice table/MBR (no magic)"); - return (ENOENT); - } - sector = 0; - goto unsliced; /* may be a floppy */ - } - - /* - * copy the partition table, then pick up any extended partitions. - */ - bcopy(buf + DOSPARTOFF, &od->od_slicetab, - sizeof(struct dos_partition) * NDOSPART); - od->od_nslices = 4; /* extended slices start here */ - for (i = 0; i < NDOSPART; i++) - bd_checkextended(od, i); - od->od_flags |= BD_PARTTABOK; - dptr = &od->od_slicetab[0]; - - /* Is this a request for the whole disk? */ - if (dev->d_kind.biosdisk.slice == -1) { - sector = 0; - goto unsliced; - } - - /* - * if a slice number was supplied but not found, this is an error. - */ - if (dev->d_kind.biosdisk.slice > 0) { - slice = dev->d_kind.biosdisk.slice - 1; - if (slice >= od->od_nslices) { - DEBUG("slice %d not found", slice); - return (ENOENT); - } - } - - /* - * Check for the historically bogus MBR found on true dedicated disks - */ - if ((dptr[3].dp_typ == DOSPTYP_386BSD) && - (dptr[3].dp_start == 0) && - (dptr[3].dp_size == 50000)) { - sector = 0; - goto unsliced; - } - - /* Try to auto-detect the best slice; this should always give a slice number */ - if (dev->d_kind.biosdisk.slice == 0) { - slice = bd_bestslice(od); - if (slice == -1) { - return (ENOENT); - } - dev->d_kind.biosdisk.slice = slice; - } - - dptr = &od->od_slicetab[0]; - /* - * Accept the supplied slice number unequivocally (we may be looking - * at a DOS partition). - */ - dptr += (dev->d_kind.biosdisk.slice - 1); /* we number 1-4, offsets are 0-3 */ - sector = dptr->dp_start; - DEBUG("slice entry %d at %d, %d sectors", dev->d_kind.biosdisk.slice - 1, sector, dptr->dp_size); - - /* - * If we are looking at a BSD slice, and the partition is < 0, assume the 'a' partition - */ - if ((dptr->dp_typ == DOSPTYP_386BSD) && (dev->d_kind.biosdisk.partition < 0)) - dev->d_kind.biosdisk.partition = 0; - - unsliced: - /* - * Now we have the slice offset, look for the partition in the disklabel if we have - * a partition to start with. - * - * XXX we might want to check the label checksum. - */ - if (dev->d_kind.biosdisk.partition < 0) { - od->od_boff = sector; /* no partition, must be after the slice */ - DEBUG("opening raw slice"); - } else { - - if (bd_read(od, sector + LABELSECTOR, 1, buf)) { - DEBUG("error reading disklabel"); - return (EIO); - } - DEBUG("copy %d bytes of label from %p to %p", sizeof(struct disklabel), buf + LABELOFFSET, &od->od_disklabel); - bcopy(buf + LABELOFFSET, &od->od_disklabel, sizeof(struct disklabel)); - lp = &od->od_disklabel; - od->od_flags |= BD_LABELOK; - - if (lp->d_magic != DISKMAGIC) { - DEBUG("no disklabel"); - return (ENOENT); - } - if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) { - DEBUG("partition '%c' exceeds partitions in table (a-'%c')", - 'a' + dev->d_kind.biosdisk.partition, 'a' + lp->d_npartitions); - return (EPART); - } - -#ifdef DISK_DEBUG - /* Complain if the partition is unused unless this is a floppy. */ - if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) && - !(od->od_flags & BD_FLOPPY)) - DEBUG("warning, partition marked as unused"); -#endif - - od->od_boff = - lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset - - lp->d_partitions[RAW_PART].p_offset + - sector; - } - return (0); -} - -static void -bd_checkextended(struct open_disk *od, int slicenum) -{ - char buf[BIOSDISK_SECSIZE]; - struct dos_partition *dp; - u_int base; - int i, start, end; - - dp = &od->od_slicetab[slicenum]; - start = od->od_nslices; - - if (dp->dp_size == 0) - goto done; - if (dp->dp_typ != DOSPTYP_EXT) - goto done; - if (bd_read(od, (daddr_t)dp->dp_start, 1, buf)) - goto done; - if (((u_char)buf[0x1fe] != 0x55) || ((u_char)buf[0x1ff] != 0xaa)) { - DEBUG("no magic in extended table"); - goto done; - } - base = dp->dp_start; - dp = (struct dos_partition *)(&buf[DOSPARTOFF]); - for (i = 0; i < NDOSPART; i++, dp++) { - if (dp->dp_size == 0) - continue; - if (od->od_nslices == NEXTDOSPART) - goto done; - dp->dp_start += base; - bcopy(dp, &od->od_slicetab[od->od_nslices], sizeof(*dp)); - od->od_nslices++; - } - end = od->od_nslices; - - /* - * now, recursively check the slices we just added - */ - for (i = start; i < end; i++) - bd_checkextended(od, i); -done: - return; -} - -/* - * Search for a slice with the following preferences: - * - * 1: Active FreeBSD slice - * 2: Non-active FreeBSD slice - * 3: Active Linux slice - * 4: non-active Linux slice - * 5: Active FAT/FAT32 slice - * 6: non-active FAT/FAT32 slice - */ -#define PREF_RAWDISK 0 -#define PREF_FBSD_ACT 1 -#define PREF_FBSD 2 -#define PREF_LINUX_ACT 3 -#define PREF_LINUX 4 -#define PREF_DOS_ACT 5 -#define PREF_DOS 6 -#define PREF_NONE 7 - -/* - * slicelimit is in the range 0 .. NDOSPART - */ -static int -bd_bestslice(struct open_disk *od) -{ - struct dos_partition *dp; - int pref, preflevel; - int i, prefslice; - - prefslice = 0; - preflevel = PREF_NONE; - - dp = &od->od_slicetab[0]; - for (i = 0; i < od->od_nslices; i++, dp++) { - - switch (dp->dp_typ) { - case DOSPTYP_386BSD: /* FreeBSD */ - pref = dp->dp_flag & 0x80 ? PREF_FBSD_ACT : PREF_FBSD; - break; - - case DOSPTYP_LINUX: - pref = dp->dp_flag & 0x80 ? PREF_LINUX_ACT : PREF_LINUX; - break; - - case 0x01: /* DOS/Windows */ - case 0x04: - case 0x06: - case 0x0b: - case 0x0c: - case 0x0e: - pref = dp->dp_flag & 0x80 ? PREF_DOS_ACT : PREF_DOS; - break; - - default: - pref = PREF_NONE; - } - if (pref < preflevel) { - preflevel = pref; - prefslice = i + 1; - } - } - return (prefslice); -} - -#ifdef LOADER_GPT_SUPPORT -static int -bd_open_gpt(struct open_disk *od, struct i386_devdesc *dev) -{ - struct dos_partition *dp; - struct gpt_hdr *hdr; - struct gpt_ent *ent; - struct gpt_part *gp; - int entries_per_sec, error, i, part; - daddr_t lba, elba; - char gpt[BIOSDISK_SECSIZE], tbl[BIOSDISK_SECSIZE]; - - /* - * Following calculations attempt to determine the correct value - * for d->od_boff by looking for the slice and partition specified, - * or searching for reasonable defaults. - */ - error = 0; - - /* First, read the MBR and see if we have a PMBR. */ - if (bd_read(od, 0, 1, tbl)) { - DEBUG("error reading MBR"); - return (EIO); - } - - /* Check the slice table magic. */ - if (((u_char)tbl[0x1fe] != 0x55) || ((u_char)tbl[0x1ff] != 0xaa)) - return (ENXIO); - - /* Check for GPT slice. */ - part = 0; - dp = (struct dos_partition *)(tbl + DOSPARTOFF); - for (i = 0; i < NDOSPART; i++) { - if (dp[i].dp_typ == 0xee) - part++; - else if ((part != 1) && (dp[i].dp_typ != 0x00)) - return (EINVAL); - } - if (part != 1) - return (EINVAL); - - /* Read primary GPT table header. */ - if (bd_read(od, 1, 1, gpt)) { - DEBUG("error reading GPT header"); - return (EIO); - } - hdr = (struct gpt_hdr *)gpt; - if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0 || - hdr->hdr_lba_self != 1 || hdr->hdr_revision < 0x00010000 || - hdr->hdr_entsz < sizeof(*ent) || - BIOSDISK_SECSIZE % hdr->hdr_entsz != 0) { - DEBUG("Invalid GPT header\n"); - return (EINVAL); - } - - /* Now walk the partition table to count the number of valid partitions. */ - part = 0; - entries_per_sec = BIOSDISK_SECSIZE / hdr->hdr_entsz; - elba = hdr->hdr_lba_table + hdr->hdr_entries / entries_per_sec; - for (lba = hdr->hdr_lba_table; lba < elba; lba++) { - if (bd_read(od, lba, 1, tbl)) { - DEBUG("error reading GPT table"); - return (EIO); - } - for (i = 0; i < entries_per_sec; i++) { - ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz); - if (uuid_is_nil(&ent->ent_type, NULL) || ent->ent_lba_start == 0 || - ent->ent_lba_end < ent->ent_lba_start) - continue; - part++; - } - } - - /* Save the important information about all the valid partitions. */ - od->od_nparts = part; - if (part != 0) { - od->od_partitions = malloc(part * sizeof(struct gpt_part)); - part = 0; - for (lba = hdr->hdr_lba_table; lba < elba; lba++) { - if (bd_read(od, lba, 1, tbl)) { - DEBUG("error reading GPT table"); - error = EIO; - goto out; - } - for (i = 0; i < entries_per_sec; i++) { - ent = (struct gpt_ent *)(tbl + i * hdr->hdr_entsz); - if (uuid_is_nil(&ent->ent_type, NULL) || - ent->ent_lba_start == 0 || - ent->ent_lba_end < ent->ent_lba_start) - continue; - od->od_partitions[part].gp_index = (lba - hdr->hdr_lba_table) * - entries_per_sec + i + 1; - od->od_partitions[part].gp_type = ent->ent_type; - od->od_partitions[part].gp_start = ent->ent_lba_start; - od->od_partitions[part].gp_end = ent->ent_lba_end; - part++; - } - } - } - od->od_flags |= BD_GPTOK; - - /* Is this a request for the whole disk? */ - if (dev->d_kind.biosdisk.slice < 0) { - od->od_boff = 0; - return (0); - } - - /* - * If a partition number was supplied, then the user is trying to use - * an MBR address rather than a GPT address, so fail. - */ - if (dev->d_kind.biosdisk.partition != 0xff) { - error = ENOENT; - goto out; - } - - /* If a slice number was supplied but not found, this is an error. */ - gp = NULL; - if (dev->d_kind.biosdisk.slice > 0) { - for (i = 0; i < od->od_nparts; i++) { - if (od->od_partitions[i].gp_index == dev->d_kind.biosdisk.slice) { - gp = &od->od_partitions[i]; - break; - } - } - if (gp == NULL) { - DEBUG("partition %d not found", dev->d_kind.biosdisk.slice); - error = ENOENT; - goto out; - } - } - - /* Try to auto-detect the best partition. */ - if (dev->d_kind.biosdisk.slice == 0) { - gp = bd_best_gptpart(od); - if (gp == NULL) { - error = ENOENT; - goto out; - } - dev->d_kind.biosdisk.slice = gp->gp_index; - } - od->od_boff = gp->gp_start; - -out: - if (error) { - if (od->od_nparts > 0) - free(od->od_partitions); - od->od_flags &= ~BD_GPTOK; - } - return (error); -} - -static struct gpt_part * -bd_best_gptpart(struct open_disk *od) -{ - struct gpt_part *gp, *prefpart; - int i, pref, preflevel; - - prefpart = NULL; - preflevel = PREF_NONE; - - gp = od->od_partitions; - for (i = 0; i < od->od_nparts; i++, gp++) { - /* Windows. XXX: Also Linux. */ - if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL)) - pref = PREF_DOS; - /* FreeBSD */ - else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL) || - uuid_equal(&gp->gp_type, &freebsd_zfs, NULL)) - pref = PREF_FBSD; - else - pref = PREF_NONE; - if (pref < preflevel) { - preflevel = pref; - prefpart = gp; - } - } - return (prefpart); -} -#endif - static int bd_close(struct open_file *f) { @@ -1041,15 +397,6 @@ static void bd_closedisk(struct open_disk *od) { DEBUG("open_disk %p", od); -#if 0 - /* XXX is this required? (especially if disk already open...) */ - if (od->od_flags & BD_FLOPPY) - delay(3000000); -#endif -#ifdef LOADER_GPT_SUPPORT - if (od->od_flags & BD_GPTOK && od->od_nparts > 0) - free(od->od_partitions); -#endif free(od); }