Page MenuHomeFreeBSD

D8595.id22420.diff
No OneTemporary

D8595.id22420.diff

Index: sys/boot/i386/libi386/biosdisk.c
===================================================================
--- sys/boot/i386/libi386/biosdisk.c
+++ sys/boot/i386/libi386/biosdisk.c
@@ -377,6 +377,7 @@
bd_open(struct open_file *f, ...)
{
struct disk_devdesc *dev, rdev;
+ struct disk_devdesc disk;
int err, g_err;
va_list ap;
@@ -389,6 +390,32 @@
BD(dev).bd_open++;
if (BD(dev).bd_bcache == NULL)
BD(dev).bd_bcache = bcache_allocate();
+
+ /*
+ * Read disk size from partition.
+ * This is needed to work around buggy BIOS systems returning
+ * wrong (truncated) disk media size.
+ */
+ disk.d_dev = dev->d_dev;
+ disk.d_type = dev->d_type;
+ disk.d_unit = dev->d_unit;
+ disk.d_opendata = NULL;
+ 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, (BD(dev).bd_flags & BD_FLOPPY) ?
+ DISK_F_NOCACHE: 0) == 0) {
+ off_t size;
+
+ if (disk_ioctl(&disk, DIOCGMEDIASIZE, &size) == 0) {
+ size /= BD(dev).bd_sectorsize;
+ if (size > BD(dev).bd_sectors)
+ BD(dev).bd_sectors = size;
+ }
+ disk_close(&disk);
+ }
+
err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
BD(dev).bd_sectorsize, (BD(dev).bd_flags & BD_FLOPPY) ?
DISK_F_NOCACHE: 0);
@@ -486,8 +513,14 @@
bd_ioctl(struct open_file *f, u_long cmd, void *data)
{
struct disk_devdesc *dev;
+ int rc;
dev = (struct disk_devdesc *)f->f_devdata;
+
+ rc = disk_ioctl(dev, cmd, data);
+ if (rc != ENOTTY)
+ return (rc);
+
switch (cmd) {
case DIOCGSECTORSIZE:
*(u_int *)data = BD(dev).bd_sectorsize;
@@ -521,7 +554,8 @@
char *buf, size_t *rsize)
{
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
- int blks, remaining;
+ off_t disk_blocks;
+ int blks;
#ifdef BD_SUPPORT_FRAGS /* XXX: sector size */
char fragbuf[BIOSDISK_SECSIZE];
size_t fragsize;
@@ -537,15 +571,20 @@
if (rsize)
*rsize = 0;
+ /* Get disk blocks, this value is either for whole disk or for partition */
+ if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks))
+ disk_blocks = BD(dev).bd_sectors;
+ disk_blocks /= BD(dev).bd_sectorsize;
+
+ /* IO past disk or partition size */
+ if (dblk >= dev->d_offset + disk_blocks)
+ return (EIO);
+
/*
- * Perform partial read to prevent read-ahead crossing
- * the end of disk - or any 32 bit aliases of the end.
- * Signed arithmetic is used to handle wrap-around cases
- * like we do for TCP sequence numbers.
+ * Truncate if we are crossing disk or partition end.
*/
- remaining = (int)(BD(dev).bd_sectors - dblk); /* truncate */
- if (remaining > 0 && remaining < blks) {
- blks = remaining;
+ 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);
}

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 6, 8:45 AM (11 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30952576
Default Alt Text
D8595.id22420.diff (2 KB)

Event Timeline