From 03a574d8cdc3613afe81d8c0125e18c1a6e4f64e Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Wed, 6 May 2009 11:55:19 +0000 Subject: [PATCH] * Check for disk extensions before using them (mostly for good practice reasons) * A CHS read error would previously be hidden by a successful disk system reset. Not that it matters much because it'd have resulted in a non-booting system anyway. * Add some more debug output, minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30643 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../boot/platform/bios_ia32/devices.cpp | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/devices.cpp b/src/system/boot/platform/bios_ia32/devices.cpp index d311067ddc..6c35c4b52f 100644 --- a/src/system/boot/platform/bios_ia32/devices.cpp +++ b/src/system/boot/platform/bios_ia32/devices.cpp @@ -198,6 +198,22 @@ check_cd_boot(BIOSDrive *drive) } +static bool +are_extensions_available(uint8 drive) +{ + struct bios_regs regs; + regs.eax = BIOS_IS_EXT_PRESENT; + regs.ebx = 0x55aa; + regs.edx = drive; + call_bios(0x13, ®s); + + TRACE(("checking extensions: carry: %u; ebx: 0x%08lx; ecx: 0x%08lx\n", + regs.flags & CARRY_FLAG, regs.ebx, regs.ecx)); + return (regs.flags & CARRY_FLAG) == 0 && regs.ebx == 0xaa55 + && (regs.ecx & 0x01 /* supports device access using packet */) != 0; +} + + static status_t get_ext_drive_parameters(uint8 drive, drive_parameters *targetParameters) { @@ -528,7 +544,7 @@ BIOSDrive::BIOSDrive(uint8 driveID) { TRACE(("drive ID %u\n", driveID)); - if (driveID < 0x80 + if (driveID < 0x80 || !are_extensions_available(driveID) || get_ext_drive_parameters(driveID, &fParameters) != B_OK) { // old style CHS support @@ -627,12 +643,16 @@ BIOSDrive::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) uint32 cylinder = head / fParameters.heads; head %= fParameters.heads; - if (cylinder >= fParameters.cylinders) + if (cylinder >= fParameters.cylinders) { + TRACE(("cylinder value %lu bigger than available %lu\n", + cylinder, fParameters.cylinders)); return B_BAD_VALUE; + } // try to read from the device more than once, just to make sure it'll work struct bios_regs regs; int32 tries = 3; + bool readWorked = false; while (tries-- > 0) { regs.eax = BIOS_READ | blocksRead; @@ -642,21 +662,26 @@ BIOSDrive::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize) regs.ebx = kExtraSegmentScratch; call_bios(0x13, ®s); - if ((regs.flags & CARRY_FLAG) == 0) + if ((regs.flags & CARRY_FLAG) == 0) { + readWorked = true; break; + } + + TRACE(("read failed\n")); if (tries < 2) { // reset disk system + TRACE(("reset disk system\n")); regs.eax = BIOS_RESET_DISK_SYSTEM; regs.edx = fDriveID; call_bios(0x13, ®s); } - + // wait a bit between the retries (1/20 sec) spin(50000); } - if (regs.flags & CARRY_FLAG) { + if (!readWorked) { dprintf("reading %ld bytes from drive %u failed at %Ld\n", blocksRead, fDriveID, pos); return B_ERROR;