svn commit: r339406 - in stable/11/stand: common pc98/btx/lib pc98/libpc98
Warner Losh
imp at FreeBSD.org
Wed Oct 17 04:10:25 UTC 2018
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 ***
More information about the svn-src-all
mailing list