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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to