--- truecrypt/boot/windows/bootdiskio.cpp 2018/04/24 16:52:09 1.1.1.2 +++ truecrypt/boot/windows/bootdiskio.cpp 2018/04/24 17:07:44 1.1.1.7 @@ -1,16 +1,18 @@ /* - Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. + Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved. - Governed by the TrueCrypt License 2.4 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 2.8 the full text of which is contained in + the file License.txt included in TrueCrypt binary and source code distribution + packages. */ #include "Bios.h" #include "BootConsoleIo.h" +#include "BootConfig.h" #include "BootDebug.h" #include "BootDefs.h" #include "BootDiskIo.h" +#include "BootStrings.h" byte SectorBuffer[TC_LB_SIZE]; @@ -37,7 +39,13 @@ void ReleaseSectorBuffer () bool IsLbaSupported (byte drive) { + static byte CachedDrive = TC_INVALID_BIOS_DRIVE; + static bool CachedStatus; uint16 result = 0; + + if (CachedDrive == drive) + goto ret; + __asm { mov bx, 0x55aa @@ -49,7 +57,10 @@ bool IsLbaSupported (byte drive) err: } - return result == 0xaa55; + CachedDrive = drive; + CachedStatus = (result == 0xaa55); +ret: + return CachedStatus; } @@ -57,9 +68,9 @@ void PrintDiskError (BiosResult error, b { PrintEndl(); Print (write ? "Write" : "Read"); Print (" error:"); - PrintHex (error); + Print (error); Print (" Drive:"); - Print (drive < TC_FIRST_BIOS_DRIVE ? drive : drive - TC_FIRST_BIOS_DRIVE); + Print (drive ^ 0x80); if (sector) { @@ -88,6 +99,12 @@ void Print (const ChsAddress &chs) } +void PrintSectorCountInMB (const uint64 §orCount) +{ + Print (sectorCount >> (TC_LB_SIZE_BIT_SHIFT_DIVISOR + 2)); Print (" MB "); +} + + BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) { CheckStack(); @@ -97,7 +114,7 @@ BiosResult ReadWriteSectors (bool write, sector |= byte (chs.Cylinder >> 2) & 0xc0; byte function = write ? 0x03 : 0x02; - BiosResult result; + BiosResult result = BiosResultSuccess; __asm { push es @@ -112,7 +129,9 @@ BiosResult ReadWriteSectors (bool write, 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 } @@ -130,7 +149,7 @@ BiosResult ReadWriteSectors (bool write, { uint16 codeSeg; __asm mov codeSeg, cs - return ReadWriteSectors (false, codeSeg, (uint16) buffer, drive, chs, sectorCount, silent); + return ReadWriteSectors (write, codeSeg, (uint16) buffer, drive, chs, sectorCount, silent); } @@ -150,6 +169,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; @@ -157,7 +189,7 @@ static BiosResult ReadWriteSectors (bool byte function = write ? 0x43 : 0x42; - BiosResult result; + BiosResult result = BiosResultSuccess; __asm { mov bx, 0x55aa @@ -166,7 +198,9 @@ static BiosResult ReadWriteSectors (bool 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) @@ -194,29 +228,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; } @@ -240,11 +270,9 @@ BiosResult GetDriveGeometry (byte drive, int 0x13 mov result, ah - jc err mov maxCylinderLow, ch mov maxSector, cl mov maxHead, dh -err: pop es } @@ -256,8 +284,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(); } @@ -274,10 +305,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); } @@ -294,17 +325,39 @@ void PartitionEntryMBRToPartition (const } -BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, bool silent) +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 ReadSectors (SectorBuffer, drive, mbrSector, 1, silent); // Uses alternative segment +} + + +BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, Partition *findPartitionFollowingThis, bool silent) +{ + Partition *followingPartition; + Partition tmpPartition; + + if (findPartitionFollowingThis) + { + assert (partitionArrayCapacity == 1); + partitionArrayCapacity = 0xff; + followingPartition = partitionArray; + partitionArray = &tmpPartition; + + followingPartition->Drive = TC_INVALID_BIOS_DRIVE; + followingPartition->StartSector.LowPart = 0xFFFFffffUL; + } AcquireSectorBuffer(); - BiosResult result = ReadSectors (SectorBuffer, drive, chs, 1, silent); - + BiosResult result = ReadWriteMBR (false, drive, silent); ReleaseSectorBuffer(); + partitionCount = 0; MBR *mbr = (MBR *) SectorBuffer; @@ -347,7 +400,7 @@ BiosResult GetDrivePartitions (byte driv { if (extMbr->Partitions[0].SectorCountLBA > 0) { - Partition &logPart = partitionArray[partitionArrayPos++]; + Partition &logPart = partitionArray[partitionArrayPos]; PartitionEntryMBRToPartition (extMbr->Partitions[0], logPart); logPart.Drive = drive; @@ -356,6 +409,17 @@ BiosResult GetDrivePartitions (byte driv logPart.StartSector.LowPart += extStartLBA.LowPart; logPart.EndSector.LowPart += extStartLBA.LowPart; + + if (findPartitionFollowingThis) + { + if (logPart.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart + && logPart.StartSector.LowPart < followingPartition->StartSector.LowPart) + { + *followingPartition = logPart; + } + } + else + ++partitionArrayPos; } // Secondary extended @@ -369,8 +433,18 @@ BiosResult GetDrivePartitions (byte driv } else { - ++partitionArrayPos; partition.Primary = true; + + if (findPartitionFollowingThis) + { + if (partition.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart + && partition.StartSector.LowPart < followingPartition->StartSector.LowPart) + { + *followingPartition = partition; + } + } + else + ++partitionArrayPos; } } } @@ -380,7 +454,16 @@ BiosResult GetDrivePartitions (byte driv } -BiosResult GetActivePartition (byte drive, Partition &partition, size_t &partitionCount, bool silent) +bool GetActivePartition (byte drive) { - return GetDrivePartitions (drive, &partition, 1, partitionCount, true, silent); + size_t partCount; + + if (GetDrivePartitions (drive, &ActivePartition, 1, partCount, true) != BiosResultSuccess || partCount < 1) + { + ActivePartition.Drive = TC_INVALID_BIOS_DRIVE; + PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); + return false; + } + + return true; }