Date: Sun, 5 Aug 2012 14:37:49 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r239066 - head/sys/boot/i386/libi386 Message-ID: <201208051437.q75EbnJO093363@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Sun Aug 5 14:37:48 2012 New Revision: 239066 URL: http://svn.freebsd.org/changeset/base/239066 Log: Add offset field to the i386_devdesc structure to be compatible with disk_devdesc structure. Update biosdisk driver to the new disk API. Modified: head/sys/boot/i386/libi386/Makefile head/sys/boot/i386/libi386/biosdisk.c head/sys/boot/i386/libi386/devicename.c head/sys/boot/i386/libi386/libi386.h Modified: head/sys/boot/i386/libi386/Makefile ============================================================================== --- head/sys/boot/i386/libi386/Makefile Sun Aug 5 14:11:42 2012 (r239065) +++ head/sys/boot/i386/libi386/Makefile Sun Aug 5 14:37:48 2012 (r239066) @@ -39,10 +39,6 @@ CFLAGS+= -DSMBIOS_LITTLE_ENDIAN_UUID .endif .endif -.if !defined(LOADER_NO_GPT_SUPPORT) -CFLAGS+= -DLOADER_GPT_SUPPORT -.endif - # Include simple terminal emulation (cons25-compatible) CFLAGS+= -DTERM_EMU Modified: head/sys/boot/i386/libi386/biosdisk.c ============================================================================== --- head/sys/boot/i386/libi386/biosdisk.c Sun Aug 5 14:11:42 2012 (r239065) +++ head/sys/boot/i386/libi386/biosdisk.c Sun Aug 5 14:37:48 2012 (r239066) @@ -1,5 +1,6 @@ /*- * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> + * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,21 +38,19 @@ __FBSDID("$FreeBSD$"); * */ +#include <sys/disk.h> #include <stand.h> - -#include <sys/disklabel.h> -#include <sys/diskmbr.h> -#include <sys/gpt.h> #include <machine/bootinfo.h> - #include <stdarg.h> -#include <uuid.h> #include <bootstrap.h> #include <btxv86.h> #include <edd.h> +#include "disk.h" #include "libi386.h" +CTASSERT(sizeof(struct i386_devdesc) >= sizeof(struct disk_devdesc)); + #define BIOS_NUMDRIVES 0x475 #define BIOSDISK_SECSIZE 512 #define BUFSIZE (1 * BIOSDISK_SECSIZE) @@ -68,174 +67,118 @@ __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; -}; - -#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 */ } 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); +#define BD(dev) (bdinfo[(dev)->d_unit]) + +static int bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, + caddr_t dest); +static int bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks, + caddr_t dest); +static int bd_int13probe(struct bdinfo *bd); + +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 int bd_ioctl(struct open_file *f, u_long cmd, void *data); +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, + bd_ioctl, + bd_print, + NULL }; -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 - /* * Translate between BIOS device numbers and our private unit numbers. */ int bd_bios2unit(int biosdev) { - int i; - - DEBUG("looking for bios device 0x%x", biosdev); - for (i = 0; i < nbdinfo; i++) { - DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit); - if (bdinfo[i].bd_unit == biosdev) - return(i); - } - return(-1); + int i; + + DEBUG("looking for bios device 0x%x", biosdev); + for (i = 0; i < nbdinfo; i++) { + DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit); + if (bdinfo[i].bd_unit == biosdev) + return (i); + } + return (-1); } int bd_unit2bios(int unit) { - if ((unit >= 0) && (unit < nbdinfo)) - return(bdinfo[unit].bd_unit); - return(-1); + + if ((unit >= 0) && (unit < nbdinfo)) + return (bdinfo[unit].bd_unit); + return (-1); } -/* +/* * Quiz the BIOS for disk devices, save a little info about them. */ static int -bd_init(void) +bd_init(void) { - int base, unit, nfd = 0; + int base, unit, nfd = 0; - /* sequence 0, 0x80 */ - for (base = 0; base <= 0x80; base += 0x80) { - for (unit = base; (nbdinfo < MAXBDDEV); unit++) { + /* sequence 0, 0x80 */ + for (base = 0; base <= 0x80; base += 0x80) { + for (unit = base; (nbdinfo < MAXBDDEV); unit++) { #ifndef VIRTUALBOX - /* check the BIOS equipment list for number of fixed disks */ - if((base == 0x80) && - (nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES))) - break; -#endif - - bdinfo[nbdinfo].bd_unit = unit; - bdinfo[nbdinfo].bd_flags = (unit < 0x80) ? BD_FLOPPY : 0; - - if (!bd_int13probe(&bdinfo[nbdinfo])) - break; - - /* XXX we need "disk aliases" to make this simpler */ - printf("BIOS drive %c: is disk%d\n", - (unit < 0x80) ? ('A' + unit) : ('C' + unit - 0x80), nbdinfo); - nbdinfo++; - if (base == 0x80) - nfd++; + /* + * Check the BIOS equipment list for number + * of fixed disks. + */ + if(base == 0x80 && + (nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES))) + break; +#endif + bdinfo[nbdinfo].bd_unit = unit; + bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0; + if (!bd_int13probe(&bdinfo[nbdinfo])) + break; + + /* XXX we need "disk aliases" to make this simpler */ + printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ? + ('A' + unit): ('C' + unit - 0x80), nbdinfo); + nbdinfo++; + if (base == 0x80) + nfd++; + } } - } - return(0); + return(0); } /* @@ -244,36 +187,60 @@ bd_init(void) static int bd_int13probe(struct bdinfo *bd) { - v86.ctl = V86_FLAGS; - v86.addr = 0x13; - v86.eax = 0x800; - v86.edx = bd->bd_unit; - v86int(); - - if (!(V86_CY(v86.efl)) && /* carry clear */ - ((v86.edx & 0xff) > ((unsigned)bd->bd_unit & 0x7f))) { /* unit # OK */ - if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */ - DEBUG("Invalid geometry for unit %d", bd->bd_unit); - return(0); /* skip device */ - } - bd->bd_flags |= BD_MODEINT13; + struct edd_params params; + + v86.ctl = V86_FLAGS; + v86.addr = 0x13; + v86.eax = 0x800; + v86.edx = bd->bd_unit; + v86int(); + + if (V86_CY(v86.efl) || /* carry set */ + (v86.ecx & 0x3f) == 0 || /* absurd sector number */ + (v86.edx & 0xff) <= (unsigned)(bd->bd_unit & 0x7f)) /* unit # bad */ + return (0); /* skip device */ + + /* Convert max cyl # -> # of cylinders */ + bd->bd_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1; + /* Convert max head # -> # of heads */ + bd->bd_hds = ((v86.edx & 0xff00) >> 8) + 1; + bd->bd_sec = v86.ecx & 0x3f; bd->bd_type = v86.ebx & 0xff; + bd->bd_flags |= BD_MODEINT13; + + /* Calculate sectors count from the geometry */ + bd->bd_sectors = bd->bd_cyl * bd->bd_hds * bd->bd_sec; + bd->bd_sectorsize = BIOSDISK_SECSIZE; + DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl, + bd->bd_hds, bd->bd_sec); /* Determine if we can use EDD with this device. */ v86.eax = 0x4100; v86.edx = bd->bd_unit; v86.ebx = 0x55aa; v86int(); - if (!(V86_CY(v86.efl)) && /* carry clear */ - ((v86.ebx & 0xffff) == 0xaa55) && /* signature */ - (v86.ecx & EDD_INTERFACE_FIXED_DISK)) { /* packets mode ok */ - bd->bd_flags |= BD_MODEEDD1; - if ((v86.eax & 0xff00) >= 0x3000) - bd->bd_flags |= BD_MODEEDD3; + if (V86_CY(v86.efl) || /* carry set */ + (v86.ebx & 0xffff) != 0xaa55 || /* signature */ + (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0) + return (1); + /* EDD supported */ + bd->bd_flags |= BD_MODEEDD1; + if ((v86.eax & 0xff00) >= 0x3000) + bd->bd_flags |= BD_MODEEDD3; + /* Get disk params */ + params.len = sizeof(struct edd_params); + v86.ctl = V86_FLAGS; + v86.addr = 0x13; + v86.eax = 0x4800; + v86.edx = bd->bd_unit; + v86.ds = VTOPSEG(¶ms); + v86.esi = VTOPOFF(¶ms); + v86int(); + if (!V86_CY(v86.efl)) { + bd->bd_sectors = params.sectors; + bd->bd_sectorsize = params.sector_size; } - return(1); - } - return(0); + return (1); } /* @@ -282,238 +249,30 @@ bd_int13probe(struct bdinfo *bd) static void bd_print(int verbose) { - int i, j; - char line[80]; - struct i386_devdesc dev; - struct open_disk *od; - struct dos_partition *dptr; - - for (i = 0; i < nbdinfo; i++) { - sprintf(line, " disk%d: BIOS drive %c:\n", i, - (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit) : ('C' + bdinfo[i].bd_unit - 0x80)); - pager_output(line); - - /* try to open the whole disk */ - dev.d_unit = i; - dev.d_kind.biosdisk.slice = -1; - dev.d_kind.biosdisk.partition = -1; - - if (!bd_opendisk(&od, &dev)) { - -#ifdef LOADER_GPT_SUPPORT - /* Do we have a GPT table? */ - if (od->od_flags & BD_GPTOK) { - for (j = 0; j < od->od_nparts; j++) { - sprintf(line, " disk%dp%d", i, - od->od_partitions[j].gp_index); - bd_printgptpart(od, &od->od_partitions[j], line, verbose); + static char line[80]; + struct disk_devdesc dev; + int i; + + for (i = 0; i < nbdinfo; i++) { + sprintf(line, " disk%d: BIOS drive %c:\n", i, + (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit): + ('C' + bdinfo[i].bd_unit - 0x80)); + pager_output(line); + dev.d_dev = &biosdisk; + dev.d_unit = i; + dev.d_slice = -1; + dev.d_partition = -1; + if (disk_open(&dev, + bdinfo[i].bd_sectorsize * bdinfo[i].bd_sectors, + bdinfo[i].bd_sectorsize) == 0) { + sprintf(line, " disk%d", i); + disk_print(&dev, line, verbose); + disk_close(&dev); } - } else -#endif - /* Do we have a partition table? */ - if (od->od_flags & BD_PARTTABOK) { - dptr = &od->od_slicetab[0]; - - /* Check for a "dedicated" disk */ - if ((dptr[3].dp_typ == DOSPTYP_386BSD) && - (dptr[3].dp_start == 0) && - (dptr[3].dp_size == 50000)) { - sprintf(line, " disk%d", i); - bd_printbsdslice(od, 0, line, verbose); - } else { - for (j = 0; j < od->od_nslices; j++) { - sprintf(line, " disk%ds%d", i, j + 1); - bd_printslice(od, &dptr[j], line, verbose); - } - } - } - bd_closedisk(od); - } - } -} - -/* Given a size in 512 byte sectors, convert it to a human-readable number. */ -static char * -display_size(uint64_t size) -{ - static char buf[80]; - char unit; - - size /= 2; - unit = 'K'; - if (size >= 10485760000LL) { - size /= 1073741824; - unit = 'T'; - } else if (size >= 10240000) { - size /= 1048576; - unit = 'G'; - } else if (size >= 10000) { - size /= 1024; - unit = 'M'; - } - sprintf(buf, "%.6ld%cB", (long)size, unit); - 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). * * Note that the philosophy here is "give them exactly what @@ -523,564 +282,83 @@ bd_printbsdslice(struct open_disk *od, d * sliced - are they after the first BSD slice, or the DOS * slice before it?) */ -static int -bd_open(struct open_file *f, ...) -{ - va_list ap; - struct i386_devdesc *dev; - struct open_disk *od; - int error; - - va_start(ap, f); - dev = va_arg(ap, struct i386_devdesc *); - va_end(ap); - if ((error = bd_opendisk(&od, dev))) - return(error); - - /* - * Save our context - */ - ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od; - DEBUG("open_disk %p, partition at 0x%x", od, od->od_boff); - return(0); -} - static int -bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev) -{ - struct open_disk *od; - int error; - - if (dev->d_unit >= nbdinfo) { - DEBUG("attempt to open nonexistent disk"); - return(ENXIO); - } - - od = (struct open_disk *)malloc(sizeof(struct open_disk)); - if (!od) { - DEBUG("no memory"); - return (ENOMEM); - } - - /* Look up BIOS unit number, initalise open_disk structure */ - od->od_dkunit = dev->d_unit; - od->od_unit = bdinfo[od->od_dkunit].bd_unit; - od->od_flags = bdinfo[od->od_dkunit].bd_flags; - od->od_boff = 0; - error = 0; - DEBUG("open '%s', unit 0x%x slice %d partition %d", - i386_fmtdev(dev), dev->d_unit, - dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition); - - /* Get geometry for this open (removable device may have changed) */ - if (bd_getgeom(od)) { - DEBUG("can't get geometry"); - error = ENXIO; - goto out; - } - - /* Determine disk layout. */ -#ifdef LOADER_GPT_SUPPORT - error = bd_open_gpt(od, dev); - if (error) -#endif - error = bd_open_mbr(od, dev); - - out: - if (error) { - free(od); - } else { - *odp = od; /* return the open disk */ - } - return(error); -} - -static int -bd_open_mbr(struct open_disk *od, struct i386_devdesc *dev) +bd_open(struct open_file *f, ...) { - 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; - } + struct disk_devdesc *dev; + va_list ap; - /* 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; - } + va_start(ap, f); + dev = va_arg(ap, struct disk_devdesc *); + va_end(ap); - 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); - } + if (dev->d_unit < 0 || dev->d_unit >= nbdinfo) + return (EIO); -#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); + return (disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize, + BD(dev).bd_sectorsize)); } -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) +bd_close(struct open_file *f) { - 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; + struct disk_devdesc *dev; - default: - pref = PREF_NONE; - } - if (pref < preflevel) { - preflevel = pref; - prefslice = i + 1; - } - } - return (prefslice); + dev = (struct disk_devdesc *)f->f_devdata; + return (disk_close(dev)); } -#ifdef LOADER_GPT_SUPPORT static int -bd_open_gpt(struct open_disk *od, struct i386_devdesc *dev) +bd_ioctl(struct open_file *f, u_long cmd, void *data) { - 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 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208051437.q75EbnJO093363>