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

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

unix.superglobalmegacorp.com

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