Date: Tue, 03 Sep 2019 14:08:09 -0000 From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r346474 - in stable/11/stand/i386: libi386 loader Message-ID: <201904210327.x3L3RCXa015476@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904210327.x3L3RCXa015476>