Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Sep 2016 06:35:13 +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: r305178 - head/sys/boot/i386/libi386
Message-ID:  <201609010635.u816ZDlc025340@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tsoome
Date: Thu Sep  1 06:35:13 2016
New Revision: 305178
URL: https://svnweb.freebsd.org/changeset/base/305178

Log:
  bd_int13probe() should check extended info if sector info is bad
  
  In some Dell systems and usb stick combinations, it is found that
  int13 AH=08 is reporting back bad sector information, preventing the
  boot.
  
  This update is allowing bd_int13probe() to use extended info call to
  build disk properties.
  
  It also can happen the total sectors count from extended info may be
  wrong, in such case, the CHS data is used to calculate total sectors.
  
  Reviewed by:	allanjude
  Approved by:	allanjude (mentor)
  Differential Revision:	https://reviews.freebsd.org/D7718

Modified:
  head/sys/boot/i386/libi386/biosdisk.c

Modified: head/sys/boot/i386/libi386/biosdisk.c
==============================================================================
--- head/sys/boot/i386/libi386/biosdisk.c	Thu Sep  1 06:32:35 2016	(r305177)
+++ head/sys/boot/i386/libi386/biosdisk.c	Thu Sep  1 06:35:13 2016	(r305178)
@@ -244,6 +244,7 @@ static int
 bd_int13probe(struct bdinfo *bd)
 {
 	struct edd_params params;
+	int ret = 1;	/* assume success */
 
 	v86.ctl = V86_FLAGS;
 	v86.addr = 0x13;
@@ -251,11 +252,14 @@ bd_int13probe(struct bdinfo *bd)
 	v86.edx = bd->bd_unit;
 	v86int();
 
+	/* Don't error out if we get bad sector number, try EDD as well */
 	if (V86_CY(v86.efl) ||	/* carry set */
-	    (v86.ecx & 0x3f) == 0 || /* absurd sector number */
 	    (v86.edx & 0xff) <= (unsigned)(bd->bd_unit & 0x7f))	/* unit # bad */
 		return (0);	/* skip device */
 
+	if ((v86.ecx & 0x3f) == 0) /* absurd sector number */
+		ret = 0;	/* set error */
+
 	/* Convert max cyl # -> # of cylinders */
 	bd->bd_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1;
 	/* Convert max head # -> # of heads */
@@ -280,7 +284,8 @@ bd_int13probe(struct bdinfo *bd)
 	if (V86_CY(v86.efl) ||	/* carry set */
 	    (v86.ebx & 0xffff) != 0xaa55 || /* signature */
 	    (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0)
-		return (1);
+		return (ret);	/* return code from int13 AH=08 */
+
 	/* EDD supported */
 	bd->bd_flags |= BD_MODEEDD1;
 	if ((v86.eax & 0xff00) >= 0x3000)
@@ -295,12 +300,22 @@ bd_int13probe(struct bdinfo *bd)
 	v86.esi = VTOPOFF(&params);
 	v86int();
 	if (!V86_CY(v86.efl)) {
-		bd->bd_sectors = params.sectors;
+		uint64_t total;
+
+		if (params.sectors != 0)
+			bd->bd_sectors = params.sectors;
+
+		total = (uint64_t)params.cylinders *
+		    params.heads * params.sectors_per_track;
+		if (bd->bd_sectors < total)
+			bd->bd_sectors = total;
+
 		bd->bd_sectorsize = params.sector_size;
+		ret = 1;
 	}
 	DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u",
 	    bd->bd_unit, bd->bd_flags, bd->bd_sectors, bd->bd_sectorsize);
-	return (1);
+	return (ret);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609010635.u816ZDlc025340>