aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-06-30 14:02:56 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-07-01 07:20:04 -0700
commite59b713abd2875ba8ad464c41e40582462e01b80 (patch)
treec5ceb489a230c0dcae6f00d9e645b604fe6f15cb
parent04639c3ea4179a98d555c13ce6b73d49e96bf4e5 (diff)
downloadsyslinux-e59b713abd2875ba8ad464c41e40582462e01b80.tar.gz
syslinux-e59b713abd2875ba8ad464c41e40582462e01b80.tar.xz
syslinux-e59b713abd2875ba8ad464c41e40582462e01b80.zip
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@linux.intel.com>
-rw-r--r--core/fs/diskio.c112
1 files changed, 59 insertions, 53 deletions
diff --git a/core/fs/diskio.c b/core/fs/diskio.c
index 1180c445..fb53109e 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;
}