Annotation of truecrypt/boot/windows/bootdiskio.cpp, revision 1.1.1.3

1.1       root        1: /*
                      2:  Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
                      3: 
1.1.1.3 ! root        4:  Governed by the TrueCrypt License 2.5 the full text of which is contained
1.1       root        5:  in the file License.txt included in TrueCrypt binary and source code
                      6:  distribution packages.
                      7: */
                      8: 
                      9: #include "Bios.h"
                     10: #include "BootConsoleIo.h"
1.1.1.3 ! root       11: #include "BootConfig.h"
1.1       root       12: #include "BootDebug.h"
1.1.1.2   root       13: #include "BootDefs.h"
1.1       root       14: #include "BootDiskIo.h"
                     15: 
                     16: 
1.1.1.2   root       17: byte SectorBuffer[TC_LB_SIZE];
                     18: 
                     19: #ifdef TC_BOOT_DEBUG_ENABLED
                     20: static bool SectorBufferInUse = false;
                     21: 
                     22: void AcquireSectorBuffer ()
                     23: {
                     24:        if (SectorBufferInUse)
                     25:                TC_THROW_FATAL_EXCEPTION;
                     26: 
                     27:        SectorBufferInUse = true;
                     28: }
                     29: 
                     30: 
                     31: void ReleaseSectorBuffer ()
                     32: {
                     33:        SectorBufferInUse = false;
                     34: }
                     35: 
                     36: #endif
                     37: 
                     38: 
1.1       root       39: bool IsLbaSupported (byte drive)
                     40: {
1.1.1.3 ! root       41:        static byte CachedDrive = TC_INVALID_BIOS_DRIVE;
        !            42:        static bool CachedStatus;
1.1       root       43:        uint16 result = 0;
1.1.1.3 ! root       44: 
        !            45:        if (CachedDrive == drive)
        !            46:                goto ret;
        !            47: 
1.1       root       48:        __asm
                     49:        {
                     50:                mov bx, 0x55aa
                     51:                mov dl, drive
                     52:                mov ah, 0x41
                     53:                int 0x13
                     54:                jc err
                     55:                mov result, bx
                     56:        err:
                     57:        }
                     58: 
1.1.1.3 ! root       59:        CachedDrive = drive;
        !            60:        CachedStatus = (result == 0xaa55);
        !            61: ret:
        !            62:        return CachedStatus;
1.1       root       63: }
                     64: 
                     65: 
                     66: void PrintDiskError (BiosResult error, bool write, byte drive, const uint64 *sector, const ChsAddress *chs)
                     67: {
                     68:        PrintEndl();
                     69:        Print (write ? "Write" : "Read"); Print (" error:");
1.1.1.3 ! root       70:        Print (error);
1.1       root       71:        Print (" Drive:");
                     72:        Print (drive < TC_FIRST_BIOS_DRIVE ? drive : drive - TC_FIRST_BIOS_DRIVE);
                     73: 
                     74:        if (sector)
                     75:        {
                     76:                Print (" Sector:");
                     77:                Print (*sector);
                     78:        }
                     79: 
                     80:        if (chs)
                     81:        {
                     82:                Print (" CHS:");
                     83:                Print (*chs);
                     84:        }
                     85: 
                     86:        PrintEndl();
                     87:        Beep();
                     88: }
                     89: 
                     90: 
                     91: void Print (const ChsAddress &chs)
                     92: {
                     93:        Print (chs.Cylinder);
                     94:        PrintChar ('/');
                     95:        Print (chs.Head);
                     96:        PrintChar ('/');
                     97:        Print (chs.Sector);
                     98: }
                     99: 
                    100: 
1.1.1.3 ! root      101: void PrintSectorCountInMB (const uint64 &sectorCount)
        !           102: {
        !           103:        Print (sectorCount >> (TC_LB_SIZE_BIT_SHIFT_DIVISOR + 2)); Print (" MB ");
        !           104: }
        !           105: 
        !           106: 
1.1.1.2   root      107: BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const ChsAddress &chs, byte sectorCount, bool silent)
1.1       root      108: {
1.1.1.2   root      109:        CheckStack();
                    110: 
1.1       root      111:        byte cylinderLow = (byte) chs.Cylinder;
                    112:        byte sector = chs.Sector;
                    113:        sector |= byte (chs.Cylinder >> 2) & 0xc0;
                    114:        byte function = write ? 0x03 : 0x02;
1.1.1.2   root      115: 
1.1       root      116:        BiosResult result;
                    117:        __asm
                    118:        {
                    119:                push es
1.1.1.2   root      120:                mov ax, bufferSegment
1.1       root      121:                mov     es, ax
1.1.1.2   root      122:                mov     bx, bufferOffset
                    123:                mov dl, drive
                    124:                mov ch, cylinderLow
1.1       root      125:                mov si, chs
1.1.1.2   root      126:                mov dh, [si].Head
                    127:                mov cl, sector
                    128:                mov     al, sectorCount
1.1       root      129:                mov     ah, function
                    130:                int     0x13
                    131:                mov     result, ah
                    132:                pop es
                    133:        }
                    134: 
                    135:        if (result == BiosResultEccCorrected)
                    136:                result = BiosResultSuccess;
                    137: 
                    138:        if (!silent && result != BiosResultSuccess)
                    139:                PrintDiskError (result, write, drive, nullptr, &chs);
                    140: 
                    141:        return result;
                    142: }
                    143: 
                    144: 
1.1.1.2   root      145: BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent)
                    146: {
                    147:        uint16 codeSeg;
                    148:        __asm mov codeSeg, cs
1.1.1.3 ! root      149:        return ReadWriteSectors (write, codeSeg, (uint16) buffer, drive, chs, sectorCount, silent);
1.1.1.2   root      150: }
                    151: 
                    152: 
1.1       root      153: BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent)
                    154: {
                    155:        return ReadWriteSectors (false, buffer, drive, chs, sectorCount, silent);
                    156: }
                    157: 
                    158: 
                    159: BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent)
                    160: {
                    161:        return ReadWriteSectors (true, buffer, drive, chs, sectorCount, silent);
                    162: }
                    163: 
                    164: 
                    165: static BiosResult ReadWriteSectors (bool write, BiosLbaPacket &dapPacket, byte drive, const uint64 &sector, uint16 sectorCount, bool silent)
                    166: {
1.1.1.2   root      167:        CheckStack();
                    168: 
1.1       root      169:        dapPacket.Size = sizeof (dapPacket);
                    170:        dapPacket.Reserved = 0;
                    171:        dapPacket.SectorCount = sectorCount;
                    172:        dapPacket.Sector = sector;
                    173: 
                    174:        byte function = write ? 0x43 : 0x42;
                    175:        
                    176:        BiosResult result;
                    177:        __asm
                    178:        {
                    179:                mov     bx, 0x55aa
                    180:                mov     dl, drive
                    181:                mov si, [dapPacket]
                    182:                mov     ah, function
                    183:                xor al, al
                    184:                int     0x13
                    185:                mov     result, ah
                    186:        }
                    187: 
                    188:        if (result == BiosResultEccCorrected)
                    189:                result = BiosResultSuccess;
                    190: 
                    191:        if (!silent && result != BiosResultSuccess)
                    192:                PrintDiskError (result, write, drive, &sector);
                    193: 
                    194:        return result;
                    195: }
                    196: 
                    197: 
                    198: static BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const uint64 &sector, uint16 sectorCount, bool silent)
                    199: {
                    200:        BiosLbaPacket dapPacket;
                    201:        dapPacket.Buffer = (uint32) buffer;
                    202:        return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent);
                    203: }
                    204: 
                    205: 
                    206: BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 &sector, uint16 sectorCount, bool silent)
                    207: {
                    208:        BiosLbaPacket dapPacket;
                    209:        dapPacket.Buffer = ((uint32) bufferSegment << 16) | bufferOffset;
                    210:        return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent);
                    211: }
                    212: 
                    213: 
1.1.1.2   root      214: BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 &sector, uint16 sectorCount, bool silent)
1.1       root      215: {
                    216:        if (IsLbaSupported (drive))
1.1.1.2   root      217:                return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, sector, sectorCount, silent);
1.1       root      218: 
                    219:        DriveGeometry geometry;
                    220: 
                    221:        BiosResult result = GetDriveGeometry (drive, geometry, silent);
                    222:        if (result != BiosResultSuccess)
                    223:                return result;
                    224: 
                    225:        ChsAddress chs;
                    226:        LbaToChs (geometry, sector, chs);
1.1.1.2   root      227:        return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, chs, sectorCount, silent);
                    228: }
                    229: 
                    230: 
                    231: BiosResult ReadSectors (byte *buffer, byte drive, const uint64 &sector, uint16 sectorCount, bool silent)
                    232: {
                    233:        uint16 codeSeg;
                    234:        __asm mov codeSeg, cs
                    235:        return ReadSectors (codeSeg, (uint16) buffer, drive, sector, sectorCount, silent);
1.1       root      236: }
                    237: 
                    238: 
                    239: BiosResult WriteSectors (byte *buffer, byte drive, const uint64 &sector, uint16 sectorCount, bool silent)
                    240: {
                    241:        return ReadWriteSectors (true, buffer, drive, sector, sectorCount, silent);
                    242: }
                    243: 
                    244: 
                    245: BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent)
                    246: {
1.1.1.2   root      247:        CheckStack();
                    248: 
1.1       root      249:        byte maxCylinderLow, maxHead, maxSector;
                    250:        BiosResult result;
                    251:        __asm
                    252:        {
                    253:                push es
                    254:                mov dl, drive
                    255:                mov ah, 0x08
                    256:                int     0x13
                    257: 
                    258:                mov     result, ah
                    259:                jc err
                    260:                mov maxCylinderLow, ch
                    261:                mov maxSector, cl
                    262:                mov maxHead, dh
                    263: err:
                    264:                pop es
                    265:        }
                    266: 
                    267:        if (result == BiosResultSuccess)
                    268:        {
                    269:                geometry.Cylinders = (maxCylinderLow | (uint16 (maxSector & 0xc0) << 2)) + 1;
                    270:                geometry.Heads = maxHead + 1;
                    271:                geometry.Sectors = maxSector & ~0xc0;
                    272:        }
                    273:        else if (!silent)
                    274:        {
                    275:                PrintError ("Cannot get geometry of drive ", true, false);
                    276:                Print (drive);
                    277:                PrintEndl();
                    278:        }
                    279: 
                    280:        return result;
                    281: }
                    282: 
                    283: 
                    284: void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba)
                    285: {
                    286:        lba.HighPart = 0;
                    287:        lba.LowPart = (uint32 (chs.Cylinder) * geometry.Heads + chs.Head) * geometry.Sectors + chs.Sector - 1;
                    288: }
                    289: 
                    290: 
                    291: void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs)
                    292: {
                    293:        chs.Sector = (lba.LowPart % geometry.Sectors) + 1;
                    294:        uint32 ch = lba.LowPart / geometry.Sectors;
                    295:        chs.Head = ch % geometry.Heads;
                    296:        chs.Cylinder = ch / geometry.Heads;
                    297: }
                    298: 
                    299: 
                    300: void PartitionEntryMBRToPartition (const PartitionEntryMBR &partEntry, Partition &partition)
                    301: {
                    302:        partition.Active = partEntry.BootIndicator == 0x80;
                    303:        partition.EndSector.HighPart = 0;
                    304:        partition.EndSector.LowPart = partEntry.StartLBA + partEntry.SectorCountLBA - 1;
                    305:        partition.SectorCount.HighPart = 0;
                    306:        partition.SectorCount.LowPart = partEntry.SectorCountLBA;
                    307:        partition.StartSector.HighPart = 0;
                    308:        partition.StartSector.LowPart = partEntry.StartLBA;
                    309:        partition.Type = partEntry.Type;
                    310: }
                    311: 
                    312: 
1.1.1.3 ! root      313: BiosResult ReadWriteMBR (bool write, byte drive, bool silent)
1.1       root      314: {
1.1.1.2   root      315:        ChsAddress chs;
                    316:        chs.Cylinder = 0;
                    317:        chs.Head = 0;
                    318:        chs.Sector = 1;
                    319: 
1.1.1.3 ! root      320:        return ReadWriteSectors (write, SectorBuffer, drive, chs, 1, silent);
        !           321: }
        !           322: 
        !           323: 
        !           324: BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, Partition *findPartitionFollowingThis, bool silent)
        !           325: {
        !           326:        Partition *followingPartition;
        !           327:        Partition tmpPartition;
        !           328: 
        !           329:        if (findPartitionFollowingThis)
        !           330:        {
        !           331:                assert (partitionArrayCapacity == 1);
        !           332:                partitionArrayCapacity = 0xff;
        !           333:                followingPartition = partitionArray;
        !           334:                partitionArray = &tmpPartition;
        !           335: 
        !           336:                followingPartition->Drive = TC_INVALID_BIOS_DRIVE;
        !           337:                followingPartition->StartSector.LowPart = 0xFFFFffffUL;
        !           338:        }
        !           339: 
1.1.1.2   root      340:        AcquireSectorBuffer();
1.1.1.3 ! root      341:        BiosResult result = ReadWriteMBR (false, drive, silent);
1.1.1.2   root      342:        ReleaseSectorBuffer();
1.1.1.3 ! root      343: 
1.1.1.2   root      344:        partitionCount = 0;
                    345: 
                    346:        MBR *mbr = (MBR *) SectorBuffer;
                    347:        if (result != BiosResultSuccess || mbr->Signature != 0xaa55)
1.1       root      348:                return result;
                    349: 
1.1.1.2   root      350:        PartitionEntryMBR mbrPartitions[4];
                    351:        memcpy (mbrPartitions, mbr->Partitions, sizeof (mbrPartitions));
1.1       root      352:        size_t partitionArrayPos = 0, partitionNumber;
                    353:        
                    354:        for (partitionNumber = 0;
1.1.1.2   root      355:                partitionNumber < array_capacity (mbrPartitions) && partitionArrayPos < partitionArrayCapacity;
1.1       root      356:                ++partitionNumber)
                    357:        {
1.1.1.2   root      358:                const PartitionEntryMBR &partEntry = mbrPartitions[partitionNumber];
1.1       root      359:                
                    360:                if (partEntry.SectorCountLBA > 0)
                    361:                {
                    362:                        Partition &partition = partitionArray[partitionArrayPos];
                    363:                        PartitionEntryMBRToPartition (partEntry, partition);
                    364: 
                    365:                        if (activeOnly && !partition.Active)
                    366:                                continue;
                    367: 
                    368:                        partition.Drive = drive;
                    369:                        partition.Number = partitionNumber;
                    370: 
                    371:                        if (partEntry.Type == 0x5 || partEntry.Type == 0xf) // Extended partition
                    372:                        {
                    373:                                if (IsLbaSupported (drive))
                    374:                                {
                    375:                                        // Find all extended partitions
                    376:                                        uint64 firstExtStartLBA = partition.StartSector;
                    377:                                        uint64 extStartLBA = partition.StartSector;
1.1.1.2   root      378:                                        MBR *extMbr = (MBR *) SectorBuffer;
1.1       root      379: 
                    380:                                        while (partitionArrayPos < partitionArrayCapacity &&
1.1.1.2   root      381:                                                (result = ReadSectors ((byte *) extMbr, drive, extStartLBA, 1, silent)) == BiosResultSuccess
                    382:                                                && extMbr->Signature == 0xaa55)
1.1       root      383:                                        {
1.1.1.2   root      384:                                                if (extMbr->Partitions[0].SectorCountLBA > 0)
1.1       root      385:                                                {
1.1.1.3 ! root      386:                                                        Partition &logPart = partitionArray[partitionArrayPos];
1.1.1.2   root      387:                                                        PartitionEntryMBRToPartition (extMbr->Partitions[0], logPart);
1.1       root      388:                                                        logPart.Drive = drive;
                    389: 
                    390:                                                        logPart.Number = partitionNumber++;
                    391:                                                        logPart.Primary = false;
                    392: 
                    393:                                                        logPart.StartSector.LowPart += extStartLBA.LowPart;
                    394:                                                        logPart.EndSector.LowPart += extStartLBA.LowPart;
1.1.1.3 ! root      395: 
        !           396:                                                        if (findPartitionFollowingThis)
        !           397:                                                        {
        !           398:                                                                if (logPart.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart
        !           399:                                                                        && logPart.StartSector.LowPart < followingPartition->StartSector.LowPart)
        !           400:                                                                {
        !           401:                                                                        *followingPartition = logPart;
        !           402:                                                                }
        !           403:                                                        }
        !           404:                                                        else
        !           405:                                                                ++partitionArrayPos;
1.1       root      406:                                                }
                    407: 
                    408:                                                // Secondary extended
1.1.1.2   root      409:                                                if (extMbr->Partitions[1].Type != 0x5 && extMbr->Partitions[1].Type == 0xf
                    410:                                                        || extMbr->Partitions[1].SectorCountLBA == 0)
1.1       root      411:                                                        break;
                    412: 
1.1.1.2   root      413:                                                extStartLBA.LowPart = extMbr->Partitions[1].StartLBA + firstExtStartLBA.LowPart;
1.1       root      414:                                        }
                    415:                                }
                    416:                        }
                    417:                        else
                    418:                        {
                    419:                                partition.Primary = true;
1.1.1.3 ! root      420: 
        !           421:                                if (findPartitionFollowingThis)
        !           422:                                {
        !           423:                                        if (partition.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart
        !           424:                                                && partition.StartSector.LowPart < followingPartition->StartSector.LowPart)
        !           425:                                        {
        !           426:                                                *followingPartition = partition;
        !           427:                                        }
        !           428:                                }
        !           429:                                else
        !           430:                                        ++partitionArrayPos;
1.1       root      431:                        }
                    432:                }
                    433:        }
                    434: 
                    435:        partitionCount = partitionArrayPos;
                    436:        return result;
                    437: }
                    438: 
                    439: 
1.1.1.3 ! root      440: bool GetActiveAndFollowingPartition (byte drive)
1.1       root      441: {
1.1.1.3 ! root      442:        size_t partCount;
        !           443: 
        !           444:        // Find active partition
        !           445:        if (GetDrivePartitions (drive, &ActivePartition, 1, partCount, true) != BiosResultSuccess || partCount < 1)
        !           446:        {
        !           447:                ActivePartition.Drive = TC_INVALID_BIOS_DRIVE;
        !           448:                PrintError ("No bootable partition found");
        !           449:                return false;
        !           450:        }
        !           451: 
        !           452:        // Find partition following the active one
        !           453:        GetDrivePartitions (drive, &PartitionFollowingActive, 1, partCount, false, &ActivePartition);
        !           454: 
        !           455:        return true;
1.1       root      456: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.