Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142175961
D11174.id29556.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D11174.id29556.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D11174: loader: biosdisk interface should be able to cope with 4k sectors
Attached
Detach File
Event Timeline
Log In to Comment