svn commit: r346474 - in stable/11/stand/i386: libi386 loader
Kyle Evans
kevans at FreeBSD.org
Sun Apr 21 03:27:13 UTC 2019
Author: kevans
Date: Sun Apr 21 03:27:12 2019
New Revision: 346474
URL: https://svnweb.freebsd.org/changeset/base/346474
Log:
MFC i386 stand cleanup: r337353-r337354, r337356, r337872, r337878, r337881,
r337890-r337891, r338188
r337353:
loader: cstyle cleanup for biosdisk.c
Also switch u_int to uint32_t. Also replace "write" by "dowrite".
No functional changes intended.
r337354:
loader: 337353 did miss to rename 2 write instances
2 write instances got somehow missed.
r337356:
loader: bd_open() should cleanup from disk_open() error
Since bd_open() does early increment for reference counter and bcache
allocation, it also should undo those in case of the error.
Also remove unused variables rdev, g_err.
r337872:
libi386: remove BD_SUPPORT_FRAGS
BD_SUPPORT_FRAGS is preprocessor knob to allow partial reads in bioscd/biosdisk
level. However, we already have support for partial reads in bcache, and there
is no need to have duplication via preprocessor controls.
Note that bioscd/biosdisk interface is assumed to perform IO in 512B blocks,
so the only translation we have to do is 512 <-> native block size.
r337878:
libi386: remove bd_read() and bd_write() wrappers
Those wroappers are nice, but do not really add much value.
r337881:
libi386: use BD_RD and BR_WR constants
Use BD_RD and BD_WR instead of 0 and 1.
r337890:
libi386: small style updates in biosdisk
Use break instead of return in for loop, as done earlier. Insert and remove
some blank lines. No functional changes intended.
r337891:
libi386: bd_io_workaround() is to be called for reads only
bd_io() can perform either reads or writes, we only need bd_io_workaround()
for reads.
r338188:
loader: bios loader should allow to chain load a file
The current chain command does accept only device, allow also a file to be used,
such as /boot/pmbr or /boot/mbr (or stored third party MBR/VBR block).
Also fix file descriptor leak.
Modified:
stable/11/stand/i386/libi386/bioscd.c
stable/11/stand/i386/libi386/biosdisk.c
stable/11/stand/i386/loader/chain.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/stand/i386/libi386/bioscd.c
==============================================================================
--- stable/11/stand/i386/libi386/bioscd.c Sun Apr 21 03:22:57 2019 (r346473)
+++ stable/11/stand/i386/libi386/bioscd.c Sun Apr 21 03:27:12 2019 (r346474)
@@ -258,15 +258,9 @@ bc_realstrategy(void *devdata, int rw, daddr_t dblk, s
struct i386_devdesc *dev;
int unit;
int blks;
-#ifdef BD_SUPPORT_FRAGS
- char fragbuf[BIOSCD_SECSIZE];
- size_t fragsize;
- fragsize = size % BIOSCD_SECSIZE;
-#else
if (size % BIOSCD_SECSIZE)
return (EINVAL);
-#endif
if ((rw & F_MASK) != F_READ)
return(EROFS);
@@ -290,20 +284,6 @@ bc_realstrategy(void *devdata, int rw, daddr_t dblk, s
return (0);
}
}
-#ifdef BD_SUPPORT_FRAGS
- DEBUG("frag read %d from %lld+%d to %p",
- fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
- if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf) != 1) {
- if (blks) {
- if (rsize)
- *rsize = blks * BIOSCD_SECSIZE;
- return (0);
- }
- DEBUG("frag read error");
- return(EIO);
- }
- bcopy(fragbuf, buf + (blks * BIOSCD_SECSIZE), fragsize);
-#endif
if (rsize)
*rsize = size;
return (0);
Modified: stable/11/stand/i386/libi386/biosdisk.c
==============================================================================
--- stable/11/stand/i386/libi386/biosdisk.c Sun Apr 21 03:22:57 2019 (r346473)
+++ stable/11/stand/i386/libi386/biosdisk.c Sun Apr 21 03:27:12 2019 (r346474)
@@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$");
/*
* BIOS disk device handling.
- *
+ *
* Ideas and algorithms from:
*
* - NetBSD libi386/biosdisk.c
@@ -50,20 +50,20 @@ __FBSDID("$FreeBSD$");
#include "disk.h"
#include "libi386.h"
-#define BIOS_NUMDRIVES 0x475
-#define BIOSDISK_SECSIZE 512
-#define BUFSIZE (1 * BIOSDISK_SECSIZE)
+#define BIOS_NUMDRIVES 0x475
+#define BIOSDISK_SECSIZE 512
+#define BUFSIZE (1 * BIOSDISK_SECSIZE)
-#define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
-#define WDMAJOR 0 /* major numbers for devices we frontend for */
-#define WFDMAJOR 1
-#define FDMAJOR 2
-#define DAMAJOR 4
+#define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
+#define WDMAJOR 0 /* major numbers for devices we frontend for */
+#define WFDMAJOR 1
+#define FDMAJOR 2
+#define DAMAJOR 4
#ifdef DISK_DEBUG
-# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
+#define DEBUG(fmt, args...) printf("%s: " fmt "\n", __func__, ## args)
#else
-# define DEBUG(fmt, args...)
+#define DEBUG(fmt, args...)
#endif
/*
@@ -91,13 +91,12 @@ static struct bdinfo
static int nbdinfo = 0;
#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);
-static int bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks,
- caddr_t dest);
-static int bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks,
- caddr_t dest);
+static int bd_io(struct disk_devdesc *, daddr_t, int, caddr_t, int);
static int bd_int13probe(struct bdinfo *bd);
static int bd_init(void);
@@ -164,7 +163,7 @@ bd_init(void)
* Check the BIOS equipment list for number
* of fixed disks.
*/
- if(base == 0x80 &&
+ if (base == 0x80 &&
(nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES)))
break;
#endif
@@ -184,7 +183,7 @@ bd_init(void)
}
}
bcache_add_dev(nbdinfo);
- return(0);
+ return (0);
}
/*
@@ -207,7 +206,7 @@ bd_int13probe(struct bdinfo *bd)
(v86.edx & 0xff) <= (unsigned)(bd->bd_unit & 0x7f)) /* unit # bad */
return (0); /* skip device */
- if ((v86.ecx & 0x3f) == 0) /* absurd sector number */
+ if ((v86.ecx & 0x3f) == 0) /* absurd sector number */
ret = 0; /* set error */
/* Convert max cyl # -> # of cylinders */
@@ -307,6 +306,7 @@ bd_print(int verbose)
bdinfo[i].bd_sectorsize);
if ((ret = pager_output(line)) != 0)
break;
+
dev.dd.d_dev = &biosdisk;
dev.dd.d_unit = i;
dev.d_slice = -1;
@@ -318,7 +318,7 @@ bd_print(int verbose)
ret = disk_print(&dev, line, verbose);
disk_close(&dev);
if (ret != 0)
- return (ret);
+ break;
}
}
return (ret);
@@ -337,11 +337,11 @@ bd_print(int verbose)
static int
bd_open(struct open_file *f, ...)
{
- struct disk_devdesc *dev, rdev;
+ struct disk_devdesc *dev;
struct disk_devdesc disk;
- int err, g_err;
va_list ap;
uint64_t size;
+ int rc;
va_start(ap, f);
dev = va_arg(ap, struct disk_devdesc *);
@@ -365,6 +365,7 @@ bd_open(struct open_file *f, ...)
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) {
@@ -376,10 +377,16 @@ bd_open(struct open_file *f, ...)
disk_close(&disk);
}
- err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
+ rc = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
BD(dev).bd_sectorsize);
-
- return (err);
+ if (rc != 0) {
+ BD(dev).bd_open--;
+ if (BD(dev).bd_open == 0) {
+ bcache_free(BD(dev).bd_bcache);
+ BD(dev).bd_bcache = NULL;
+ }
+ }
+ return (rc);
}
static int
@@ -410,7 +417,7 @@ bd_ioctl(struct open_file *f, u_long cmd, void *data)
switch (cmd) {
case DIOCGSECTORSIZE:
- *(u_int *)data = BD(dev).bd_sectorsize;
+ *(uint32_t *)data = BD(dev).bd_sectorsize;
break;
case DIOCGMEDIASIZE:
*(uint64_t *)data = BD(dev).bd_sectors * BD(dev).bd_sectorsize;
@@ -432,176 +439,161 @@ bd_strategy(void *devdata, int rw, daddr_t dblk, size_
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));
+ 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 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;
+ struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
+ uint64_t disk_blocks;
+ int blks, rc;
- fragsize = size % BIOSDISK_SECSIZE;
-#else
- if (size % BD(dev).bd_sectorsize)
- panic("bd_strategy: %d bytes I/O not multiple of block size", size);
-#endif
+ if (size % BD(dev).bd_sectorsize) {
+ panic("bd_strategy: %d bytes I/O not multiple of block size",
+ size);
+ }
- DEBUG("open_disk %p", dev);
+ 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);
- }
+ /*
+ * 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);
+ blks = size / BD(dev).bd_sectorsize;
+ if (dblk > dblk + blks)
+ return (EIO);
- if (rsize)
- *rsize = 0;
+ if (rsize)
+ *rsize = 0;
- /* Get disk blocks, this value is either for whole disk or for partition */
- if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
- /* DIOCGMEDIASIZE returns 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;
- }
+ /*
+ * Get disk blocks, this value is either for whole disk or for
+ * partition.
+ */
+ if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
+ /* DIOCGMEDIASIZE returns 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);
+ /* 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);
- }
+ /*
+ * 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 %lld to %p", blks, dblk, buf);
+ switch (rw & F_MASK) {
+ case F_READ:
+ DEBUG("read %d from %lld to %p", blks, dblk, buf);
- if (blks && (rc = bd_read(dev, dblk, blks, buf))) {
- /* Filter out floppy controller errors */
- if (BD(dev).bd_flags != BD_FLOPPY || rc != 0x20) {
- printf("read %d from %lld to %p, error: 0x%x\n", blks, dblk,
- buf, rc);
- }
- return (EIO);
- }
-#ifdef BD_SUPPORT_FRAGS /* XXX: sector size */
- DEBUG("bd_strategy: frag read %d from %d+%d to %p",
- fragsize, dblk, blks, buf + (blks * BIOSDISK_SECSIZE));
- if (fragsize && bd_read(od, dblk + blks, 1, fragsize)) {
- DEBUG("frag read error");
- return(EIO);
- }
- bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize);
-#endif
- break;
- case F_WRITE :
- DEBUG("write %d from %lld to %p", blks, dblk, buf);
+ if (blks && (rc = bd_io(dev, dblk, blks, buf, BD_RD))) {
+ /* Filter out floppy controller errors */
+ if (BD(dev).bd_flags != BD_FLOPPY || rc != 0x20) {
+ printf("read %d from %lld to %p, error: 0x%x\n",
+ blks, dblk, buf, rc);
+ }
+ return (EIO);
+ }
+ break;
+ case F_WRITE :
+ DEBUG("write %d from %lld to %p", blks, dblk, buf);
- if (blks && bd_write(dev, dblk, blks, buf)) {
- DEBUG("write error");
- return (EIO);
+ if (blks && bd_io(dev, dblk, blks, buf, BD_WR)) {
+ DEBUG("write error");
+ return (EIO);
+ }
+ break;
+ default:
+ /* DO NOTHING */
+ return (EROFS);
}
-#ifdef BD_SUPPORT_FRAGS
- if(fragsize) {
- DEBUG("Attempted to write a frag");
- return (EIO);
- }
-#endif
- break;
- default:
- /* DO NOTHING */
- return (EROFS);
- }
- if (rsize)
- *rsize = size;
- return (0);
+ if (rsize)
+ *rsize = size;
+ return (0);
}
static int
bd_edd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
- int write)
+ int dowrite)
{
- static struct edd_packet packet;
+ static struct edd_packet packet;
- packet.len = sizeof(struct edd_packet);
- packet.count = blks;
- packet.off = VTOPOFF(dest);
- packet.seg = VTOPSEG(dest);
- packet.lba = dblk;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- if (write)
+ packet.len = sizeof(struct edd_packet);
+ packet.count = blks;
+ packet.off = VTOPOFF(dest);
+ packet.seg = VTOPSEG(dest);
+ packet.lba = dblk;
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
/* Should we Write with verify ?? 0x4302 ? */
- v86.eax = 0x4300;
- else
- v86.eax = 0x4200;
- v86.edx = BD(dev).bd_unit;
- v86.ds = VTOPSEG(&packet);
- v86.esi = VTOPOFF(&packet);
- v86int();
- if (V86_CY(v86.efl))
- return (v86.eax >> 8);
- return (0);
+ if (dowrite == BD_WR)
+ v86.eax = 0x4300;
+ else
+ v86.eax = 0x4200;
+ v86.edx = BD(dev).bd_unit;
+ v86.ds = VTOPSEG(&packet);
+ v86.esi = VTOPOFF(&packet);
+ v86int();
+ if (V86_CY(v86.efl))
+ return (v86.eax >> 8);
+ return (0);
}
static int
bd_chs_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
- int write)
+ int dowrite)
{
- u_int x, bpc, cyl, hd, sec;
+ uint32_t x, bpc, cyl, hd, sec;
- bpc = BD(dev).bd_sec * BD(dev).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 */
+ bpc = BD(dev).bd_sec * BD(dev).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 */
- /* correct sector number for 1-based BIOS numbering */
- sec++;
+ /* correct sector number for 1-based BIOS numbering */
+ sec++;
- if (cyl > 1023)
- /* CHS doesn't support cylinders > 1023. */
- return (1);
+ if (cyl > 1023) {
+ /* CHS doesn't support cylinders > 1023. */
+ return (1);
+ }
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- if (write)
- v86.eax = 0x300 | blks;
- else
- v86.eax = 0x200 | blks;
- v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec;
- v86.edx = (hd << 8) | BD(dev).bd_unit;
- v86.es = VTOPSEG(dest);
- v86.ebx = VTOPOFF(dest);
- v86int();
- if (V86_CY(v86.efl))
- return (v86.eax >> 8);
- return (0);
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ if (dowrite == BD_WR)
+ v86.eax = 0x300 | blks;
+ else
+ v86.eax = 0x200 | blks;
+ v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec;
+ v86.edx = (hd << 8) | BD(dev).bd_unit;
+ v86.es = VTOPSEG(dest);
+ v86.ebx = VTOPOFF(dest);
+ v86int();
+ if (V86_CY(v86.efl))
+ return (v86.eax >> 8);
+ return (0);
}
static void
@@ -609,130 +601,117 @@ bd_io_workaround(struct disk_devdesc *dev)
{
uint8_t buf[8 * 1024];
- bd_edd_io(dev, 0xffffffff, 1, (caddr_t)buf, 0);
+ bd_edd_io(dev, 0xffffffff, 1, (caddr_t)buf, BD_RD);
}
static int
-bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest, int write)
+bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
+ int dowrite)
{
- u_int x, sec, result, resid, retry, maxfer;
- caddr_t p, xp, bbuf;
+ u_int x, sec, result, resid, retry, maxfer;
+ caddr_t p, xp, bbuf;
- /* Just in case some idiot actually tries to read/write -1 blocks... */
- if (blks < 0)
- return (-1);
+ /* Just in case some idiot actually tries to read/write -1 blocks... */
+ if (blks < 0)
+ return (-1);
- resid = blks;
- p = dest;
+ resid = blks;
+ p = dest;
- /*
- * Workaround for a problem with some HP ProLiant BIOS failing to work out
- * the boot disk after installation. hrs and kuriyama discovered this
- * problem with an HP ProLiant DL320e Gen 8 with a 3TB HDD, and discovered
- * that an int13h call seems to cause a buffer overrun in the bios. The
- * problem is alleviated by doing an extra read before the buggy read. It
- * is not immediately known whether other models are similarly affected.
- */
- if (dblk >= 0x100000000)
- bd_io_workaround(dev);
-
- /* Decide whether we have to bounce */
- if (VTOP(dest) >> 20 != 0 || (BD(dev).bd_unit < 0x80 &&
- (VTOP(dest) >> 16) != (VTOP(dest +
- blks * BD(dev).bd_sectorsize) >> 16))) {
-
- /*
- * There is a 64k physical boundary somewhere in the
- * destination buffer, or the destination buffer is above
- * first 1MB of physical memory so we have to arrange a
- * suitable bounce buffer. Allocate a buffer twice as large
- * as we need to. Use the bottom half unless there is a break
- * there, in which case we use the top half.
- */
- x = V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize;
- x = min(x, (unsigned)blks);
- bbuf = PTOV(V86_IO_BUFFER);
- maxfer = x; /* limit transfers to bounce region size */
- } else {
- bbuf = NULL;
- maxfer = 0;
- }
-
- while (resid > 0) {
/*
- * Play it safe and don't cross track boundaries.
- * (XXX this is probably unnecessary)
+ * Workaround for a problem with some HP ProLiant BIOS failing to work
+ * out the boot disk after installation. hrs and kuriyama discovered
+ * this problem with an HP ProLiant DL320e Gen 8 with a 3TB HDD, and
+ * discovered that an int13h call seems to cause a buffer overrun in
+ * the bios. The problem is alleviated by doing an extra read before
+ * the buggy read. It is not immediately known whether other models
+ * are similarly affected.
*/
- sec = dblk % BD(dev).bd_sec; /* offset into track */
- x = min(BD(dev).bd_sec - sec, resid);
- if (maxfer > 0)
- x = min(x, maxfer); /* fit bounce buffer */
+ if (dowrite == BD_RD && dblk >= 0x100000000)
+ bd_io_workaround(dev);
- /* where do we transfer to? */
- xp = bbuf == NULL ? p : bbuf;
+ /* Decide whether we have to bounce */
+ if (VTOP(dest) >> 20 != 0 || (BD(dev).bd_unit < 0x80 &&
+ (VTOP(dest) >> 16) !=
+ (VTOP(dest + blks * BD(dev).bd_sectorsize) >> 16))) {
- /*
- * Put your Data In, Put your Data out,
- * Put your Data In, and shake it all about
- */
- if (write && bbuf != NULL)
- bcopy(p, bbuf, x * BD(dev).bd_sectorsize);
-
- /*
- * 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 = BD(dev).bd_unit;
- v86int();
- }
-
- if (BD(dev).bd_flags & BD_MODEEDD1)
- result = bd_edd_io(dev, dblk, x, xp, write);
- else
- result = bd_chs_io(dev, dblk, x, xp, write);
- if (result == 0)
- break;
+ /*
+ * There is a 64k physical boundary somewhere in the
+ * destination buffer, or the destination buffer is above
+ * first 1MB of physical memory so we have to arrange a
+ * suitable bounce buffer. Allocate a buffer twice as large
+ * as we need to. Use the bottom half unless there is a break
+ * there, in which case we use the top half.
+ */
+ x = V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize;
+ x = min(x, (unsigned)blks);
+ bbuf = PTOV(V86_IO_BUFFER);
+ maxfer = x; /* limit transfers to bounce region size */
+ } else {
+ bbuf = NULL;
+ maxfer = 0;
}
+
+ while (resid > 0) {
+ /*
+ * Play it safe and don't cross track boundaries.
+ * (XXX this is probably unnecessary)
+ */
+ sec = dblk % BD(dev).bd_sec; /* offset into track */
+ x = min(BD(dev).bd_sec - sec, resid);
+ if (maxfer > 0)
+ x = min(x, maxfer); /* fit bounce buffer */
- if (write)
- DEBUG("Write %d sector(s) from %p (0x%x) to %lld %s", x,
- p, VTOP(p), dblk, result ? "failed" : "ok");
- else
- DEBUG("Read %d sector(s) from %lld to %p (0x%x) %s", x,
- dblk, p, VTOP(p), result ? "failed" : "ok");
- if (result) {
- return (result);
- }
- if (!write && bbuf != NULL)
- bcopy(bbuf, p, x * BD(dev).bd_sectorsize);
- p += (x * BD(dev).bd_sectorsize);
- dblk += x;
- resid -= x;
- }
+ /* where do we transfer to? */
+ xp = bbuf == NULL ? p : bbuf;
-/* hexdump(dest, (blks * BD(dev).bd_sectorsize)); */
- return(0);
-}
+ /*
+ * Put your Data In, Put your Data out,
+ * Put your Data In, and shake it all about
+ */
+ if (dowrite == BD_WR && bbuf != NULL)
+ bcopy(p, bbuf, x * BD(dev).bd_sectorsize);
-static int
-bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest)
-{
+ /*
+ * 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 = BD(dev).bd_unit;
+ v86int();
+ }
- return (bd_io(dev, dblk, blks, dest, 0));
-}
+ if (BD(dev).bd_flags & BD_MODEEDD1)
+ result = bd_edd_io(dev, dblk, x, xp, dowrite);
+ else
+ result = bd_chs_io(dev, dblk, x, xp, dowrite);
+ if (result == 0)
+ break;
+ }
-static int
-bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest)
-{
+ if (dowrite == BD_WR)
+ DEBUG("Write %d sector(s) from %p (0x%x) to %lld %s", x,
+ p, VTOP(p), dblk, result ? "failed" : "ok");
+ else
+ DEBUG("Read %d sector(s) from %lld to %p (0x%x) %s", x,
+ dblk, p, VTOP(p), result ? "failed" : "ok");
+ if (result) {
+ return (result);
+ }
+ if (dowrite == BD_RD && bbuf != NULL)
+ bcopy(bbuf, p, x * BD(dev).bd_sectorsize);
+ p += (x * BD(dev).bd_sectorsize);
+ dblk += x;
+ resid -= x;
+ }
- return (bd_io(dev, dblk, blks, dest, 1));
+ return (0);
}
/*
@@ -753,15 +732,15 @@ uint32_t
bd_getbigeom(int bunit)
{
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x800;
- v86.edx = 0x80 + bunit;
- v86int();
- if (V86_CY(v86.efl))
- return 0x4f010f;
- return ((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) |
- (v86.edx & 0xff00) | (v86.ecx & 0x3f);
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0x800;
+ v86.edx = 0x80 + bunit;
+ v86int();
+ if (V86_CY(v86.efl))
+ return (0x4f010f);
+ return (((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) |
+ (v86.edx & 0xff00) | (v86.ecx & 0x3f));
}
/*
@@ -773,49 +752,49 @@ bd_getbigeom(int bunit)
int
bd_getdev(struct i386_devdesc *d)
{
- struct disk_devdesc *dev;
- int biosdev;
- int major;
- int rootdev;
- char *nip, *cp;
- int i, unit;
+ struct disk_devdesc *dev;
+ int biosdev;
+ int major;
+ int rootdev;
+ char *nip, *cp;
+ int i, unit;
- dev = (struct disk_devdesc *)d;
- biosdev = bd_unit2bios(dev->dd.d_unit);
- 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);
+ dev = (struct disk_devdesc *)d;
+ biosdev = bd_unit2bios(dev->dd.d_unit);
+ 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 (biosdev < 0x80) {
- /* floppy (or emulated floppy) or ATAPI device */
- if (bdinfo[dev->dd.d_unit].bd_type == DT_ATAPI) {
- /* is an ATAPI disk */
- major = WFDMAJOR;
+ if (biosdev < 0x80) {
+ /* floppy (or emulated floppy) or ATAPI device */
+ if (bdinfo[dev->dd.d_unit].bd_type == DT_ATAPI) {
+ /* is an ATAPI disk */
+ major = WFDMAJOR;
+ } else {
+ /* is a floppy disk */
+ major = FDMAJOR;
+ }
} else {
- /* is a floppy disk */
- major = FDMAJOR;
+ /* assume an IDE disk */
+ major = WDMAJOR;
}
- } else {
- /* assume an IDE disk */
- major = WDMAJOR;
- }
- /* default root disk unit number */
- unit = biosdev & 0x7f;
+ /* default root disk unit number */
+ unit = biosdev & 0x7f;
- /* XXX a better kludge to set the root disk unit number */
- if ((nip = getenv("root_disk_unit")) != NULL) {
- i = strtol(nip, &cp, 0);
- /* check for parse error */
- if ((cp != nip) && (*cp == 0))
- unit = i;
- }
+ /* XXX a better kludge to set the root disk unit number */
+ if ((nip = getenv("root_disk_unit")) != NULL) {
+ i = strtol(nip, &cp, 0);
+ /* check for parse error */
+ if ((cp != nip) && (*cp == 0))
+ unit = i;
+ }
- rootdev = MAKEBOOTDEV(major, dev->d_slice + 1, unit, dev->d_partition);
- DEBUG("dev is 0x%x\n", rootdev);
- return(rootdev);
+ rootdev = MAKEBOOTDEV(major, dev->d_slice + 1, unit, dev->d_partition);
+ DEBUG("dev is 0x%x\n", rootdev);
+ return (rootdev);
}
Modified: stable/11/stand/i386/loader/chain.c
==============================================================================
--- stable/11/stand/i386/loader/chain.c Sun Apr 21 03:22:57 2019 (r346473)
+++ stable/11/stand/i386/loader/chain.c Sun Apr 21 03:27:12 2019 (r346474)
@@ -92,24 +92,26 @@ command_chain(int argc, char *argv[])
i386_getdev((void **)(&rootdev), argv[1], NULL);
if (rootdev == NULL) {
command_errmsg = "can't determine root device";
+ close(fd);
return (CMD_ERROR);
}
- if (archsw.arch_readin(fd, mem, SECTOR_SIZE) != SECTOR_SIZE) {
+ if (archsw.arch_readin(fd, mem, size) != size) {
command_errmsg = "failed to read disk";
close(fd);
return (CMD_ERROR);
}
close(fd);
- if (*((uint16_t *)PTOV(mem + DOSMAGICOFFSET)) != DOSMAGIC) {
+ if (argv[1][len-1] == ':' &&
+ *((uint16_t *)PTOV(mem + DOSMAGICOFFSET)) != DOSMAGIC) {
command_errmsg = "wrong magic";
return (CMD_ERROR);
}
relocater_data[0].src = mem;
relocater_data[0].dest = 0x7C00;
- relocater_data[0].size = SECTOR_SIZE;
+ relocater_data[0].size = size;
relocator_edx = bd_unit2bios(rootdev->dd.d_unit);
relocator_esi = relocater_size;
More information about the svn-src-all
mailing list