Date: Wed, 17 Oct 2018 04:10:24 +0000 (UTC) From: Warner Losh <imp@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r339406 - in stable/11/stand: common pc98/btx/lib pc98/libpc98 Message-ID: <201810170410.w9H4AOCm059102@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: imp Date: Wed Oct 17 04:10:23 2018 New Revision: 339406 URL: https://svnweb.freebsd.org/changeset/base/339406 Log: Direct commit since these files have gone away in head Move pc98's biosdisk.c to the new style disk access. This is missing support in common/part.c, however, for pc98 partitions, so it's unlikely to actually work. Lack of a pc98 machine that's in sevice limits my ability to test, but this allows pc98 to compile again. Modified: stable/11/stand/common/part.c stable/11/stand/pc98/btx/lib/btxv86.h stable/11/stand/pc98/libpc98/biosdisk.c Modified: stable/11/stand/common/part.c ============================================================================== --- stable/11/stand/common/part.c Wed Oct 17 02:45:15 2018 (r339405) +++ stable/11/stand/common/part.c Wed Oct 17 04:10:23 2018 (r339406) @@ -898,6 +898,38 @@ ptable_getbestpart(const struct ptable *table, struct pref = PREF_NONE; } #endif /* LOADER_GPT_SUPPORT */ +#ifdef LOADER_PC98_SUPPORT + if (table->type == PTABLE_PC98) { + switch(entry->part.type & PC98_MID_MASK) { + case PC98_MID_386BSD: /* FreeBSD */ + if ((entry->part.type & PC98_MID_BOOTABLE) && + (preflevel > PREF_FBSD_ACT)) { + pref = i; + preflevel = PREF_FBSD_ACT; + } else if (preflevel > PREF_FBSD) { + pref = i; + preflevel = PREF_FBSD; + } + break; + + case 0x11: /* DOS/Windows */ + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x63: + if ((entry->part.type & PC98_MID_BOOTABLE) && + (preflevel > PREF_DOS_ACT)) { + pref = i; + preflevel = PREF_DOS_ACT; + } else if (preflevel > PREF_DOS) { + pref = i; + preflevel = PREF_DOS; + } + break; + } + } +#endif /* LOADER_PC98_SUPPORT */ if (pref < preflevel) { preflevel = pref; best = entry; @@ -943,3 +975,162 @@ ptable_iterate(const struct ptable *table, void *arg, } return (ret); } +#ifdef LOADER_PC98_SUPPORT +static int +bd_open_pc98(struct open_disk *od, struct i386_devdesc *dev) +{ + struct pc98_partition *dptr; + struct disklabel *lp; + int sector, slice, i; + 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 (od->od_flags & BD_FLOPPY) { + sector = 0; + goto unsliced; + } + 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 */ + } + if (bd_read(od, 1, 1, buf)) { + DEBUG("error reading MBR"); + return (EIO); + } + + /* + * copy the partition table, then pick up any extended partitions. + */ + bcopy(buf + PC98_PARTOFF, &od->od_slicetab, + sizeof(struct pc98_partition) * PC98_NPARTS); + od->od_nslices = PC98_NPARTS; /* extended slices start here */ + 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); + } + } + + /* 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_scyl * od->od_hds * od->od_sec + + dptr->dp_shd * od->od_sec + dptr->dp_ssect; + { + int end = dptr->dp_ecyl * od->od_hds * od->od_sec + + dptr->dp_ehd * od->od_sec + dptr->dp_esect; + DEBUG("slice entry %d at %d, %d sectors", + dev->d_kind.biosdisk.slice - 1, sector, end-sector); + } + + /* + * If we are looking at a BSD slice, and the partition is < 0, assume the 'a' partition + */ + if ((dptr->dp_mid == DOSMID_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_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 + free(od); +} + +#endif /* LOADER_PC98_SUPPORT */ Modified: stable/11/stand/pc98/btx/lib/btxv86.h ============================================================================== --- stable/11/stand/pc98/btx/lib/btxv86.h Wed Oct 17 02:45:15 2018 (r339405) +++ stable/11/stand/pc98/btx/lib/btxv86.h Wed Oct 17 04:10:23 2018 (r339406) @@ -23,6 +23,15 @@ #include <sys/types.h> #include <machine/psl.h> +/* + * Memory buffer space for real mode IO. + * Just one page is not much, but the space is rather limited. + * See ../btx/btx.S for details. + * XXX TEST THIS XXX + */ +#define V86_IO_BUFFER 0x8000 +#define V86_IO_BUFFER_SIZE 0x1000 + #define V86_ADDR 0x10000 /* Segment:offset address */ #define V86_CALLF 0x20000 /* Emulate far call */ #define V86_FLAGS 0x40000 /* Return flags */ Modified: stable/11/stand/pc98/libpc98/biosdisk.c ============================================================================== --- stable/11/stand/pc98/libpc98/biosdisk.c Wed Oct 17 02:45:15 2018 (r339405) +++ stable/11/stand/pc98/libpc98/biosdisk.c Wed Oct 17 04:10:23 2018 (r339406) @@ -37,18 +37,24 @@ __FBSDID("$FreeBSD$"); * */ +#include <sys/disk.h> +#include <sys/limits.h> #include <stand.h> +#include <machine/bootinfo.h> +#include <stdarg.h> #include <sys/disklabel.h> #include <sys/diskpc98.h> -#include <machine/bootinfo.h> -#include <stdarg.h> - #include <bootstrap.h> #include <btxv86.h> +#include "disk.h" #include "libi386.h" +#ifdef LOADER_GELI_SUPPORT +#error "Nope! No GELI on pc98 so sorry." +#endif + #define BIOS_NUMDRIVES 0x475 #define BIOSDISK_SECSIZE 512 #define BUFSIZE (1 * BIOSDISK_SECSIZE) @@ -65,27 +71,6 @@ __FBSDID("$FreeBSD$"); # define DEBUG(fmt, args...) #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; - int 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 -#define BD_OPTICAL 0x0020 - struct disklabel od_disklabel; - int od_nslices; /* slice count */ - struct pc98_partition od_slicetab[PC98_NPARTS]; -}; - /* * List of BIOS devices, translation from disk unit number to * BIOS unit number. @@ -93,8 +78,21 @@ struct open_disk { static struct bdinfo { 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 +#define BD_LABELOK 0x0008 +#define BD_PARTTABOK 0x0010 +#define BD_OPTICAL 0x0020 int bd_type; /* BIOS 'drive type' (floppy only) */ + uint16_t bd_sectorsize; /* Sector size */ + uint64_t bd_sectors; /* Disk size */ int bd_da_unit; /* kernel unit number for da */ int bd_open; /* reference counter */ void *bd_bcache; /* buffer cache data */ @@ -103,18 +101,12 @@ static int nbdinfo = 0; #define BD(dev) (bdinfo[(dev)->dd.d_unit]) -static int bd_getgeom(struct open_disk *od); -static int bd_read(struct open_disk *od, daddr_t dblk, int blks, +static int bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest); -static int bd_write(struct open_disk *od, daddr_t dblk, int blks, +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_printslice(struct open_disk *od, struct pc98_partition *dp, - char *prefix, int verbose); -static int 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); @@ -122,6 +114,7 @@ static int bd_realstrategy(void *devdata, int flag, da 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 int bd_print(int verbose); struct devsw biosdisk = { @@ -131,17 +124,11 @@ struct devsw biosdisk = { bd_strategy, bd_open, bd_close, - noioctl, + 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_pc98(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); - /* * Translate between BIOS device numbers and our private unit numbers. */ @@ -260,10 +247,9 @@ bd_int13probe(struct bdinfo *bd) static int bd_print(int verbose) { - int i, j, ret = 0; char line[80]; - struct i386_devdesc dev; - struct open_disk *od; + struct disk_devdesc dev; + int i, ret = 0; struct pc98_partition *dptr; if (nbdinfo == 0) @@ -274,34 +260,28 @@ bd_print(int verbose) return (ret); for (i = 0; i < nbdinfo; i++) { - snprintf(line, sizeof(line), " disk%d: BIOS drive %c:\n", - i, 'A' + i); + snprintf(line, sizeof(line), + " disk%d: BIOS drive %c (%ju X %u):\n", i, + (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit): + ('C' + bdinfo[i].bd_unit - 0x80), + (uintmax_t)bdinfo[i].bd_sectors, + bdinfo[i].bd_sectorsize); if ((ret = pager_output(line)) != 0) break; /* try to open the whole disk */ + dev.dd.d_dev = &biosdisk; dev.dd.d_unit = i; - dev.d_kind.biosdisk.slice = -1; - dev.d_kind.biosdisk.partition = -1; - - if (!bd_opendisk(&od, &dev)) { - - /* Do we have a partition table? */ - if (od->od_flags & BD_PARTTABOK) { - dptr = &od->od_slicetab[0]; - - /* Check for a "dedicated" disk */ - for (j = 0; j < od->od_nslices; j++) { - snprintf(line, sizeof(line), - " disk%ds%d", i, j + 1); - if ((ret = bd_printslice(od, &dptr[j], - line, verbose)) != 0) - break; - } - } - bd_closedisk(od); + 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) { + snprintf(line, sizeof(line), " disk%d", i); + ret = disk_print(&dev, line, verbose); + disk_close(&dev); if (ret != 0) - break; + return (ret); } } return (ret); @@ -331,109 +311,6 @@ display_size(uint64_t size) } /* - * Print information about slices on a disk. For the size calculations we - * assume a 512 byte sector. - */ -static int -bd_printslice(struct open_disk *od, struct pc98_partition *dp, char *prefix, - int verbose) -{ - int cylsecs, start, size; - char stats[80]; - char line[80]; - - cylsecs = od->od_hds * od->od_sec; - start = dp->dp_scyl * cylsecs + dp->dp_shd * od->od_sec + dp->dp_ssect; - size = (dp->dp_ecyl - dp->dp_scyl + 1) * cylsecs; - - if (verbose) - sprintf(stats, " %s (%d - %d)", display_size(size), - start, start + size); - else - stats[0] = '\0'; - - switch(dp->dp_mid & PC98_MID_MASK) { - case PC98_MID_386BSD: - return (bd_printbsdslice(od, start, prefix, verbose)); - case 0x00: /* unused partition */ - return (0); - case 0x01: - sprintf(line, "%s: FAT-12%s\n", prefix, stats); - break; - case 0x11: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - sprintf(line, "%s: FAT-16%s\n", prefix, stats); - break; - default: - sprintf(line, "%s: Unknown fs: 0x%x %s\n", prefix, dp->dp_mid, - stats); - } - return (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 int -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 (0); - lp =(struct disklabel *)(&buf[0]); - if (lp->d_magic != DISKMAGIC) { - sprintf(line, "%s: FFS bad disklabel\n", prefix); - return (pager_output(line)); - } - - /* 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"); - if (pager_output(line)) - return (1); - } - } - return (0); -} - - -/* * Attempt to open the disk described by (dev) for use by (f). * * Note that the philosophy here is "give them exactly what @@ -446,359 +323,177 @@ bd_printbsdslice(struct open_disk *od, daddr_t offset, static int bd_open(struct open_file *f, ...) { - va_list ap; - struct i386_devdesc *dev; - struct open_disk *od; - int error; + va_list ap; + struct disk_devdesc *dev; + struct disk_devdesc disk; + int err; + uint64_t size; - va_start(ap, f); - dev = va_arg(ap, struct i386_devdesc *); - va_end(ap); - if ((error = bd_opendisk(&od, dev))) - return(error); + va_start(ap, f); + dev = va_arg(ap, struct disk_devdesc *); + va_end(ap); - BD(dev).bd_open++; - if (BD(dev).bd_bcache == NULL) - BD(dev).bd_bcache = bcache_allocate(); + if (dev->dd.d_unit < 0 || dev->dd.d_unit >= nbdinfo) + return (EIO); + BD(dev).bd_open++; + if (BD(dev).bd_bcache == NULL) + BD(dev).bd_bcache = bcache_allocate(); - /* - * 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); -} + /* + * Read disk size from partition. + * This is needed to work around buggy BIOS systems returning + * wrong (truncated) disk media size. + * During bd_probe() we tested if the mulitplication of bd_sectors + * would overflow so it should be safe to perform here. + */ + disk.dd.d_dev = dev->dd.d_dev; + disk.dd.d_unit = dev->dd.d_unit; + disk.d_slice = -1; + disk.d_partition = -1; + disk.d_offset = 0; + if (disk_open(&disk, BD(dev).bd_sectors * BD(dev).bd_sectorsize, + BD(dev).bd_sectorsize) == 0) { -static int -bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev) -{ - struct open_disk *od; - int error; + if (disk_ioctl(&disk, DIOCGMEDIASIZE, &size) == 0) { + size /= BD(dev).bd_sectorsize; + if (size > BD(dev).bd_sectors) + BD(dev).bd_sectors = size; + } + disk_close(&disk); + } - if (dev->dd.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, intialise open_disk structure */ - od->od_dkunit = dev->dd.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->dd.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. */ - error = bd_open_pc98(od, dev); - - out: - if (error) { - free(od); - } else { - *odp = od; /* return the open disk */ - } - return(error); + err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize, + BD(dev).bd_sectorsize); + /* i386 has GELI here */ + return(err); } -static int -bd_open_pc98(struct open_disk *od, struct i386_devdesc *dev) +static int +bd_close(struct open_file *f) { - struct pc98_partition *dptr; - struct disklabel *lp; - int sector, slice, i; - char buf[BUFSIZE]; + struct disk_devdesc *dev; - /* - * 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 (od->od_flags & BD_FLOPPY) { - sector = 0; - goto unsliced; - } - 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); + dev = (struct disk_devdesc *)f->f_devdata; + BD(dev).bd_open--; + if (BD(dev).bd_open == 0) { + bcache_free(BD(dev).bd_bcache); + BD(dev).bd_bcache = NULL; } - sector = 0; - goto unsliced; /* may be a floppy */ - } - if (bd_read(od, 1, 1, buf)) { - DEBUG("error reading MBR"); - return (EIO); - } - - /* - * copy the partition table, then pick up any extended partitions. - */ - bcopy(buf + PC98_PARTOFF, &od->od_slicetab, - sizeof(struct pc98_partition) * PC98_NPARTS); - od->od_nslices = PC98_NPARTS; /* extended slices start here */ - 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); - } - } - - /* 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_scyl * od->od_hds * od->od_sec + - dptr->dp_shd * od->od_sec + dptr->dp_ssect; - { - int end = dptr->dp_ecyl * od->od_hds * od->od_sec + - dptr->dp_ehd * od->od_sec + dptr->dp_esect; - DEBUG("slice entry %d at %d, %d sectors", - dev->d_kind.biosdisk.slice - 1, sector, end-sector); - } - - /* - * If we are looking at a BSD slice, and the partition is < 0, assume the 'a' partition - */ - if ((dptr->dp_mid == DOSMID_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); + return (disk_close(dev)); } -/* - * 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 .. PC98_NPARTS - */ static int -bd_bestslice(struct open_disk *od) +bd_ioctl(struct open_file *f, u_long cmd, void *data) { - struct pc98_partition *dp; - int pref, preflevel; - int i, prefslice; - - prefslice = 0; - preflevel = PREF_NONE; + struct disk_devdesc *dev; + int rc; - dp = &od->od_slicetab[0]; - for (i = 0; i < od->od_nslices; i++, dp++) { - switch(dp->dp_mid & PC98_MID_MASK) { - case PC98_MID_386BSD: /* FreeBSD */ - if ((dp->dp_mid & PC98_MID_BOOTABLE) && - (preflevel > PREF_FBSD_ACT)) { - pref = i; - preflevel = PREF_FBSD_ACT; - } else if (preflevel > PREF_FBSD) { - pref = i; - preflevel = PREF_FBSD; - } - break; + dev = (struct disk_devdesc *)f->f_devdata; - case 0x11: /* DOS/Windows */ - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x63: - if ((dp->dp_mid & PC98_MID_BOOTABLE) && - (preflevel > PREF_DOS_ACT)) { - pref = i; - preflevel = PREF_DOS_ACT; - } else if (preflevel > PREF_DOS) { - pref = i; - preflevel = PREF_DOS; - } - break; - } + rc = disk_ioctl(dev, cmd, data); + if (rc != ENOTTY) + return (rc); + + switch (cmd) { + case DIOCGSECTORSIZE: + *(u_int *)data = BD(dev).bd_sectorsize; + break; + case DIOCGMEDIASIZE: + *(uint64_t *)data = BD(dev).bd_sectors * BD(dev).bd_sectorsize; + break; + default: + return (ENOTTY); } - return (prefslice); + return (0); } - -static int -bd_close(struct open_file *f) -{ - struct i386_devdesc *dev = f->f_devdata; - struct open_disk *od = (struct open_disk *)(dev->d_kind.biosdisk.data); - BD(dev).bd_open--; - if (BD(dev).bd_open == 0) { - bcache_free(BD(dev).bd_bcache); - BD(dev).bd_bcache = NULL; - } - - bd_closedisk(od); - return(0); -} - -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 - free(od); -} - static int bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { - struct bcache_devdata bcd; - struct i386_devdesc *dev = devdata; - struct open_disk *od = (struct open_disk *)(dev->d_kind.biosdisk.data); + struct bcache_devdata bcd; + struct disk_devdesc *dev; - bcd.dv_strategy = bd_realstrategy; - bcd.dv_devdata = devdata; - bcd.dv_cache = BD(dev).bd_bcache; - return(bcache_strategy(&bcd, rw, dblk+od->od_boff, size, buf, rsize)); + dev = (struct disk_devdesc *)devdata; + bcd.dv_strategy = bd_realstrategy; + bcd.dv_devdata = devdata; + bcd.dv_cache = BD(dev).bd_bcache; + return (bcache_strategy(&bcd, rw, dblk + dev->d_offset, + size, buf, rsize)); } static int bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { - struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data); - int blks; -#ifdef BD_SUPPORT_FRAGS + struct disk_devdesc *dev = (struct disk_devdesc *)devdata; + uint64_t disk_blocks; + int blks, rc; +#ifdef BD_SUPPORT_FRAGS /* XXX: sector size */ char fragbuf[BIOSDISK_SECSIZE]; size_t fragsize; fragsize = size % BIOSDISK_SECSIZE; #else - if (size % BIOSDISK_SECSIZE) + if (size % BD(dev).bd_sectorsize) panic("bd_strategy: %d bytes I/O not multiple of block size", size); #endif - DEBUG("open_disk %p", od); - blks = size / BIOSDISK_SECSIZE; + DEBUG("open_disk %p", dev); + + /* + * Check the value of the size argument. We do have quite small + * heap (64MB), but we do not know good upper limit, so we check against + * INT_MAX here. This will also protect us against possible overflows + * while translating block count to bytes. + */ + if (size > INT_MAX) { + DEBUG("too large read: %zu bytes", size); + return (EIO); + } + + blks = size / BD(dev).bd_sectorsize; + if (dblk > dblk + blks) + return (EIO); + if (rsize) *rsize = 0; - switch(rw){ + /* Get disk blocks, this value is either for whole disk or for partition */ + if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks)) { + /* DIOCGMEDIASIZE does return bytes. */ + disk_blocks /= BD(dev).bd_sectorsize; + } else { + /* We should not get here. Just try to survive. */ + disk_blocks = BD(dev).bd_sectors - dev->d_offset; + } + + /* Validate source block address. */ + if (dblk < dev->d_offset || dblk >= dev->d_offset + disk_blocks) + return (EIO); + + /* + * Truncate if we are crossing disk or partition end. + */ + if (dblk + blks >= dev->d_offset + disk_blocks) { + blks = dev->d_offset + disk_blocks - dblk; + size = blks * BD(dev).bd_sectorsize; + DEBUG("short read %d", blks); + } + + switch (rw & F_MASK) { case F_READ: - DEBUG("read %d from %d to %p", blks, dblk, buf); + DEBUG("read %d from %lld to %p", blks, dblk, buf); - if (blks && bd_read(od, dblk, blks, buf)) { - DEBUG("read error"); + if (blks && (rc = bd_read(dev, dblk, blks, buf))) { + /* Filter out floppy controller errors */ + if (BD(dev).bd_flags != BD_FLOPPY || rc != 0x20) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201810170410.w9H4AOCm059102>