svn commit: r305178 - head/sys/boot/i386/libi386

Toomas Soome tsoome at FreeBSD.org
Thu Sep 1 06:35:14 UTC 2016


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);
 }
 
 /*


More information about the svn-src-all mailing list