Date: Thu, 4 May 2017 05:26:37 +0000 (UTC) From: Toomas Soome <tsoome@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r317785 - head/sys/boot/i386/zfsboot Message-ID: <201705040526.v445QbfU077237@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tsoome Date: Thu May 4 05:26:37 2017 New Revision: 317785 URL: https://svnweb.freebsd.org/changeset/base/317785 Log: zfsboot: drvsize() may be unusable on some systems From user report, the errors are seen: error 1 error 1 gptzfsboot: error 1 lba 4294967288 gptzfsboot: error 1 lba 1 gptzfsboot: no ZFS pools located, can't boot The first two errors above are from issuing INT13 EAX=0x4800, meaning we need to check if EDD is available and use EAX=0x800 if not. For an workaround I'm using the similar idea as in biosdisk.c - first probe ah=8h, then check if we have EDD. Note we would like to see the correct disk size info, but we *may* get away with anything >64MB, so we could at least test 2 zfs pool labels on whole disk setup and not to freak out the INT13 interface. If we get away with initial disk probing, then we have partition sizes from the partition table and we should be able to complete the disk probing. Note: this update does not provide full fix to all errors, but we get the drvsize() errors removed. Reported by: Michael W. Lucas Reviewed by: julian Differential Revision: https://reviews.freebsd.org/D10591 Modified: head/sys/boot/i386/zfsboot/zfsboot.c Modified: head/sys/boot/i386/zfsboot/zfsboot.c ============================================================================== --- head/sys/boot/i386/zfsboot/zfsboot.c Thu May 4 03:11:59 2017 (r317784) +++ head/sys/boot/i386/zfsboot/zfsboot.c Thu May 4 05:26:37 2017 (r317785) @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "lib.h" #include "rbx.h" #include "drv.h" +#include "edd.h" #include "util.h" #include "cons.h" #include "bootargs.h" @@ -125,6 +126,7 @@ static int parse_cmd(void); static void bios_getmem(void); void *malloc(size_t n); void free(void *ptr); +int main(void); void * malloc(size_t n) @@ -469,6 +471,56 @@ copy_dsk(struct dsk *dsk) } /* + * Get disk size from eax=0x800 and 0x4800. We need to probe both + * because 0x4800 may not be available and we would like to get more + * or less correct disk size - if it is possible at all. + * Note we do not really want to touch drv.c because that code is shared + * with boot2 and we can not afford to grow that code. + */ +static uint64_t +drvsize_ext(struct dsk *dskp) +{ + uint64_t size, tmp; + int cyl, hds, sec; + + v86.ctl = V86_FLAGS; + v86.addr = 0x13; + v86.eax = 0x800; + v86.edx = dskp->drive; + v86int(); + + /* Don't error out if we get bad sector number, try EDD as well */ + if (V86_CY(v86.efl) || /* carry set */ + (v86.edx & 0xff) <= (unsigned)(dskp->drive & 0x7f)) /* unit # bad */ + return (0); + + cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1; + /* Convert max head # -> # of heads */ + hds = ((v86.edx & 0xff00) >> 8) + 1; + sec = v86.ecx & 0x3f; + + size = (uint64_t)cyl * hds * sec; + + /* Determine if we can use EDD with this device. */ + v86.ctl = V86_FLAGS; + v86.addr = 0x13; + v86.eax = 0x4100; + v86.edx = dskp->drive; + v86.ebx = 0x55aa; + v86int(); + if (V86_CY(v86.efl) || /* carry set */ + (v86.ebx & 0xffff) != 0xaa55 || /* signature */ + (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0) + return (size); + + tmp = drvsize(dskp); + if (tmp > size) + size = tmp; + + return (size); +} + +/* * The "layered" ioctl to read disk/partition size. Unfortunately * the zfsboot case is hardest, because we do not have full software * stack available, so we need to do some manual work here. @@ -480,7 +532,7 @@ ldi_get_size(void *priv) uint64_t size = dskp->size; if (dskp->start == 0) - size = drvsize(dskp); + size = drvsize_ext(dskp); return (size * DEV_BSIZE); } @@ -515,7 +567,7 @@ probe_drive(struct dsk *dsk) * out the partition table and probe each slice/partition * in turn for a vdev or GELI encrypted vdev. */ - elba = drvsize(dsk); + elba = drvsize_ext(dsk); if (elba > 0) { elba--; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705040526.v445QbfU077237>