diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-06-30 14:02:56 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-07-01 07:20:04 -0700 |
commit | e59b713abd2875ba8ad464c41e40582462e01b80 (patch) | |
tree | c5ceb489a230c0dcae6f00d9e645b604fe6f15cb /core/fs | |
parent | 04639c3ea4179a98d555c13ce6b73d49e96bf4e5 (diff) | |
download | syslinux-e59b713abd2875ba8ad464c41e40582462e01b80.tar.gz |
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>
Diffstat (limited to 'core/fs')
-rw-r--r-- | 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 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; } |