From owner-svn-src-head@freebsd.org Tue Oct 23 15:41:22 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 034D9FEA402; Tue, 23 Oct 2018 15:41:22 +0000 (UTC) (envelope-from cy.schubert@cschubert.com) Received: from smtp-out-no.shaw.ca (smtp-out-no.shaw.ca [64.59.134.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "Client", Issuer "CA" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4A74882B4F; Tue, 23 Oct 2018 15:41:20 +0000 (UTC) (envelope-from cy.schubert@cschubert.com) Received: from spqr.komquats.com ([70.67.125.17]) by shaw.ca with ESMTPA id EynwgpYFY1jEDEynxgcn48; Tue, 23 Oct 2018 09:41:14 -0600 X-Authority-Analysis: v=2.3 cv=W/aMqiek c=1 sm=1 tr=0 a=VFtTW3WuZNDh6VkGe7fA3g==:117 a=VFtTW3WuZNDh6VkGe7fA3g==:17 a=smKx5t2vBNcA:10 a=YxBL1-UpAAAA:8 a=6I5d2MoRAAAA:8 a=DSHT9BU3AAAA:8 a=WUIPhXQWiyYIYI8gKDUA:9 a=jklPvFAKvOX8gjHU:21 a=y1gyoRiRoFa-LYvn:21 a=QEXdDO2ut3YA:10 a=K18A3tn0-rEuzAXC8TkA:9 a=yny1GjbhH21OAmSn:21 a=sfqfZOwAzBG0_j6c:21 a=osFmxWBz9zXBFo9r:21 a=_W_S_7VecoQA:10 a=Ia-lj3WSrqcvXOmTRaiG:22 a=IjZwj45LgO3ly-622nXo:22 a=8ljxv5-TN0tg3ptMfEC3:22 Received: from [10.168.101.253] (S0106788a207e2972.gv.shawcable.net [70.66.154.233]) by spqr.komquats.com (Postfix) with ESMTPSA id 067AD431; Tue, 23 Oct 2018 08:41:11 -0700 (PDT) MIME-Version: 1.0 From: Cy Schubert Subject: RE: svn commit: r339658 - head/stand/i386/libi386 Date: Tue, 23 Oct 2018 08:41:14 -0700 To: Toomas Soome , "src-committers@freebsd.org" , "svn-src-all@freebsd.org" , "svn-src-head@freebsd.org" Message-Id: <20181023154112.067AD431@spqr.komquats.com> X-CMAE-Envelope: MS4wfPa3JlKXyxzOwPuA7zbj9Vi1Qjk4mnymd6uC7ECUOewQvpk4pgAnmowzx1qAqTedXtX0nQuE1FLgW/ZuP3RLen7Lnmbsu9jDgixJ7dbND+lWNchkrbVt aq9CLVcKLaJmkZmFAf5H1EORclR7YYqy4rBV/XB7vpaNYcFag7nkFv8wafjSsB6O9AIhaMlZ/1xJWHyliqL0q5p2SGDJvk/L9R+LSaPXWUDuCHFkWslR/W// OOYsbZ81d1ie0rIjlDd8g4lSfxgufsL2ezoelDvf1uA= Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Oct 2018 15:41:22 -0000 Thank you Toomas. --- Sent using a tiny phone keyboard. Apologies for any typos and autocorrect. Also, this old phone only supports top post. Apologies. Cy Schubert or The need of the many outweighs the greed of the few. --- -----Original Message----- From: Toomas Soome Sent: 23/10/2018 07:44 To: src-committers@freebsd.org; svn-src-all@freebsd.org; svn-src-head@freeb= sd.org Subject: svn commit: r339658 - head/stand/i386/libi386 Author: tsoome Date: Tue Oct 23 14:44:32 2018 New Revision: 339658 URL: https://svnweb.freebsd.org/changeset/base/339658 Log: loader: biosdisk interface should be able to cope with 4k sectors =20 The 4kn support in current bios specific biosdisk.c is broken, as the cod= e is only implementing the support for the 512B sector size. =20 This work is building the support for custom size sectors, we still do as= sume the requested data to be multiple of 512B blocks and we only do address t= he biosdisk.c interface here. =20 For reference, see also: https://www.illumos.org/issues/8303 https://www.illumos.org/rb/r/547 =20 As the GELI is moved above biosdisk "layer", the GELI should just work =20 Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D11174 Modified: head/stand/i386/libi386/biosdisk.c Modified: head/stand/i386/libi386/biosdisk.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- head/stand/i386/libi386/biosdisk.c Tue Oct 23 14:38:08 2018 (r339657) +++ head/stand/i386/libi386/biosdisk.c Tue Oct 23 14:44:32 2018 (r339658) @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include =20 #include #include @@ -255,10 +256,11 @@ bd_int13probe(struct bdinfo *bd) * Sector size must be a multiple of 512 bytes. * An alternate test would be to check power of 2, * powerof2(params.sector_size). + * 4K is largest read buffer we can use at this time. */ - if (params.sector_size % BIOSDISK_SECSIZE) - bd->bd_sectorsize =3D BIOSDISK_SECSIZE; - else + if (params.sector_size >=3D 512 && + params.sector_size <=3D 4096 && + (params.sector_size % BIOSDISK_SECSIZE) =3D=3D 0) bd->bd_sectorsize =3D params.sector_size; =20 total =3D bd->bd_sectorsize * params.sectors; @@ -448,16 +450,29 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, = s char *buf, size_t *rsize) { struct disk_devdesc *dev =3D (struct disk_devdesc *)devdata; - uint64_t disk_blocks; - int blks, rc; + uint64_t disk_blocks, offset; + size_t blks, blkoff, bsize, rest; + caddr_t bbuf; + int rc; =20 - if (size % BD(dev).bd_sectorsize) { - panic("bd_strategy: %d bytes I/O not multiple of block size", - size); + /* + * First make sure the IO size is a 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 =3D=3D 0 || (size % BIOSDISK_SECSIZE) !=3D 0) { + printf("bd_strategy: %d bytes I/O not multiple of %d\n", + size, BIOSDISK_SECSIZE); + return (EIO); } =20 DEBUG("open_disk %p", dev); =20 + offset =3D dblk * BIOSDISK_SECSIZE; + dblk =3D offset / BD(dev).bd_sectorsize; + blkoff =3D offset % BD(dev).bd_sectorsize; + /* * 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 @@ -465,11 +480,14 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, = s * while translating block count to bytes. */ if (size > INT_MAX) { - DEBUG("too large read: %zu bytes", size); + DEBUG("too large I/O: %zu bytes", size); return (EIO); } =20 blks =3D size / BD(dev).bd_sectorsize; + if (blks =3D=3D 0 || (size % BD(dev).bd_sectorsize) !=3D 0) + blks++; + if (dblk > dblk + blks) return (EIO); =20 @@ -498,36 +516,75 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, = s if (dblk + blks >=3D dev->d_offset + disk_blocks) { blks =3D dev->d_offset + disk_blocks - dblk; size =3D blks * BD(dev).bd_sectorsize; - DEBUG("short read %d", blks); + DEBUG("short I/O %d", blks); } =20 - switch (rw & F_MASK) { - case F_READ: - DEBUG("read %d from %lld to %p", blks, dblk, buf); + if (V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize =3D=3D 0) + panic("BUG: Real mode buffer is too small\n"); =20 - if (blks && (rc =3D bd_io(dev, dblk, blks, buf, BD_RD))) { - /* Filter out floppy controller errors */ - if (BD(dev).bd_flags !=3D BD_FLOPPY || rc !=3D 0x20) { - printf("read %d from %lld to %p, error: 0x%x\n", - blks, dblk, buf, rc); + bbuf =3D PTOV(V86_IO_BUFFER); + rest =3D size; + + while (blks > 0) { + int x =3D min(blks, V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize); + + switch (rw & F_MASK) { + case F_READ: + DEBUG("read %d from %lld to %p", x, dblk, buf); + bsize =3D BD(dev).bd_sectorsize * x - blkoff; + if (rest < bsize) + bsize =3D rest; + + if ((rc =3D bd_io(dev, dblk, x, bbuf, BD_RD)) !=3D 0) + return (EIO); + + bcopy(bbuf + blkoff, buf, bsize); + break; + case F_WRITE : + DEBUG("write %d from %lld to %p", x, dblk, buf); + if (blkoff !=3D 0) { + /* + * We got offset to sector, read 1 sector to + * bbuf. + */ + x =3D 1; + bsize =3D BD(dev).bd_sectorsize - blkoff; + bsize =3D min(bsize, rest); + rc =3D bd_io(dev, dblk, x, bbuf, BD_RD); + } else if (rest < BD(dev).bd_sectorsize) { + /* + * The remaining block is not full + * sector. Read 1 sector to bbuf. + */ + x =3D 1; + bsize =3D rest; + rc =3D bd_io(dev, dblk, x, bbuf, BD_RD); + } else { + /* We can write full sector(s). */ + bsize =3D BD(dev).bd_sectorsize * x; } - return (EIO); - } - break; - case F_WRITE : - DEBUG("write %d from %lld to %p", blks, dblk, buf); + /* + * Put your Data In, Put your Data out, + * Put your Data In, and shake it all about + */ + bcopy(buf, bbuf + blkoff, bsize); + if ((rc =3D bd_io(dev, dblk, x, bbuf, BD_WR)) !=3D 0) + return (EIO); =20 - if (blks && bd_io(dev, dblk, blks, buf, BD_WR)) { - DEBUG("write error"); - return (EIO); + break; + default: + /* DO NOTHING */ + return (EROFS); } - break; - default: - /* DO NOTHING */ - return (EROFS); + + blkoff =3D 0; + buf +=3D bsize; + rest -=3D bsize; + blks -=3D x; + dblk +=3D x; } =20 - if (rsize) + if (rsize !=3D NULL) *rsize =3D size; return (0); } @@ -604,21 +661,16 @@ bd_io_workaround(struct disk_devdesc *dev) bd_edd_io(dev, 0xffffffff, 1, (caddr_t)buf, BD_RD); } =20 - static int 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; - =20 + int result, retry; + /* Just in case some idiot actually tries to read/write -1 blocks... */ if (blks < 0) return (-1); =20 - resid =3D blks; - p =3D dest; - /* * Workaround for a problem with some HP ProLiant BIOS failing to work * out the boot disk after installation. hrs and kuriyama discovered @@ -627,91 +679,49 @@ bd_io(struct disk_devdesc *dev, daddr_t dblk, int blk= s * 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. + * Loop retrying the operation a couple of times. The BIOS + * may also retry. */ if (dowrite =3D=3D BD_RD && dblk >=3D 0x100000000) bd_io_workaround(dev); + for (retry =3D 0; retry < 3; retry++) { + /* if retrying, reset the drive */ + if (retry > 0) { + v86.ctl =3D V86_FLAGS; + v86.addr =3D 0x13; + v86.eax =3D 0; + v86.edx =3D BD(dev).bd_unit; + v86int(); + } =20 - /* Decide whether we have to bounce */ - if (VTOP(dest) >> 20 !=3D 0 || (BD(dev).bd_unit < 0x80 && - (VTOP(dest) >> 16) !=3D - (VTOP(dest + blks * BD(dev).bd_sectorsize) >> 16))) { + if (BD(dev).bd_flags & BD_MODEEDD1) + result =3D bd_edd_io(dev, dblk, blks, dest, dowrite); + else + result =3D bd_chs_io(dev, dblk, blks, dest, dowrite); =20 - /*=20 - * 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 =3D V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize; - x =3D min(x, (unsigned)blks); - bbuf =3D PTOV(V86_IO_BUFFER); - maxfer =3D x; /* limit transfers to bounce region size */ - } else { - bbuf =3D NULL; - maxfer =3D 0; + if (result =3D=3D 0) + break; } - =20 - while (resid > 0) { - /* - * Play it safe and don't cross track boundaries. - * (XXX this is probably unnecessary) - */ - sec =3D dblk % BD(dev).bd_sec; /* offset into track */ - x =3D min(BD(dev).bd_sec - sec, resid); - if (maxfer > 0) - x =3D min(x, maxfer); /* fit bounce buffer */ =20 - /* where do we transfer to? */ - xp =3D bbuf =3D=3D NULL ? p : bbuf; - - /* - * Put your Data In, Put your Data out, - * Put your Data In, and shake it all about=20 - */ - if (dowrite =3D=3D BD_WR && bbuf !=3D NULL) - bcopy(p, bbuf, x * BD(dev).bd_sectorsize); - - /* - * Loop retrying the operation a couple of times. The BIOS - * may also retry. - */ - for (retry =3D 0; retry < 3; retry++) { - /* if retrying, reset the drive */ - if (retry > 0) { - v86.ctl =3D V86_FLAGS; - v86.addr =3D 0x13; - v86.eax =3D 0; - v86.edx =3D BD(dev).bd_unit; - v86int(); - } - - if (BD(dev).bd_flags & BD_MODEEDD1) - result =3D bd_edd_io(dev, dblk, x, xp, dowrite); - else - result =3D bd_chs_io(dev, dblk, x, xp, dowrite); - if (result =3D=3D 0) - break; + /* + * 0x20 - Controller failure. This is common error when the + * media is not present. + */ + if (result !=3D 0 && result !=3D 0x20) { + if (dowrite =3D=3D BD_WR) { + printf("%s%d: Write %d sector(s) from %p (0x%x) " + "to %lld: 0x%x\n", dev->dd.d_dev->dv_name, + dev->dd.d_unit, blks, dest, VTOP(dest), dblk, + result); + } else { + printf("%s%d: Read %d sector(s) from %lld to %p " + "(0x%x): 0x%x\n", dev->dd.d_dev->dv_name, + dev->dd.d_unit, blks, dblk, dest, VTOP(dest), + result); } - - if (dowrite =3D=3D 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 =3D=3D BD_RD && bbuf !=3D NULL) - bcopy(bbuf, p, x * BD(dev).bd_sectorsize); - p +=3D (x * BD(dev).bd_sectorsize); - dblk +=3D x; - resid -=3D x; } =20 - return (0); + return (result); } =20 /*