Page MenuHomeFreeBSD

D11174.id29556.diff
No OneTemporary

D11174.id29556.diff

Index: sys/boot/i386/libi386/biosdisk.c
===================================================================
--- sys/boot/i386/libi386/biosdisk.c
+++ sys/boot/i386/libi386/biosdisk.c
@@ -563,265 +563,260 @@
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, offset;
+ size_t blks, blkoff, bsize, rest;
+ caddr_t bbuf;
+ int 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
+ /*
+ * First make sure the IO size is multiple of 512 bytes. While we do
+ * process partial reads below, the strategy mechanism is built
+ * assuming IO is a multiple of 512B blocks. If the request is not
+ * a multiple of 512B blocks, it has to be some sort of bug.
+ */
+ if (size == 0 || (size % BIOSDISK_SECSIZE) != 0) {
+ printf("bd_strategy: %d bytes I/O not multiple of %d\n",
+ size, BIOSDISK_SECSIZE);
+ return (EIO);
+ }
- 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);
- }
+ offset = dblk * BIOSDISK_SECSIZE;
+ dblk = offset / BD(dev).bd_sectorsize;
+ blkoff = offset % BD(dev).bd_sectorsize;
- blks = size / BD(dev).bd_sectorsize;
- if (dblk > dblk + blks)
- 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("requested read: %zu too large", size);
+ return (EIO);
+ }
- if (rsize)
- *rsize = 0;
+ blks = size / BD(dev).bd_sectorsize;
+ if (blks == 0 || (size % BD(dev).bd_sectorsize) != 0)
+ blks++;
- /* 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;
- }
+ if (dblk > dblk + blks)
+ return (EIO);
- /* Validate source block address. */
- if (dblk < dev->d_offset || dblk >= dev->d_offset + disk_blocks)
- return (EIO);
+ if (rsize)
+ *rsize = 0;
- /*
- * 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);
- }
+ /*
+ * 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;
+ }
- switch (rw & F_MASK) {
- case F_READ:
- DEBUG("read %d from %lld to %p", blks, dblk, buf);
+ /* Validate source block address. */
+ if (dblk < dev->d_offset || dblk >= dev->d_offset + disk_blocks)
+ return (EIO);
- 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", blks, dblk,
- buf, rc);
- }
- 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);
}
-#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 %d to %p", blks, dblk, buf);
- if (blks && bd_write(dev, dblk, blks, buf)) {
- DEBUG("write error");
- return (EIO);
+ if (V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize == 0)
+ panic("BUG: Real mode buffer is too small\n");
+
+ bbuf = PTOV(V86_IO_BUFFER);
+ rest = size;
+
+ while (blks > 0) {
+ int x = min(blks, V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize);
+
+ switch (rw & F_MASK) {
+ case F_READ:
+ DEBUG("read %d from %lld to %p", blks, dblk, buf);
+ bsize = BD(dev).bd_sectorsize * x - blkoff;
+ if (rest < bsize)
+ bsize = rest;
+
+ if ((rc = bd_read(dev, dblk, x, bbuf)) != 0)
+ return (EIO);
+
+ bcopy(bbuf + blkoff, buf, bsize);
+ break;
+ case F_WRITE :
+ DEBUG("write %d from %d to %p", blks, dblk, buf);
+ if (blkoff != 0) {
+ /*
+ * We got offset to sector, read 1 sector to
+ * bbuf.
+ */
+ x = 1;
+ bsize = rest;
+ rc = bd_read(dev, dblk, x, bbuf);
+ } else if (rest < BD(dev).bd_sectorsize) {
+ /*
+ * The remaining block is not full
+ * sector. Read 1 sector to bbuf.
+ */
+ x = 1;
+ bsize = rest;
+ rc = bd_read(dev, dblk, x, bbuf);
+ } else {
+ /* We can write full sector(s). */
+ bsize = BD(dev).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_write(dev, dblk, x, bbuf)) != 0)
+ return (EIO);
+
+ break;
+ default:
+ /* DO NOTHING */
+ return (EROFS);
+ }
+
+ blkoff = 0;
+ buf += bsize;
+ rest -= bsize;
+ blks -= x;
+ dblk += x;
}
-#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 != NULL)
+ *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)
- /* 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);
+ 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 (dowrite)
+ /* 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);
}
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;
+ u_int 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)
+ 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 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 result, retry;
- /* 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;
-
- /* 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)
- */
- 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 */
-
- /* where do we transfer to? */
- xp = bbuf == NULL ? p : bbuf;
-
- /*
- * 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 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;
+ if (BD(dev).bd_flags & BD_MODEEDD1)
+ result = bd_edd_io(dev, dblk, blks, dest, dowrite);
+ else
+ result = bd_chs_io(dev, dblk, blks, dest, dowrite);
+
+ if (result == 0)
+ break;
}
- 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);
+ /*
+ * 0x20 - Controller failure. This is common error when the
+ * media is not present.
+ */
+ if (result != 0 && result != 0x20) {
+ if (dowrite) {
+ printf("%s%d: Write %d sector(s) from %p (0x%x) "
+ "to %lld: 0x%x", dev->d_dev->dv_name, dev->d_unit,
+ blks, dest, VTOP(dest), dblk, result);
+ } else {
+ printf("%s%d: Read %d sector(s) from %lld to %p "
+ "(0x%x): 0x%x", dev->d_dev->dv_name, dev->d_unit,
+ blks, dblk, dest, VTOP(dest), result);
+ }
}
- if (!write && bbuf != NULL)
- bcopy(bbuf, p, x * BD(dev).bd_sectorsize);
- p += (x * BD(dev).bd_sectorsize);
- dblk += x;
- resid -= x;
- }
-/* hexdump(dest, (blks * BD(dev).bd_sectorsize)); */
- return(0);
+ return (result);
}
static int
@@ -923,15 +918,15 @@
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);
}
/*
@@ -943,51 +938,51 @@
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->d_unit);
- DEBUG("unit %d BIOS device %d", dev->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->d_unit);
+ DEBUG("unit %d BIOS device %d", dev->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->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->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);
}
#ifdef LOADER_GELI_SUPPORT

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 17, 8:13 PM (21 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27698656
Default Alt Text
D11174.id29556.diff (16 KB)

Event Timeline