svn commit: r237323 - user/ae/bootcode/sys/boot/i386/libi386
Andrey V. Elsukov
ae at FreeBSD.org
Wed Jun 20 15:55:43 UTC 2012
Author: ae
Date: Wed Jun 20 15:55:43 2012
New Revision: 237323
URL: http://svn.freebsd.org/changeset/base/237323
Log:
Reimplement bd_opendisk and bd_closedisk functins using new API to
get access to partition tables.
Modified:
user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c
Modified: user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c
==============================================================================
--- user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c Wed Jun 20 15:45:50 2012 (r237322)
+++ user/ae/bootcode/sys/boot/i386/libi386/biosdisk.c Wed Jun 20 15:55:43 2012 (r237323)
@@ -96,6 +96,9 @@ static struct bdinfo
} bdinfo [MAXBDDEV];
static int nbdinfo = 0;
+#define BDSZ(od) (bdinfo[(od)->od_dkunit].bd_sectors)
+#define BDSECSZ(od) (bdinfo[(od)->od_dkunit].bd_sectorsize)
+
static int bd_read(struct open_disk *od, daddr_t dblk, int blks,
caddr_t dest);
static int bd_write(struct open_disk *od, daddr_t dblk, int blks,
@@ -362,49 +365,123 @@ bd_open(struct open_file *f, ...)
}
static int
-bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev)
+diskread(void *dev, void *buf, size_t blocks, off_t offset)
{
- struct open_disk *od;
- int error;
- if (dev->d_unit >= nbdinfo) {
- DEBUG("attempt to open nonexistent disk");
- return(ENXIO);
- }
-
- od = (struct open_disk *)malloc(sizeof(struct open_disk));
- if (!od) {
- DEBUG("no memory");
- return (ENOMEM);
- }
+ return (bd_read(dev, offset, blocks, buf));
+}
- /* Look up BIOS unit number, initalise open_disk structure */
- od->od_dkunit = dev->d_unit;
- od->od_unit = bdinfo[od->od_dkunit].bd_unit;
- od->od_flags = bdinfo[od->od_dkunit].bd_flags;
- od->od_boff = 0;
- error = 0;
- DEBUG("open '%s', unit 0x%x slice %d partition %d",
- i386_fmtdev(dev), dev->d_unit,
- dev->d_kind.biosdisk.slice, dev->d_kind.biosdisk.partition);
-
- /* Get geometry for this open (removable device may have changed) */
- if (bd_getgeom(od)) {
- DEBUG("can't get geometry");
- error = ENXIO;
- goto out;
- }
+static int
+bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev)
+{
+ struct open_disk *od;
+ struct ptable_entry part;
+ int error;
- /* Determine disk layout. */
- error = bd_open_mbr(od, dev);
-
- out:
- if (error) {
- free(od);
- } else {
- *odp = od; /* return the open disk */
- }
- return(error);
+ if (dev->d_unit >= nbdinfo) {
+ DEBUG("attempt to open nonexistent disk");
+ return (ENXIO);
+ }
+ od = (struct open_disk *)malloc(sizeof(struct open_disk));
+ if (!od) {
+ DEBUG("no memory");
+ return (ENOMEM);
+ }
+
+ /* Look up BIOS unit number, initalize open_disk structure */
+ od->od_dkunit = dev->d_unit;
+ od->od_unit = bdinfo[od->od_dkunit].bd_unit;
+ od->od_ptable = bdinfo[od->od_dkunit].bd_ptable;
+ od->od_slice = 0;
+ od->od_boff = 0;
+ error = 0;
+ DEBUG("open '%s', unit 0x%x slice %d partition %d",
+ i386_fmtdev(dev), dev->d_unit, dev->d_kind.biosdisk.slice,
+ dev->d_kind.biosdisk.partition);
+
+ /* Determine disk layout. */
+ if (od->od_ptable == NULL) {
+ od->od_ptable = ptable_open(od, BDSZ(od), BDSECSZ(od),
+ diskread);
+ if (od->od_ptable == NULL) {
+ DEBUG("Can't read partition table");
+ error = ENXIO;
+ goto out;
+ }
+ /* Save the result */
+ bdinfo[od->od_dkunit].bd_ptable = od->od_ptable;
+ }
+ /*
+ * What we want to open:
+ * a whole disk:
+ * slice = -1
+ *
+ * a MBR slice:
+ * slice = 1 .. 4
+ * partition = -1
+ *
+ * an EBR slice:
+ * slice = 5 .. N
+ * partition = -1
+ *
+ * a GPT partition:
+ * slice = 1 .. N
+ * partition = 255
+ *
+ * BSD partition within an MBR slice:
+ * slice = 1 .. N
+ * partition = 0 .. 19
+ */
+ if (dev->d_kind.biosdisk.slice > 0) {
+ /* Try to get information about partition */
+ error = ptable_getpart(od->od_ptable, &part,
+ dev->d_kind.biosdisk.slice);
+ if (error != 0) /* Partition isn't exists */
+ goto out;
+ /* Adjust open_disk's offset within the biosdisk */
+ od->od_boff = part.start;
+ if (dev->d_kind.biosdisk.partition == -1 ||
+ dev->d_kind.biosdisk.partition == 255)
+ goto out; /* Nothing more to do */
+
+ /* Try to read BSD label */
+ od->od_ptable = ptable_open(od, part.end - part.start + 1,
+ SECSZ(od), diskread);
+ if (od->od_ptable == NULL) {
+ DEBUG("Can't read BSD label");
+ error = ENXIO;
+ /* Keep parent partition table opened */
+ goto out;
+ }
+ /* Save the slice number of the parent partition */
+ od->od_slice = part.index;
+ error = ptable_getpart(od->od_ptable, &part,
+ dev->d_kind.biosdisk.partition);
+ if (error != 0) {
+ /*
+ * Keep parent partition table opened, but
+ * close this one (BSD label).
+ */
+ ptable_close(od->od_ptable);
+ goto out;
+ }
+ /* Adjust open_disk's offset within the biosdisk */
+ od->od_boff += part.start;
+ } else if (dev->d_kind.biosdisk.slice == 0) {
+ error = ptable_getbestpart(od->od_ptable, &part);
+ if (error != 0)
+ goto out;
+ /* Save the slice number of best partition to dev */
+ dev->d_kind.biosdisk.slice = part.index;
+ od->od_boff = part.start;
+ }
+out:
+ if (error != 0) {
+ free(od);
+ } else {
+ *odp = od; /* return the open disk */
+ }
+ return (error);
}
static int
@@ -421,8 +498,12 @@ bd_close(struct open_file *f)
static void
bd_closedisk(struct open_disk *od)
{
- DEBUG("open_disk %p", od);
- free(od);
+
+ DEBUG("close_disk %p", od);
+ /* Close only nested ptables */
+ if (od->od_slice != 0 && od->od_ptable != NULL)
+ ptable_close(od->od_ptable);
+ free(od);
}
static int
More information about the svn-src-user
mailing list