[syslinux:master] core, diskio: skip EDD/CHS detect for CD-ROMs

syslinux-bot for H. Peter Anvin hpa at linux.intel.com
Thu Jul 1 07:24:47 PDT 2010


Commit-ID:  e59b713abd2875ba8ad464c41e40582462e01b80
Gitweb:     http://syslinux.zytor.com/commit/e59b713abd2875ba8ad464c41e40582462e01b80
Author:     H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Wed, 30 Jun 2010 14:02:56 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Thu, 1 Jul 2010 07:20:04 -0700

core, diskio: skip EDD/CHS detect for CD-ROMs

Skip EDD and CHS detection if we know it is a CD-ROM, because some
CD-ROMs possibly report bad information, and/or screw up the stack,
possibly permanently.

Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>


---
 core/fs/diskio.c |  112 ++++++++++++++++++++++++++++-------------------------
 1 files changed, 59 insertions(+), 53 deletions(-)

diff --git a/core/fs/diskio.c b/core/fs/diskio.c
index 1180c44..fb53109 100644
--- a/core/fs/diskio.c
+++ b/core/fs/diskio.c
@@ -267,68 +267,73 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start,
     static struct disk disk;
     static __lowmem struct edd_disk_params edd_params;
     com32sys_t ireg, oreg;
-    bool ebios = cdrom;
-    int sector_size = cdrom ? 2048 : 512;
-    unsigned int hard_max_transfer = ebios ? 127 : 63;
+    bool ebios;
+    int sector_size;
+    unsigned int hard_max_transfer;
 
     memset(&ireg, 0, sizeof ireg);
-
-    /* Get EBIOS support */
-    ireg.eax.b[1] = 0x41;
-    ireg.ebx.w[0] = 0x55aa;
     ireg.edx.b[0] = devno;
-    ireg.eflags.b[0] = 0x3;	/* CF set */
-
-    __intcall(0x13, &ireg, &oreg);
 
-    if (cdrom || (!(oreg.eflags.l & EFLAGS_CF) &&
-		  oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1))) {
+    if (cdrom) {
+	/*
+	 * The query functions don't work right on some CD-ROM stacks.
+	 * Known affected systems: ThinkPad T22, T23.
+	 */
+	sector_size = 2048;
 	ebios = true;
-	hard_max_transfer = 127;
-
-	/* Query EBIOS parameters */
-	edd_params.len = sizeof edd_params;
-
-	ireg.eax.b[1] = 0x48;
-	ireg.ds = SEG(&edd_params);
-	ireg.esi.w[0] = OFFS(&edd_params);
-	__intcall(0x13, &ireg, &oreg);
-
-	if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.b[1] == 0) {
-	    if (edd_params.len < sizeof edd_params)
-		memset((char *)&edd_params + edd_params.len, 0,
-		       sizeof edd_params - edd_params.len);
-
-	    /*
-	     * Note: filter impossible sector sizes.  Some BIOSes
-	     * are known to report incorrect sector size information
-	     * (usually 512 rather than 2048) for CD-ROMs, so at least
-	     * for now ignore the reported sector size if booted via
-	     * El Torito.
-	     *
-	     * Known affected systems: ThinkPad T22, T23.
-	     */
-	    if (!cdrom &&
-		edd_params.sector_size >= 512 &&
-		is_power_of_2(edd_params.sector_size))
-		sector_size = edd_params.sector_size;
+	hard_max_transfer = 32;
+    } else {
+	sector_size = 512;
+	ebios = false;
+	hard_max_transfer = 63;
+
+	/* CBIOS parameters */
+	disk.h = bsHeads;
+	disk.s = bsSecPerTrack;
+
+	if ((int8_t)devno < 0) {
+	    /* Get hard disk geometry from BIOS */
+	    
+	    ireg.eax.b[1] = 0x08;
+	    __intcall(0x13, &ireg, &oreg);
+	    
+	    if (!(oreg.eflags.l & EFLAGS_CF)) {
+		disk.h = oreg.edx.b[1] + 1;
+		disk.s = oreg.ecx.b[0] & 63;
+	    }
 	}
-    }
 
-    /* CBIOS parameters */
-    disk.h = bsHeads;
-    disk.s = bsSecPerTrack;
+	/* Get EBIOS support */
+	ireg.eax.b[1] = 0x41;
+	ireg.ebx.w[0] = 0x55aa;
+	ireg.eflags.b[0] = 0x3;	/* CF set */
 
-    if ((int8_t)devno < 0) {
-	/* Get hard disk geometry from BIOS */
-
-	ireg.eax.b[1] = 0x08;
 	__intcall(0x13, &ireg, &oreg);
+	
+	if (!(oreg.eflags.l & EFLAGS_CF) &&
+	    oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1)) {
+	    ebios = true;
+	    hard_max_transfer = 127;
+
+	    /* Query EBIOS parameters */
+	    edd_params.len = sizeof edd_params;
+
+	    ireg.eax.b[1] = 0x48;
+	    ireg.ds = SEG(&edd_params);
+	    ireg.esi.w[0] = OFFS(&edd_params);
+	    __intcall(0x13, &ireg, &oreg);
 
-	if (!(oreg.eflags.l & EFLAGS_CF)) {
-	    disk.h = oreg.edx.b[1] + 1;
-	    disk.s = oreg.ecx.b[0] & 63;
+	    if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.b[1] == 0) {
+		if (edd_params.len < sizeof edd_params)
+		    memset((char *)&edd_params + edd_params.len, 0,
+			   sizeof edd_params - edd_params.len);
+
+		if (edd_params.sector_size >= 512 &&
+		    is_power_of_2(edd_params.sector_size))
+		    sector_size = edd_params.sector_size;
+	    }
 	}
+
     }
 
     disk.disk_number   = devno;
@@ -343,8 +348,9 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start,
 
     disk.maxtransfer   = MaxTransfer;
 
-    dprintf("disk %02x cdrom %d type %d sector %u/%u offset %llu\n",
-	    devno, cdrom, ebios, sector_size, disk.sector_shift, part_start);
+    dprintf("disk %02x cdrom %d type %d sector %u/%u offset %llu limit %u\n",
+	    devno, cdrom, ebios, sector_size, disk.sector_shift,
+	    part_start, disk.maxtransfer);
 
     return &disk;
 }



More information about the Syslinux-commits mailing list