aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-07-01 12:47:02 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-07-01 12:47:02 -0700
commit4d98f51f96a841bd80438e25d1630cb91a9e4d7f (patch)
treef522bd40834336412a304dd1fb897b5e30e865aa
parentc575dbc5133e30c7b8f57202417696c87ec2e4fb (diff)
parent564a590beb7a686a10f8a0f1279cf83328af18e5 (diff)
downloadsyslinux-4d98f51f96a841bd80438e25d1630cb91a9e4d7f.tar.gz
syslinux-4d98f51f96a841bd80438e25d1630cb91a9e4d7f.tar.xz
syslinux-4d98f51f96a841bd80438e25d1630cb91a9e4d7f.zip
Merge branch 'master' of ssh://terminus.zytor.com/pub/git/syslinux/syslinux
-rw-r--r--NEWS3
-rw-r--r--core/fs/diskio.c124
2 files changed, 72 insertions, 55 deletions
diff --git a/NEWS b/NEWS
index 215f1550..84b77c8f 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ Changes in 4.01:
low memory.
* SYSLINUX/EXTLINUX: fix handing of disk read retries in
EDD mode.
+ * ISOLINUX: change the initialization sequence to avoid
+ problems with certain (old) BIOSes. Special thanks to
+ Helmut Hullen for invaluable debugging support.
Changes in 4.00:
* Major code base changes; all filesystem rewritten in C.
diff --git a/core/fs/diskio.c b/core/fs/diskio.c
index 176c5bcc..fb53109e 100644
--- a/core/fs/diskio.c
+++ b/core/fs/diskio.c
@@ -76,6 +76,9 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
__intcall(0x13, &ireg, &oreg);
if (!(oreg.eflags.l & EFLAGS_CF))
break;
+
+ dprintf("CHS: error AX = %04x\n", oreg.eax.w[0]);
+
if (retry--)
continue;
@@ -87,7 +90,8 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf,
ireg.eax.b[0] = chunk;
continue;
} else {
- printf("CHS: Error %s sector %llu (%u/%u/%u)\n",
+ printf("CHS: Error %04x %s sector %llu (%u/%u/%u)\n",
+ oreg.eax.w[0],
is_write ? "writing" : "reading",
lba, c, h, s+1);
}
@@ -176,6 +180,9 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
__intcall(0x13, &ireg, &oreg);
if (!(oreg.eflags.l & EFLAGS_CF))
break;
+
+ dprintf("EDD: error AX = %04x\n", oreg.eax.w[0]);
+
if (retry--)
continue;
@@ -188,7 +195,8 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf,
}
/*** XXX: Consider falling back to CHS here?! ***/
- printf("EDD: Error %s sector %llu\n",
+ printf("EDD: Error %04x %s sector %llu\n",
+ oreg.eax.w[0],
is_write ? "writing" : "reading",
lba);
return done; /* Failure */
@@ -259,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;
- if ((int8_t)devno < 0) {
- /* Get hard disk geometry from BIOS */
+ /* Get EBIOS support */
+ ireg.eax.b[1] = 0x41;
+ ireg.ebx.w[0] = 0x55aa;
+ ireg.eflags.b[0] = 0x3; /* CF set */
- 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) && 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 (!(oreg.eflags.l & EFLAGS_CF)) {
- disk.h = oreg.edx.b[1] + 1;
- disk.s = oreg.ecx.b[0] & 63;
+ if (edd_params.sector_size >= 512 &&
+ is_power_of_2(edd_params.sector_size))
+ sector_size = edd_params.sector_size;
+ }
}
+
}
disk.disk_number = devno;
@@ -335,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;
}