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

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

unix.superglobalmegacorp.com

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