--- truecrypt/boot/windows/bootdiskio.cpp 2018/04/24 16:55:30 1.1.1.3 +++ truecrypt/boot/windows/bootdiskio.cpp 2018/04/24 17:12:26 1.1.1.9 @@ -1,9 +1,9 @@ /* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + Copyright (c) 2008-2011 TrueCrypt Developers Association. All rights reserved. - Governed by the TrueCrypt License 2.5 the full text of which is contained - in the file License.txt included in TrueCrypt binary and source code - distribution packages. + Governed by the TrueCrypt License 3.0 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. */ #include "Bios.h" @@ -12,6 +12,7 @@ #include "BootDebug.h" #include "BootDefs.h" #include "BootDiskIo.h" +#include "BootStrings.h" byte SectorBuffer[TC_LB_SIZE]; @@ -69,7 +70,7 @@ void PrintDiskError (BiosResult error, b Print (write ? "Write" : "Read"); Print (" error:"); Print (error); Print (" Drive:"); - Print (drive < TC_FIRST_BIOS_DRIVE ? drive : drive - TC_FIRST_BIOS_DRIVE); + Print (drive ^ 0x80); if (sector) { @@ -114,27 +115,38 @@ BiosResult ReadWriteSectors (bool write, byte function = write ? 0x03 : 0x02; BiosResult result; - __asm - { - push es - mov ax, bufferSegment - mov es, ax - mov bx, bufferOffset - mov dl, drive - mov ch, cylinderLow - mov si, chs - mov dh, [si].Head - mov cl, sector - mov al, sectorCount - mov ah, function - int 0x13 - mov result, ah - pop es - } + byte tryCount = TC_MAX_BIOS_DISK_IO_RETRIES; - if (result == BiosResultEccCorrected) + do + { result = BiosResultSuccess; + __asm + { + push es + mov ax, bufferSegment + mov es, ax + mov bx, bufferOffset + mov dl, drive + mov ch, cylinderLow + mov si, chs + mov dh, [si].Head + mov cl, sector + mov al, sectorCount + mov ah, function + int 0x13 + jnc ok // If CF=0, ignore AH to prevent issues caused by potential bugs in BIOSes + mov result, ah + ok: + pop es + } + + if (result == BiosResultEccCorrected) + result = BiosResultSuccess; + + // Some BIOSes report I/O errors prematurely in some cases + } while (result != BiosResultSuccess && --tryCount != 0); + if (!silent && result != BiosResultSuccess) PrintDiskError (result, write, drive, nullptr, &chs); @@ -166,6 +178,19 @@ static BiosResult ReadWriteSectors (bool { CheckStack(); + if (!IsLbaSupported (drive)) + { + DriveGeometry geometry; + + BiosResult result = GetDriveGeometry (drive, geometry, silent); + if (result != BiosResultSuccess) + return result; + + ChsAddress chs; + LbaToChs (geometry, sector, chs); + return ReadWriteSectors (write, (uint16) (dapPacket.Buffer >> 16), (uint16) dapPacket.Buffer, drive, chs, sectorCount, silent); + } + dapPacket.Size = sizeof (dapPacket); dapPacket.Reserved = 0; dapPacket.SectorCount = sectorCount; @@ -174,20 +199,31 @@ static BiosResult ReadWriteSectors (bool byte function = write ? 0x43 : 0x42; BiosResult result; - __asm - { - mov bx, 0x55aa - mov dl, drive - mov si, [dapPacket] - mov ah, function - xor al, al - int 0x13 - mov result, ah - } + byte tryCount = TC_MAX_BIOS_DISK_IO_RETRIES; - if (result == BiosResultEccCorrected) + do + { result = BiosResultSuccess; + __asm + { + mov bx, 0x55aa + mov dl, drive + mov si, [dapPacket] + mov ah, function + xor al, al + int 0x13 + jnc ok // If CF=0, ignore AH to prevent issues caused by potential bugs in BIOSes + mov result, ah + ok: + } + + if (result == BiosResultEccCorrected) + result = BiosResultSuccess; + + // Some BIOSes report I/O errors prematurely in some cases + } while (result != BiosResultSuccess && --tryCount != 0); + if (!silent && result != BiosResultSuccess) PrintDiskError (result, write, drive, §or); @@ -210,29 +246,25 @@ BiosResult ReadWriteSectors (bool write, return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); } - BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent) { - if (IsLbaSupported (drive)) - return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, sector, sectorCount, silent); - - DriveGeometry geometry; - - BiosResult result = GetDriveGeometry (drive, geometry, silent); - if (result != BiosResultSuccess) - return result; - - ChsAddress chs; - LbaToChs (geometry, sector, chs); - return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, chs, sectorCount, silent); + return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, sector, sectorCount, silent); } BiosResult ReadSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) { + BiosResult result; uint16 codeSeg; __asm mov codeSeg, cs - return ReadSectors (codeSeg, (uint16) buffer, drive, sector, sectorCount, silent); + + result = ReadSectors (BootStarted ? codeSeg : TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, drive, sector, sectorCount, silent); + + // Alternative segment is used to prevent memory corruption caused by buggy BIOSes + if (!BootStarted) + CopyMemory (TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, buffer, sectorCount * TC_LB_SIZE); + + return result; } @@ -256,11 +288,9 @@ BiosResult GetDriveGeometry (byte drive, int 0x13 mov result, ah - jc err mov maxCylinderLow, ch mov maxSector, cl mov maxHead, dh -err: pop es } @@ -272,8 +302,11 @@ err: } else if (!silent) { - PrintError ("Cannot get geometry of drive ", true, false); - Print (drive); + Print ("Drive "); + Print (drive ^ 0x80); + Print (" not found: "); + PrintErrorNoEndl (""); + Print (result); PrintEndl(); } @@ -290,10 +323,10 @@ void ChsToLba (const DriveGeometry &geom void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs) { - chs.Sector = (lba.LowPart % geometry.Sectors) + 1; + chs.Sector = (byte) ((lba.LowPart % geometry.Sectors) + 1); uint32 ch = lba.LowPart / geometry.Sectors; - chs.Head = ch % geometry.Heads; - chs.Cylinder = ch / geometry.Heads; + chs.Head = (byte) (ch % geometry.Heads); + chs.Cylinder = (uint16) (ch / geometry.Heads); } @@ -312,12 +345,14 @@ void PartitionEntryMBRToPartition (const BiosResult ReadWriteMBR (bool write, byte drive, bool silent) { - ChsAddress chs; - chs.Cylinder = 0; - chs.Head = 0; - chs.Sector = 1; + uint64 mbrSector; + mbrSector.HighPart = 0; + mbrSector.LowPart = 0; + + if (write) + return WriteSectors (SectorBuffer, drive, mbrSector, 1, silent); - return ReadWriteSectors (write, SectorBuffer, drive, chs, 1, silent); + return ReadSectors (SectorBuffer, drive, mbrSector, 1, silent); // Uses alternative segment } @@ -437,20 +472,16 @@ BiosResult GetDrivePartitions (byte driv } -bool GetActiveAndFollowingPartition (byte drive) +bool GetActivePartition (byte drive) { size_t partCount; - // Find active partition if (GetDrivePartitions (drive, &ActivePartition, 1, partCount, true) != BiosResultSuccess || partCount < 1) { ActivePartition.Drive = TC_INVALID_BIOS_DRIVE; - PrintError ("No bootable partition found"); + PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); return false; } - - // Find partition following the active one - GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition); - + return true; }