Page MenuHomeFreeBSD

D17888.diff
No OneTemporary

D17888.diff

Index: head/stand/i386/libi386/Makefile
===================================================================
--- head/stand/i386/libi386/Makefile
+++ head/stand/i386/libi386/Makefile
@@ -4,7 +4,7 @@
LIB= i386
-SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
+SRCS= biosacpi.c biosdisk.c biosmem.c biospnp.c \
biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
comconsole.c devicename.c elf32_freebsd.c \
elf64_freebsd.c multiboot.c multiboot_tramp.S relocater_tramp.S \
Index: head/stand/i386/libi386/bioscd.c
===================================================================
--- head/stand/i386/libi386/bioscd.c
+++ head/stand/i386/libi386/bioscd.c
@@ -1,432 +0,0 @@
-/*-
- * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
- * Copyright (c) 2001 John H. Baldwin <jhb@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * BIOS CD device handling for CD's that have been booted off of via no
- * emulation booting as defined in the El Torito standard.
- *
- * Ideas and algorithms from:
- *
- * - FreeBSD libi386/biosdisk.c
- *
- */
-
-#include <stand.h>
-
-#include <sys/param.h>
-#include <machine/bootinfo.h>
-
-#include <stdarg.h>
-
-#include <bootstrap.h>
-#include <btxv86.h>
-#include <edd.h>
-#include "libi386.h"
-
-#define BIOSCD_SECSIZE 2048
-#define BUFSIZE (1 * BIOSCD_SECSIZE)
-#define MAXBCDEV 1
-
-/* Major numbers for devices we frontend for. */
-#define ACDMAJOR 117
-#define CDMAJOR 15
-
-#ifdef DISK_DEBUG
-# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
-#else
-# define DEBUG(fmt, args...)
-#endif
-
-struct specification_packet {
- u_char sp_size;
- u_char sp_bootmedia;
- u_char sp_drive;
- u_char sp_controller;
- u_int sp_lba;
- u_short sp_devicespec;
- u_short sp_buffersegment;
- u_short sp_loadsegment;
- u_short sp_sectorcount;
- u_short sp_cylsec;
- u_char sp_head;
-};
-
-/*
- * List of BIOS devices, translation from disk unit number to
- * BIOS unit number.
- */
-static struct bcinfo {
- int bc_unit; /* BIOS unit number */
- struct specification_packet bc_sp;
- int bc_open; /* reference counter */
- void *bc_bcache; /* buffer cache data */
-} bcinfo [MAXBCDEV];
-static int nbcinfo = 0;
-
-#define BC(dev) (bcinfo[(dev)->dd.d_unit])
-
-static int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest);
-static int bc_init(void);
-static int bc_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
-static int bc_realstrategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
-static int bc_open(struct open_file *f, ...);
-static int bc_close(struct open_file *f);
-static int bc_print(int verbose);
-
-struct devsw bioscd = {
- "cd",
- DEVT_CD,
- bc_init,
- bc_strategy,
- bc_open,
- bc_close,
- noioctl,
- bc_print,
- NULL
-};
-
-/*
- * Translate between BIOS device numbers and our private unit numbers.
- */
-int
-bc_bios2unit(int biosdev)
-{
- int i;
-
- DEBUG("looking for bios device 0x%x", biosdev);
- for (i = 0; i < nbcinfo; i++) {
- DEBUG("bc unit %d is BIOS device 0x%x", i, bcinfo[i].bc_unit);
- if (bcinfo[i].bc_unit == biosdev)
- return(i);
- }
- return(-1);
-}
-
-int
-bc_unit2bios(int unit)
-{
- if ((unit >= 0) && (unit < nbcinfo))
- return(bcinfo[unit].bc_unit);
- return(-1);
-}
-
-/*
- * We can't quiz, we have to be told what device to use, so this functoin
- * doesn't do anything. Instead, the loader calls bc_add() with the BIOS
- * device number to add.
- */
-static int
-bc_init(void)
-{
-
- return (0);
-}
-
-int
-bc_add(int biosdev)
-{
-
- if (nbcinfo >= MAXBCDEV)
- return (-1);
- bcinfo[nbcinfo].bc_unit = biosdev;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x4b01;
- v86.edx = biosdev;
- v86.ds = VTOPSEG(&bcinfo[nbcinfo].bc_sp);
- v86.esi = VTOPOFF(&bcinfo[nbcinfo].bc_sp);
- v86int();
- if ((v86.eax & 0xff00) != 0)
- return (-1);
-
- printf("BIOS CD is cd%d\n", nbcinfo);
- nbcinfo++;
- bcache_add_dev(nbcinfo); /* register cd device in bcache */
- return(0);
-}
-
-/*
- * Print information about disks
- */
-static int
-bc_print(int verbose)
-{
- char line[80];
- int i, ret = 0;
-
- if (nbcinfo == 0)
- return (0);
-
- printf("%s devices:", bioscd.dv_name);
- if ((ret = pager_output("\n")) != 0)
- return (ret);
-
- for (i = 0; i < nbcinfo; i++) {
- snprintf(line, sizeof(line), " cd%d: Device 0x%x\n", i,
- bcinfo[i].bc_sp.sp_devicespec);
- if ((ret = pager_output(line)) != 0)
- break;
- }
- return (ret);
-}
-
-/*
- * Attempt to open the disk described by (dev) for use by (f).
- */
-static int
-bc_open(struct open_file *f, ...)
-{
- va_list ap;
- struct i386_devdesc *dev;
-
- va_start(ap, f);
- dev = va_arg(ap, struct i386_devdesc *);
- va_end(ap);
- if (dev->dd.d_unit >= nbcinfo) {
- DEBUG("attempt to open nonexistent disk");
- return(ENXIO);
- }
-
- BC(dev).bc_open++;
- if (BC(dev).bc_bcache == NULL)
- BC(dev).bc_bcache = bcache_allocate();
- return(0);
-}
-
-static int
-bc_close(struct open_file *f)
-{
- struct i386_devdesc *dev;
-
- dev = (struct i386_devdesc *)f->f_devdata;
- BC(dev).bc_open--;
- if (BC(dev).bc_open == 0) {
- bcache_free(BC(dev).bc_bcache);
- BC(dev).bc_bcache = NULL;
- }
- return(0);
-}
-
-static int
-bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
- char *buf, size_t *rsize)
-{
- struct bcache_devdata bcd;
- struct i386_devdesc *dev;
-
- dev = (struct i386_devdesc *)devdata;
- bcd.dv_strategy = bc_realstrategy;
- bcd.dv_devdata = devdata;
- bcd.dv_cache = BC(dev).bc_bcache;
-
- return (bcache_strategy(&bcd, rw, dblk, size, buf, rsize));
-}
-
-static int
-bc_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
- char *buf, size_t *rsize)
-{
- struct i386_devdesc *dev;
- int unit;
- int blks;
-
- if (size % BIOSCD_SECSIZE)
- return (EINVAL);
-
- if ((rw & F_MASK) != F_READ)
- return(EROFS);
- dev = (struct i386_devdesc *)devdata;
- unit = dev->dd.d_unit;
- blks = size / BIOSCD_SECSIZE;
- if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
- return (EINVAL);
- dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
- DEBUG("read %d from %lld to %p", blks, dblk, buf);
-
- if (rsize)
- *rsize = 0;
- if ((blks = bc_read(unit, dblk, blks, buf)) < 0) {
- DEBUG("read error");
- return (EIO);
- } else {
- if (size / BIOSCD_SECSIZE > blks) {
- if (rsize)
- *rsize = blks * BIOSCD_SECSIZE;
- return (0);
- }
- }
- if (rsize)
- *rsize = size;
- return (0);
-}
-
-/* return negative value for an error, otherwise blocks read */
-static int
-bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
-{
- u_int maxfer, resid, result, retry, x;
- caddr_t bbuf, p, xp;
- static struct edd_packet packet;
- int biosdev;
-#ifdef DISK_DEBUG
- int error;
-#endif
-
- /* Just in case some idiot actually tries to read -1 blocks... */
- if (blks < 0)
- return (-1);
-
- /* If nothing to do, just return succcess. */
- if (blks == 0)
- return (0);
-
- /* Decide whether we have to bounce */
- if (VTOP(dest) >> 20 != 0) {
- /*
- * The destination buffer is above first 1MB of
- * physical memory so we have to arrange a suitable
- * bounce buffer.
- */
- x = V86_IO_BUFFER_SIZE / BIOSCD_SECSIZE;
- x = min(x, (unsigned)blks);
- bbuf = PTOV(V86_IO_BUFFER);
- maxfer = x;
- } else {
- bbuf = NULL;
- maxfer = 0;
- }
-
- biosdev = bc_unit2bios(unit);
- resid = blks;
- p = dest;
-
- while (resid > 0) {
- if (bbuf)
- xp = bbuf;
- else
- xp = p;
- x = resid;
- if (maxfer > 0)
- x = min(x, maxfer);
-
- /*
- * Loop retrying the operation a couple of times. The BIOS
- * may also retry.
- */
- for (retry = 0; retry < 3; retry++) {
- /* If retrying, reset the drive */
- if (retry > 0) {
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0;
- v86.edx = biosdev;
- v86int();
- }
-
- packet.len = sizeof(struct edd_packet);
- packet.count = x;
- packet.off = VTOPOFF(xp);
- packet.seg = VTOPSEG(xp);
- packet.lba = dblk;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x4200;
- v86.edx = biosdev;
- v86.ds = VTOPSEG(&packet);
- v86.esi = VTOPOFF(&packet);
- v86int();
- result = V86_CY(v86.efl);
- if (result == 0)
- break;
- /* fall back to 1 sector read */
- x = 1;
- }
-
-#ifdef DISK_DEBUG
- error = (v86.eax >> 8) & 0xff;
-#endif
- DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p,
- VTOP(p), result ? "failed" : "ok");
- DEBUG("unit %d status 0x%x", unit, error);
-
- /* still an error? break off */
- if (result != 0)
- break;
-
- if (bbuf != NULL)
- bcopy(bbuf, p, x * BIOSCD_SECSIZE);
- p += (x * BIOSCD_SECSIZE);
- dblk += x;
- resid -= x;
- }
-
-/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
-
- if (blks - resid == 0)
- return (-1); /* read failed */
-
- return (blks - resid);
-}
-
-/*
- * Return a suitable dev_t value for (dev).
- */
-int
-bc_getdev(struct i386_devdesc *dev)
-{
- int biosdev, unit;
- int major;
- int rootdev;
-
- unit = dev->dd.d_unit;
- biosdev = bc_unit2bios(unit);
- DEBUG("unit %d BIOS device %d", unit, biosdev);
- if (biosdev == -1) /* not a BIOS device */
- return(-1);
-
- /*
- * XXX: Need to examine device spec here to figure out if SCSI or
- * ATAPI. No idea on how to figure out device number. All we can
- * really pass to the kernel is what bus and device on which bus we
- * were booted from, which dev_t isn't well suited to since those
- * number don't match to unit numbers very well. We may just need
- * to engage in a hack where we pass -C to the boot args if we are
- * the boot device.
- */
- major = ACDMAJOR;
- unit = 0; /* XXX */
-
- /* XXX: Assume partition 'a'. */
- rootdev = MAKEBOOTDEV(major, 0, unit, 0);
- DEBUG("dev is 0x%x\n", rootdev);
- return(rootdev);
-}
Index: head/stand/i386/libi386/biosdisk.c
===================================================================
--- head/stand/i386/libi386/biosdisk.c
+++ head/stand/i386/libi386/biosdisk.c
@@ -40,9 +40,11 @@
#include <sys/disk.h>
#include <sys/limits.h>
+#include <sys/queue.h>
#include <stand.h>
#include <machine/bootinfo.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <bootstrap.h>
#include <btxv86.h>
@@ -59,6 +61,8 @@
#define WFDMAJOR 1
#define FDMAJOR 2
#define DAMAJOR 4
+#define ACDMAJOR 117
+#define CDMAJOR 15
#ifdef DISK_DEBUG
#define DEBUG(fmt, args...) printf("%s: " fmt "\n", __func__, ## args)
@@ -66,12 +70,27 @@
#define DEBUG(fmt, args...)
#endif
+struct specification_packet {
+ uint8_t sp_size;
+ uint8_t sp_bootmedia;
+ uint8_t sp_drive;
+ uint8_t sp_controller;
+ uint32_t sp_lba;
+ uint16_t sp_devicespec;
+ uint16_t sp_buffersegment;
+ uint16_t sp_loadsegment;
+ uint16_t sp_sectorcount;
+ uint16_t sp_cylsec;
+ uint8_t sp_head;
+};
+
/*
* List of BIOS devices, translation from disk unit number to
* BIOS unit number.
*/
-static struct bdinfo
+typedef struct bdinfo
{
+ STAILQ_ENTRY(bdinfo) bd_link; /* link in device list */
int bd_unit; /* BIOS unit number */
int bd_cyl; /* BIOS geometry */
int bd_hds;
@@ -83,25 +102,30 @@
#define BD_MODEEDD (BD_MODEEDD1 | BD_MODEEDD3)
#define BD_MODEMASK 0x0003
#define BD_FLOPPY 0x0004
-#define BD_NO_MEDIA 0x0008
+#define BD_CDROM 0x0008
+#define BD_NO_MEDIA 0x0010
int bd_type; /* BIOS 'drive type' (floppy only) */
uint16_t bd_sectorsize; /* Sector size */
uint64_t bd_sectors; /* Disk size */
int bd_open; /* reference counter */
void *bd_bcache; /* buffer cache data */
-} bdinfo [MAXBDDEV];
-static int nbdinfo = 0;
+} bdinfo_t;
-#define BD(dev) (bdinfo[(dev)->dd.d_unit])
#define BD_RD 0
#define BD_WR 1
-static void bd_io_workaround(struct disk_devdesc *dev);
+typedef STAILQ_HEAD(bdinfo_list, bdinfo) bdinfo_list_t;
+static bdinfo_list_t fdinfo = STAILQ_HEAD_INITIALIZER(fdinfo);
+static bdinfo_list_t cdinfo = STAILQ_HEAD_INITIALIZER(cdinfo);
+static bdinfo_list_t hdinfo = STAILQ_HEAD_INITIALIZER(hdinfo);
-static int bd_io(struct disk_devdesc *, daddr_t, int, caddr_t, int);
-static int bd_int13probe(struct bdinfo *bd);
+static void bd_io_workaround(bdinfo_t *);
+static int bd_io(struct disk_devdesc *, bdinfo_t *, daddr_t, int, caddr_t, int);
+static bool bd_int13probe(bdinfo_t *);
static int bd_init(void);
+static int cd_init(void);
+static int fd_init(void);
static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
char *buf, size_t *rsize);
static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size,
@@ -110,42 +134,120 @@
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);
+static int cd_print(int verbose);
+static int fd_print(int verbose);
-struct devsw biosdisk = {
- "disk",
- DEVT_DISK,
- bd_init,
- bd_strategy,
- bd_open,
- bd_close,
- bd_ioctl,
- bd_print,
- NULL
+struct devsw biosfd = {
+ .dv_name = "fd",
+ .dv_type = DEVT_FD,
+ .dv_init = fd_init,
+ .dv_strategy = bd_strategy,
+ .dv_open = bd_open,
+ .dv_close = bd_close,
+ .dv_ioctl = bd_ioctl,
+ .dv_print = fd_print,
+ .dv_cleanup = NULL
};
+struct devsw bioscd = {
+ .dv_name = "cd",
+ .dv_type = DEVT_CD,
+ .dv_init = cd_init,
+ .dv_strategy = bd_strategy,
+ .dv_open = bd_open,
+ .dv_close = bd_close,
+ .dv_ioctl = bd_ioctl,
+ .dv_print = cd_print,
+ .dv_cleanup = NULL
+};
+
+struct devsw bioshd = {
+ .dv_name = "disk",
+ .dv_type = DEVT_DISK,
+ .dv_init = bd_init,
+ .dv_strategy = bd_strategy,
+ .dv_open = bd_open,
+ .dv_close = bd_close,
+ .dv_ioctl = bd_ioctl,
+ .dv_print = bd_print,
+ .dv_cleanup = NULL
+};
+
+static bdinfo_list_t *
+bd_get_bdinfo_list(struct devsw *dev)
+{
+ if (dev->dv_type == DEVT_DISK)
+ return (&hdinfo);
+ if (dev->dv_type == DEVT_CD)
+ return (&cdinfo);
+ if (dev->dv_type == DEVT_FD)
+ return (&fdinfo);
+ return (NULL);
+}
+
+/* XXX this gets called way way too often, investigate */
+static bdinfo_t *
+bd_get_bdinfo(struct devdesc *dev)
+{
+ bdinfo_list_t *bdi;
+ bdinfo_t *bd = NULL;
+ int unit;
+
+ bdi = bd_get_bdinfo_list(dev->d_dev);
+ if (bdi == NULL)
+ return (bd);
+
+ unit = 0;
+ STAILQ_FOREACH(bd, bdi, bd_link) {
+ if (unit == dev->d_unit)
+ return (bd);
+ unit++;
+ }
+ return (bd);
+}
+
/*
* Translate between BIOS device numbers and our private unit numbers.
*/
int
bd_bios2unit(int biosdev)
{
- int i;
+ bdinfo_list_t *bdi[] = { &fdinfo, &cdinfo, &hdinfo, NULL };
+ bdinfo_t *bd;
+ int i, unit;
DEBUG("looking for bios device 0x%x", biosdev);
- for (i = 0; i < nbdinfo; i++) {
- DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit);
- if (bdinfo[i].bd_unit == biosdev)
- return (i);
+ for (i = 0; bdi[i] != NULL; i++) {
+ unit = 0;
+ STAILQ_FOREACH(bd, bdi[i], bd_link) {
+ if (bd->bd_unit == biosdev) {
+ DEBUG("bd unit %d is BIOS device 0x%x", unit,
+ bd->bd_unit);
+ return (unit);
+ }
+ unit++;
+ }
}
return (-1);
}
int
-bd_unit2bios(int unit)
+bd_unit2bios(struct i386_devdesc *dev)
{
+ bdinfo_list_t *bdi;
+ bdinfo_t *bd;
+ int unit;
- if ((unit >= 0) && (unit < nbdinfo))
- return (bdinfo[unit].bd_unit);
+ bdi = bd_get_bdinfo_list(dev->dd.d_dev);
+ if (bdi == NULL)
+ return (-1);
+
+ unit = 0;
+ STAILQ_FOREACH(bd, bdi, bd_link) {
+ if (unit == dev->dd.d_unit)
+ return (bd->bd_unit);
+ unit++;
+ }
return (-1);
}
@@ -153,42 +255,128 @@
* Quiz the BIOS for disk devices, save a little info about them.
*/
static int
-bd_init(void)
+fd_init(void)
{
- int base, unit, nfd = 0;
+ int unit;
+ bdinfo_t *bd;
- /* sequence 0, 0x80 */
- for (base = 0; base <= 0x80; base += 0x80) {
- for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
-#ifndef VIRTUALBOX
- /*
- * Check the BIOS equipment list for number
- * of fixed disks.
- */
- if (base == 0x80 &&
- (nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES)))
- break;
-#endif
- bdinfo[nbdinfo].bd_open = 0;
- bdinfo[nbdinfo].bd_bcache = NULL;
- bdinfo[nbdinfo].bd_unit = unit;
- bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
- if (!bd_int13probe(&bdinfo[nbdinfo]))
- break;
+ for (unit = 0; unit < MAXBDDEV; unit++) {
+ if ((bd = calloc(1, sizeof(*bd))) == NULL)
+ break;
+ bd->bd_flags = BD_FLOPPY;
+ bd->bd_unit = unit;
+ if (!bd_int13probe(bd)) {
+ free(bd);
+ break;
+ }
+ if (bd->bd_sectors == 0)
+ bd->bd_flags |= BD_NO_MEDIA;
- /* XXX we need "disk aliases" to make this simpler */
- printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ?
- ('A' + unit): ('C' + unit - 0x80), nbdinfo);
- nbdinfo++;
- if (base == 0x80)
- nfd++;
+ printf("BIOS drive %c: is %s%d\n", ('A' + unit),
+ biosfd.dv_name, unit);
+
+ STAILQ_INSERT_TAIL(&fdinfo, bd, bd_link);
+ }
+
+ bcache_add_dev(unit);
+ return (0);
+}
+
+static int
+bd_init(void)
+{
+ int base, unit;
+ bdinfo_t *bd;
+
+ base = 0x80;
+ for (unit = 0; unit < *(unsigned char *)PTOV(BIOS_NUMDRIVES); unit++) {
+ /*
+ * Check the BIOS equipment list for number of fixed disks.
+ */
+ if ((bd = calloc(1, sizeof(*bd))) == NULL)
+ break;
+ bd->bd_unit = base + unit;
+ if (!bd_int13probe(bd)) {
+ free(bd);
+ break;
}
+
+ printf("BIOS drive %c: is %s%d\n", ('C' + unit),
+ bioshd.dv_name, unit);
+
+ STAILQ_INSERT_TAIL(&hdinfo, bd, bd_link);
}
- bcache_add_dev(nbdinfo);
+ bcache_add_dev(unit);
return (0);
}
/*
+ * We can't quiz, we have to be told what device to use, so this function
+ * doesn't do anything. Instead, the loader calls bc_add() with the BIOS
+ * device number to add.
+ */
+static int
+cd_init(void)
+{
+
+ return (0);
+}
+
+int
+bc_add(int biosdev)
+{
+ bdinfo_t *bd;
+ struct specification_packet bc_sp;
+ int nbcinfo = 0;
+
+ if (!STAILQ_EMPTY(&cdinfo))
+ return (-1);
+
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0x4b01;
+ v86.edx = biosdev;
+ v86.ds = VTOPSEG(&bc_sp);
+ v86.esi = VTOPOFF(&bc_sp);
+ v86int();
+ if ((v86.eax & 0xff00) != 0)
+ return (-1);
+
+ if ((bd = calloc(1, sizeof(*bd))) == NULL)
+ return (-1);
+
+ bd->bd_flags = BD_CDROM;
+ bd->bd_unit = biosdev;
+
+ /*
+ * Ignore result from bd_int13probe(), we will use local
+ * workaround below.
+ */
+ (void)bd_int13probe(bd);
+
+ if (bd->bd_cyl == 0) {
+ bd->bd_cyl = ((bc_sp.sp_cylsec & 0xc0) << 2) +
+ ((bc_sp.sp_cylsec & 0xff00) >> 8) + 1;
+ }
+ if (bd->bd_hds == 0)
+ bd->bd_hds = bc_sp.sp_head + 1;
+ if (bd->bd_sec == 0)
+ bd->bd_sec = bc_sp.sp_cylsec & 0x3f;
+ if (bd->bd_sectors == 0)
+ bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec;
+
+ /* Still no size? use 7.961GB */
+ if (bd->bd_sectors == 0)
+ bd->bd_sectors = 4173824;
+
+ STAILQ_INSERT_TAIL(&cdinfo, bd, bd_link);
+ printf("BIOS CD is cd%d\n", nbcinfo);
+ nbcinfo++;
+ bcache_add_dev(nbcinfo); /* register cd device in bcache */
+ return(0);
+}
+
+/*
* Return EDD version or 0 if EDD is not supported on this drive.
*/
static int
@@ -306,11 +494,10 @@
/*
* Try to detect a device supported by the legacy int13 BIOS
*/
-static int
-bd_int13probe(struct bdinfo *bd)
+static bool
+bd_int13probe(bdinfo_t *bd)
{
- int edd;
- int ret;
+ int edd, ret;
bd->bd_flags &= ~BD_NO_MEDIA;
@@ -340,7 +527,7 @@
v86.edx = bd->bd_unit;
v86int();
if (V86_CY(v86.efl) || (v86.eax & 0x300) == 0)
- return (0);
+ return (false);
}
ret = 1;
@@ -354,7 +541,6 @@
bd->bd_cyl = 80;
bd->bd_hds = 2;
bd->bd_sec = 18;
- bd->bd_type = 4;
bd->bd_sectors = 2880;
/* Since we are there, there most likely is no media */
bd->bd_flags |= BD_NO_MEDIA;
@@ -362,6 +548,10 @@
}
if (ret != 0) {
+ /* CD is special case, bc_add() has its own fallback. */
+ if ((bd->bd_flags & BD_CDROM) != 0)
+ return (true);
+
if (bd->bd_sectors != 0 && edd != 0) {
bd->bd_sec = 63;
bd->bd_hds = 255;
@@ -369,9 +559,18 @@
(bd->bd_sectors + bd->bd_sec * bd->bd_hds - 1) /
bd->bd_sec * bd->bd_hds;
} else {
+ const char *dv_name;
+
+ if ((bd->bd_flags & BD_FLOPPY) != 0)
+ dv_name = biosfd.dv_name;
+ else if ((bd->bd_flags & BD_CDROM) != 0)
+ dv_name = bioscd.dv_name;
+ else
+ dv_name = bioshd.dv_name;
+
printf("Can not get information about %s unit %#x\n",
- biosdisk.dv_name, bd->bd_unit);
- return (0);
+ dv_name, bd->bd_unit);
+ return (false);
}
}
@@ -383,54 +582,86 @@
if (bd->bd_sectors == 0)
bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec;
- DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
+ DEBUG("unit 0x%x geometry %d/%d/%d\n", bd->bd_unit, bd->bd_cyl,
bd->bd_hds, bd->bd_sec);
- return (1);
+ return (true);
}
+static int
+bd_count(bdinfo_list_t *bdi)
+{
+ bdinfo_t *bd;
+ int i;
+
+ i = 0;
+ STAILQ_FOREACH(bd, bdi, bd_link)
+ i++;
+ return (i);
+}
+
/*
* Print information about disks
*/
static int
-bd_print(int verbose)
+bd_print_common(struct devsw *dev, bdinfo_list_t *bdi, int verbose)
{
- static char line[80];
- struct disk_devdesc dev;
+ char line[80];
+ struct disk_devdesc devd;
+ bdinfo_t *bd;
int i, ret = 0;
+ char drive;
- if (nbdinfo == 0)
+ if (STAILQ_EMPTY(bdi))
return (0);
- printf("%s devices:", biosdisk.dv_name);
+ printf("%s devices:", dev->dv_name);
if ((ret = pager_output("\n")) != 0)
return (ret);
- for (i = 0; i < nbdinfo; i++) {
+ i = -1;
+ STAILQ_FOREACH(bd, bdi, bd_link) {
+ i++;
+
+ switch (dev->dv_type) {
+ case DEVT_FD:
+ drive = 'A';
+ break;
+ case DEVT_CD:
+ drive = 'C' + bd_count(&hdinfo);
+ break;
+ default:
+ drive = 'C';
+ break;
+ }
+
snprintf(line, sizeof(line),
- " disk%d: BIOS drive %c (%s%ju X %u):\n", i,
- (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit):
- ('C' + bdinfo[i].bd_unit - 0x80),
- (bdinfo[i].bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA ?
+ " %s%d: BIOS drive %c (%s%ju X %u):\n",
+ dev->dv_name, i, drive + i,
+ (bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA ?
"no media, " : "",
- (uintmax_t)bdinfo[i].bd_sectors,
- bdinfo[i].bd_sectorsize);
+ (uintmax_t)bd->bd_sectors,
+ bd->bd_sectorsize);
if ((ret = pager_output(line)) != 0)
break;
- if ((bdinfo[i].bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+ if ((bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
continue;
- dev.dd.d_dev = &biosdisk;
- dev.dd.d_unit = i;
- dev.d_slice = -1;
- dev.d_partition = -1;
- if (disk_open(&dev,
- bdinfo[i].bd_sectorsize * bdinfo[i].bd_sectors,
- bdinfo[i].bd_sectorsize) == 0) {
- snprintf(line, sizeof(line), " disk%d", i);
- ret = disk_print(&dev, line, verbose);
- disk_close(&dev);
+ if (dev->dv_type != DEVT_DISK)
+ continue;
+
+ devd.dd.d_dev = dev;
+ devd.dd.d_unit = i;
+ devd.d_slice = -1;
+ devd.d_partition = -1;
+ if (disk_open(&devd,
+ bd->bd_sectorsize * bd->bd_sectors,
+ bd->bd_sectorsize) == 0) {
+ snprintf(line, sizeof(line), " %s%d",
+ dev->dv_name, i);
+ ret = disk_print(&devd, line, verbose);
+ disk_close(&devd);
if (ret != 0)
break;
}
@@ -438,6 +669,24 @@
return (ret);
}
+static int
+fd_print(int verbose)
+{
+ return (bd_print_common(&biosfd, &fdinfo, verbose));
+}
+
+static int
+bd_print(int verbose)
+{
+ return (bd_print_common(&bioshd, &hdinfo, verbose));
+}
+
+static int
+cd_print(int verbose)
+{
+ return (bd_print_common(&bioscd, &cdinfo, verbose));
+}
+
/*
* Read disk size from partition.
* This is needed to work around buggy BIOS systems returning
@@ -448,21 +697,26 @@
static uint64_t
bd_disk_get_sectors(struct disk_devdesc *dev)
{
+ bdinfo_t *bd;
struct disk_devdesc disk;
uint64_t size;
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL)
+ return (0);
+
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;
- size = BD(dev).bd_sectors * BD(dev).bd_sectorsize;
- if (disk_open(&disk, size, BD(dev).bd_sectorsize) == 0) {
+ size = bd->bd_sectors * bd->bd_sectorsize;
+ if (disk_open(&disk, size, bd->bd_sectorsize) == 0) {
(void) disk_ioctl(&disk, DIOCGMEDIASIZE, &size);
disk_close(&disk);
}
- return (size / BD(dev).bd_sectorsize);
+ return (size / bd->bd_sectorsize);
}
/*
@@ -478,6 +732,7 @@
static int
bd_open(struct open_file *f, ...)
{
+ bdinfo_t *bd;
struct disk_devdesc *dev;
va_list ap;
int rc;
@@ -486,29 +741,33 @@
dev = va_arg(ap, struct disk_devdesc *);
va_end(ap);
- if (dev->dd.d_unit < 0 || dev->dd.d_unit >= nbdinfo)
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL)
return (EIO);
- if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA) {
- if (!bd_int13probe(&BD(dev)))
+ if ((bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA) {
+ if (!bd_int13probe(bd))
return (EIO);
- if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+ if ((bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
return (EIO);
}
- if (BD(dev).bd_bcache == NULL)
- BD(dev).bd_bcache = bcache_allocate();
+ if (bd->bd_bcache == NULL)
+ bd->bd_bcache = bcache_allocate();
- if (BD(dev).bd_open == 0)
- BD(dev).bd_sectors = bd_disk_get_sectors(dev);
- BD(dev).bd_open++;
+ if (bd->bd_open == 0)
+ bd->bd_sectors = bd_disk_get_sectors(dev);
+ bd->bd_open++;
- rc = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
- BD(dev).bd_sectorsize);
- if (rc != 0) {
- BD(dev).bd_open--;
- if (BD(dev).bd_open == 0) {
- bcache_free(BD(dev).bd_bcache);
- BD(dev).bd_bcache = NULL;
+ rc = 0;
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ rc = disk_open(dev, bd->bd_sectors * bd->bd_sectorsize,
+ bd->bd_sectorsize);
+ if (rc != 0) {
+ bd->bd_open--;
+ if (bd->bd_open == 0) {
+ bcache_free(bd->bd_bcache);
+ bd->bd_bcache = NULL;
+ }
}
}
return (rc);
@@ -518,34 +777,48 @@
bd_close(struct open_file *f)
{
struct disk_devdesc *dev;
+ bdinfo_t *bd;
+ int rc = 0;
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;
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL)
+ return (EIO);
+
+ bd->bd_open--;
+ if (bd->bd_open == 0) {
+ bcache_free(bd->bd_bcache);
+ bd->bd_bcache = NULL;
}
- return (disk_close(dev));
+ if (dev->dd.d_dev->dv_type == DEVT_DISK)
+ rc = disk_close(dev);
+ return (rc);
}
static int
bd_ioctl(struct open_file *f, u_long cmd, void *data)
{
+ bdinfo_t *bd;
struct disk_devdesc *dev;
int rc;
dev = (struct disk_devdesc *)f->f_devdata;
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL)
+ return (EIO);
- rc = disk_ioctl(dev, cmd, data);
- if (rc != ENOTTY)
- return (rc);
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ rc = disk_ioctl(dev, cmd, data);
+ if (rc != ENOTTY)
+ return (rc);
+ }
switch (cmd) {
case DIOCGSECTORSIZE:
- *(uint32_t *)data = BD(dev).bd_sectorsize;
+ *(uint32_t *)data = bd->bd_sectorsize;
break;
case DIOCGMEDIASIZE:
- *(uint64_t *)data = BD(dev).bd_sectors * BD(dev).bd_sectorsize;
+ *(uint64_t *)data = bd->bd_sectors * bd->bd_sectorsize;
break;
default:
return (ENOTTY);
@@ -557,14 +830,27 @@
bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
char *buf, size_t *rsize)
{
+ bdinfo_t *bd;
struct bcache_devdata bcd;
struct disk_devdesc *dev;
+ daddr_t offset;
dev = (struct disk_devdesc *)devdata;
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL)
+ return (EINVAL);
+
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,
+ bcd.dv_cache = bd->bd_bcache;
+
+ offset = 0;
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+
+ offset = dev->d_offset * bd->bd_sectorsize;
+ offset /= BIOSDISK_SECSIZE;
+ }
+ return (bcache_strategy(&bcd, rw, dblk + offset, size,
buf, rsize));
}
@@ -573,12 +859,14 @@
char *buf, size_t *rsize)
{
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
- uint64_t disk_blocks, offset;
+ bdinfo_t *bd;
+ uint64_t disk_blocks, offset, d_offset;
size_t blks, blkoff, bsize, rest;
caddr_t bbuf;
int rc;
- if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL || (bd->bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
return (EIO);
/*
@@ -596,8 +884,8 @@
DEBUG("open_disk %p", dev);
offset = dblk * BIOSDISK_SECSIZE;
- dblk = offset / BD(dev).bd_sectorsize;
- blkoff = offset % BD(dev).bd_sectorsize;
+ dblk = offset / bd->bd_sectorsize;
+ blkoff = offset % bd->bd_sectorsize;
/*
* Check the value of the size argument. We do have quite small
@@ -610,8 +898,8 @@
return (EIO);
}
- blks = size / BD(dev).bd_sectorsize;
- if (blks == 0 || (size % BD(dev).bd_sectorsize) != 0)
+ blks = size / bd->bd_sectorsize;
+ if (blks == 0 || (size % bd->bd_sectorsize) != 0)
blks++;
if (dblk > dblk + blks)
@@ -624,44 +912,48 @@
* Get disk blocks, this value is either for whole disk or for
* partition.
*/
- if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
- /* 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;
+ d_offset = 0;
+ disk_blocks = 0;
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
+ /* DIOCGMEDIASIZE does return bytes. */
+ disk_blocks /= bd->bd_sectorsize;
+ }
+ d_offset = dev->d_offset;
}
+ if (disk_blocks == 0)
+ disk_blocks = bd->bd_sectors - d_offset;
/* Validate source block address. */
- if (dblk < dev->d_offset || dblk >= dev->d_offset + disk_blocks)
+ if (dblk < d_offset || dblk >= 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;
+ if (dblk + blks >= d_offset + disk_blocks) {
+ blks = d_offset + disk_blocks - dblk;
+ size = blks * bd->bd_sectorsize;
DEBUG("short I/O %d", blks);
}
- if (V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize == 0)
+ if (V86_IO_BUFFER_SIZE / bd->bd_sectorsize == 0)
panic("BUG: Real mode buffer is too small");
bbuf = PTOV(V86_IO_BUFFER);
rest = size;
while (blks > 0) {
- int x = min(blks, V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize);
+ int x = min(blks, V86_IO_BUFFER_SIZE / bd->bd_sectorsize);
switch (rw & F_MASK) {
case F_READ:
DEBUG("read %d from %lld to %p", x, dblk, buf);
- bsize = BD(dev).bd_sectorsize * x - blkoff;
+ bsize = bd->bd_sectorsize * x - blkoff;
if (rest < bsize)
bsize = rest;
- if ((rc = bd_io(dev, dblk, x, bbuf, BD_RD)) != 0)
+ if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0)
return (EIO);
bcopy(bbuf + blkoff, buf, bsize);
@@ -674,27 +966,27 @@
* bbuf.
*/
x = 1;
- bsize = BD(dev).bd_sectorsize - blkoff;
+ bsize = bd->bd_sectorsize - blkoff;
bsize = min(bsize, rest);
- rc = bd_io(dev, dblk, x, bbuf, BD_RD);
- } else if (rest < BD(dev).bd_sectorsize) {
+ rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD);
+ } else if (rest < bd->bd_sectorsize) {
/*
* The remaining block is not full
* sector. Read 1 sector to bbuf.
*/
x = 1;
bsize = rest;
- rc = bd_io(dev, dblk, x, bbuf, BD_RD);
+ rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD);
} else {
/* We can write full sector(s). */
- bsize = BD(dev).bd_sectorsize * x;
+ bsize = bd->bd_sectorsize * x;
}
/*
* Put your Data In, Put your Data out,
* Put your Data In, and shake it all about
*/
bcopy(buf, bbuf + blkoff, bsize);
- if ((rc = bd_io(dev, dblk, x, bbuf, BD_WR)) != 0)
+ if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_WR)) != 0)
return (EIO);
break;
@@ -716,7 +1008,7 @@
}
static int
-bd_edd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
+bd_edd_io(bdinfo_t *bd, daddr_t dblk, int blks, caddr_t dest,
int dowrite)
{
static struct edd_packet packet;
@@ -733,7 +1025,7 @@
v86.eax = 0x4300;
else
v86.eax = 0x4200;
- v86.edx = BD(dev).bd_unit;
+ v86.edx = bd->bd_unit;
v86.ds = VTOPSEG(&packet);
v86.esi = VTOPOFF(&packet);
v86int();
@@ -743,17 +1035,17 @@
}
static int
-bd_chs_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
+bd_chs_io(bdinfo_t *bd, daddr_t dblk, int blks, caddr_t dest,
int dowrite)
{
uint32_t x, bpc, cyl, hd, sec;
- bpc = BD(dev).bd_sec * BD(dev).bd_hds; /* blocks per cylinder */
+ bpc = bd->bd_sec * bd->bd_hds; /* blocks per cylinder */
x = dblk;
cyl = x / bpc; /* block # / blocks per cylinder */
x %= bpc; /* block offset into cylinder */
- hd = x / BD(dev).bd_sec; /* offset / blocks per track */
- sec = x % BD(dev).bd_sec; /* offset into track */
+ hd = x / bd->bd_sec; /* offset / blocks per track */
+ sec = x % bd->bd_sec; /* offset into track */
/* correct sector number for 1-based BIOS numbering */
sec++;
@@ -770,7 +1062,7 @@
else
v86.eax = 0x200 | blks;
v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec;
- v86.edx = (hd << 8) | BD(dev).bd_unit;
+ v86.edx = (hd << 8) | bd->bd_unit;
v86.es = VTOPSEG(dest);
v86.ebx = VTOPOFF(dest);
v86int();
@@ -780,16 +1072,16 @@
}
static void
-bd_io_workaround(struct disk_devdesc *dev)
+bd_io_workaround(bdinfo_t *bd)
{
uint8_t buf[8 * 1024];
- bd_edd_io(dev, 0xffffffff, 1, (caddr_t)buf, BD_RD);
+ bd_edd_io(bd, 0xffffffff, 1, (caddr_t)buf, BD_RD);
}
static int
-bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
- int dowrite)
+bd_io(struct disk_devdesc *dev, bdinfo_t *bd, daddr_t dblk, int blks,
+ caddr_t dest, int dowrite)
{
int result, retry;
@@ -809,20 +1101,20 @@
* may also retry.
*/
if (dowrite == BD_RD && dblk >= 0x100000000)
- bd_io_workaround(dev);
+ bd_io_workaround(bd);
for (retry = 0; retry < 3; retry++) {
- if (BD(dev).bd_flags & BD_MODEEDD)
- result = bd_edd_io(dev, dblk, blks, dest, dowrite);
+ if (bd->bd_flags & BD_MODEEDD)
+ result = bd_edd_io(bd, dblk, blks, dest, dowrite);
else
- result = bd_chs_io(dev, dblk, blks, dest, dowrite);
+ result = bd_chs_io(bd, dblk, blks, dest, dowrite);
if (result == 0) {
- if (BD(dev).bd_flags & BD_NO_MEDIA)
- BD(dev).bd_flags &= ~BD_NO_MEDIA;
+ if (bd->bd_flags & BD_NO_MEDIA)
+ bd->bd_flags &= ~BD_NO_MEDIA;
break;
}
- bd_reset_disk(BD(dev).bd_unit);
+ bd_reset_disk(bd->bd_unit);
/*
* Error codes:
@@ -832,12 +1124,12 @@
* There is no reason to repeat the IO with errors above.
*/
if (result == 0x20 || result == 0x31 || result == 0x80) {
- BD(dev).bd_flags |= BD_NO_MEDIA;
+ bd->bd_flags |= BD_NO_MEDIA;
break;
}
}
- if (result != 0 && (BD(dev).bd_flags & BD_NO_MEDIA) == 0) {
+ if (result != 0 && (bd->bd_flags & BD_NO_MEDIA) == 0) {
if (dowrite == BD_WR) {
printf("%s%d: Write %d sector(s) from %p (0x%x) "
"to %lld: 0x%x\n", dev->dd.d_dev->dv_name,
@@ -893,26 +1185,40 @@
bd_getdev(struct i386_devdesc *d)
{
struct disk_devdesc *dev;
+ bdinfo_t *bd;
int biosdev;
int major;
int rootdev;
char *nip, *cp;
- int i, unit;
+ int i, unit, slice, partition;
+ /* XXX: Assume partition 'a'. */
+ slice = 0;
+ partition = 0;
+
dev = (struct disk_devdesc *)d;
- biosdev = bd_unit2bios(dev->dd.d_unit);
+ bd = bd_get_bdinfo(&dev->dd);
+ if (bd == NULL)
+ return (-1);
+
+ biosdev = bd_unit2bios(d);
DEBUG("unit %d BIOS device %d", dev->dd.d_unit, biosdev);
if (biosdev == -1) /* not a BIOS device */
return (-1);
- if (disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
- BD(dev).bd_sectorsize) != 0) /* oops, not a viable device */
- return (-1);
- else
- disk_close(dev);
+ if (dev->dd.d_dev->dv_type == DEVT_DISK) {
+ if (disk_open(dev, bd->bd_sectors * bd->bd_sectorsize,
+ bd->bd_sectorsize) != 0) /* oops, not a viable device */
+ return (-1);
+ else
+ disk_close(dev);
+ slice = dev->d_slice + 1;
+ partition = dev->d_partition;
+ }
+
if (biosdev < 0x80) {
/* floppy (or emulated floppy) or ATAPI device */
- if (bdinfo[dev->dd.d_unit].bd_type == DT_ATAPI) {
+ if (bd->bd_type == DT_ATAPI) {
/* is an ATAPI disk */
major = WFDMAJOR;
} else {
@@ -926,6 +1232,20 @@
/* default root disk unit number */
unit = biosdev & 0x7f;
+ if (dev->dd.d_dev->dv_type == DEVT_CD) {
+ /*
+ * XXX: Need to examine device spec here to figure out if
+ * SCSI or ATAPI. No idea on how to figure out device number.
+ * All we can really pass to the kernel is what bus and device
+ * on which bus we were booted from, which dev_t isn't well
+ * suited to since those number don't match to unit numbers
+ * very well. We may just need to engage in a hack where
+ * we pass -C to the boot args if we are the boot device.
+ */
+ major = ACDMAJOR;
+ unit = 0; /* XXX */
+ }
+
/* XXX a better kludge to set the root disk unit number */
if ((nip = getenv("root_disk_unit")) != NULL) {
i = strtol(nip, &cp, 0);
@@ -934,7 +1254,7 @@
unit = i;
}
- rootdev = MAKEBOOTDEV(major, dev->d_slice + 1, unit, dev->d_partition);
+ rootdev = MAKEBOOTDEV(major, slice, unit, partition);
DEBUG("dev is 0x%x\n", rootdev);
return (rootdev);
}
Index: head/stand/i386/libi386/bootinfo32.c
===================================================================
--- head/stand/i386/libi386/bootinfo32.c
+++ head/stand/i386/libi386/bootinfo32.c
@@ -176,14 +176,9 @@
switch(rootdev->dd.d_dev->dv_type) {
case DEVT_CD:
- /* Pass in BIOS device number. */
- bi.bi_bios_dev = bc_unit2bios(rootdev->dd.d_unit);
- bootdevnr = bc_getdev(rootdev);
- break;
-
case DEVT_DISK:
/* pass in the BIOS device number of the current disk */
- bi.bi_bios_dev = bd_unit2bios(rootdev->dd.d_unit);
+ bi.bi_bios_dev = bd_unit2bios(rootdev);
bootdevnr = bd_getdev(rootdev);
break;
Index: head/stand/i386/libi386/libi386.h
===================================================================
--- head/stand/i386/libi386/libi386.h
+++ head/stand/i386/libi386/libi386.h
@@ -91,17 +91,15 @@
/* exported devices XXX rename? */
extern struct devsw bioscd;
-extern struct devsw biosdisk;
+extern struct devsw biosfd;
+extern struct devsw bioshd;
extern struct devsw pxedisk;
extern struct fs_ops pxe_fsops;
int bc_add(int biosdev); /* Register CD booted from. */
-int bc_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */
-int bc_bios2unit(int biosdev); /* xlate BIOS device -> bioscd unit */
-int bc_unit2bios(int unit); /* xlate bioscd unit -> BIOS device */
uint32_t bd_getbigeom(int bunit); /* return geometry in bootinfo format */
int bd_bios2unit(int biosdev); /* xlate BIOS device -> biosdisk unit */
-int bd_unit2bios(int unit); /* xlate biosdisk unit -> BIOS device */
+int bd_unit2bios(struct i386_devdesc *); /* xlate biosdisk -> BIOS device */
int bd_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */
ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len);
Index: head/stand/i386/loader/chain.c
===================================================================
--- head/stand/i386/loader/chain.c
+++ head/stand/i386/loader/chain.c
@@ -113,7 +113,7 @@
relocater_data[0].dest = 0x7C00;
relocater_data[0].size = size;
- relocator_edx = bd_unit2bios(rootdev->dd.d_unit);
+ relocator_edx = bd_unit2bios(rootdev);
relocator_esi = relocater_size;
relocator_ds = 0;
relocator_es = 0;
Index: head/stand/i386/loader/conf.c
===================================================================
--- head/stand/i386/loader/conf.c
+++ head/stand/i386/loader/conf.c
@@ -51,8 +51,9 @@
/* Exported for libstand */
struct devsw *devsw[] = {
+ &biosfd,
&bioscd,
- &biosdisk,
+ &bioshd,
#if defined(LOADER_NFS_SUPPORT) || defined(LOADER_TFTP_SUPPORT)
&pxedisk,
#endif
Index: head/stand/i386/loader/main.c
===================================================================
--- head/stand/i386/loader/main.c
+++ head/stand/i386/loader/main.c
@@ -251,14 +251,14 @@
int biosdev = -1;
/* Assume we are booting from a BIOS disk by default */
- new_currdev.dd.d_dev = &biosdisk;
+ new_currdev.dd.d_dev = &bioshd;
/* new-style boot loaders such as pxeldr and cdldr */
if (kargs->bootinfo == 0) {
if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) {
/* we are booting from a CD with cdboot */
new_currdev.dd.d_dev = &bioscd;
- new_currdev.dd.d_unit = bc_bios2unit(initial_bootdev);
+ new_currdev.dd.d_unit = bd_bios2unit(initial_bootdev);
} else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) {
/* we are booting from pxeldr */
new_currdev.dd.d_dev = &pxedisk;
@@ -318,7 +318,7 @@
* If we are booting off of a BIOS disk and we didn't succeed in determining
* which one we booted off of, just use disk0: as a reasonable default.
*/
- if ((new_currdev.dd.d_dev->dv_type == biosdisk.dv_type) &&
+ if ((new_currdev.dd.d_dev->dv_type == bioshd.dv_type) &&
((new_currdev.dd.d_unit = bd_bios2unit(biosdev)) == -1)) {
printf("Can't work out which disk we are booting from.\n"
"Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev);
@@ -390,18 +390,16 @@
i386_zfs_probe(void)
{
char devname[32];
- int unit;
+ struct i386_devdesc dev;
/*
* Open all the disks we can find and see if we can reconstruct
* ZFS pools from them.
*/
- for (unit = 0; unit < MAXBDDEV; unit++) {
- if (bd_unit2bios(unit) == -1)
- break;
- if (bd_unit2bios(unit) < 0x80)
- continue;
- sprintf(devname, "disk%d:", unit);
+ dev.dd.d_dev = &bioshd;
+ for (dev.dd.d_unit = 0; bd_unit2bios(&dev) >= 0; dev.dd.d_unit++) {
+ snprintf(devname, sizeof(devname), "%s%d:", bioshd.dv_name,
+ dev.dd.d_unit);
zfs_probe_dev(devname, NULL);
}
}

File Metadata

Mime Type
text/plain
Expires
Sun, Aug 23, 12:31 AM (56 m, 6 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37115572
Default Alt Text
D17888.diff (42 KB)

Event Timeline