Annotation of truecrypt/boot/windows/bootmain.cpp, revision 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 "Crc.h"
        !            10: #include "Crypto.h"
        !            11: #include "Password.h"
        !            12: #include "Volumes.h"
        !            13: 
        !            14: #include "Platform.h"
        !            15: #include "Bios.h"
        !            16: #include "BootConfig.h"
        !            17: #include "BootMain.h"
        !            18: #include "BootDefs.h"
        !            19: #include "BootCommon.h"
        !            20: #include "BootConsoleIo.h"
        !            21: #include "BootDebug.h"
        !            22: #include "BootDiskIo.h"
        !            23: #include "BootEncryptedIo.h"
        !            24: #include "IntFilter.h"
        !            25: 
        !            26: 
        !            27: static void InitScreen ()
        !            28: {
        !            29:        ClearScreen();
        !            30: 
        !            31:        Print (" TrueCrypt Boot Loader " VERSION_STRING "             Copyright (C) 2008 TrueCrypt Foundation\r\n");
        !            32:        PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE);
        !            33: 
        !            34:        PrintEndl (2);
        !            35: }
        !            36: 
        !            37: 
        !            38: static void PrintMainMenu ()
        !            39: {
        !            40:        Print ("    Keyboard Controls:\r\n");
        !            41:        Print ("    [Esc]  Skip Authentication (Boot Manager)\r\n");
        !            42:        Print ("    [F8]   "); Print ("Repair Options");
        !            43: 
        !            44:        PrintEndl (3);
        !            45: }
        !            46: 
        !            47: 
        !            48: static bool IsMenuKey (byte scanCode)
        !            49: {
        !            50:        return scanCode == TC_MENU_KEY_REPAIR;
        !            51: }
        !            52: 
        !            53: 
        !            54: static bool AskYesNo (const char *message)
        !            55: {
        !            56:        Print (message);
        !            57:        Print ("? (y/n): ");
        !            58:        while (true)
        !            59:        {
        !            60:                switch (GetKeyboardChar())
        !            61:                {
        !            62:                case 'y':
        !            63:                case 'Y':
        !            64:                        PrintEndl();
        !            65:                        return true;
        !            66: 
        !            67:                case 'n':
        !            68:                case 'N':
        !            69:                        PrintEndl();
        !            70:                        return false;
        !            71: 
        !            72:                default:
        !            73:                        Beep();
        !            74:                }
        !            75:        }
        !            76: }
        !            77: 
        !            78: 
        !            79: static int AskSelection (const char *options[], size_t optionCount)
        !            80: {
        !            81:        for (int i = 0; i < optionCount; ++i)
        !            82:        {
        !            83:                Print ("["); Print (i + 1); Print ("]    ");
        !            84:                Print (options[i]);
        !            85:                PrintEndl();
        !            86:        }
        !            87:        Print ("[Esc]  Cancel\r\n\r\n");
        !            88: 
        !            89:        Print ("To select, press 1-9: ");
        !            90: 
        !            91:        char str;
        !            92: 
        !            93:        while (true)
        !            94:        {
        !            95:                if (GetString (&str, 1) == 0)
        !            96:                        return 0;
        !            97: 
        !            98:                if (str >= '1' && str <= optionCount + '0')
        !            99:                        return str - '0';
        !           100: 
        !           101:                Beep();
        !           102:                PrintBackspace();
        !           103:        }
        !           104: }
        !           105: 
        !           106: 
        !           107: static byte AskPassword (Password &password)
        !           108: {
        !           109:        size_t pos = 0;
        !           110:        byte scanCode;
        !           111:        byte asciiCode;
        !           112: 
        !           113:        Print ("Enter password: ");
        !           114: 
        !           115:        while (true)
        !           116:        {
        !           117:                asciiCode = GetKeyboardChar (&scanCode);
        !           118: 
        !           119:                switch (scanCode)
        !           120:                {
        !           121:                case TC_BIOS_KEY_ENTER:
        !           122:                        PrintEndl();
        !           123:                        goto ret;
        !           124: 
        !           125:                case TC_BIOS_KEY_BACKSPACE:
        !           126:                        if (pos > 0)
        !           127:                        {
        !           128:                                if (pos < MAX_PASSWORD)
        !           129:                                        PrintBackspace();
        !           130:                                else
        !           131:                                        PrintCharAtCusor (' ');
        !           132: 
        !           133:                                --pos;
        !           134:                        }
        !           135:                        continue;
        !           136: 
        !           137:                default:
        !           138:                        if (scanCode == TC_BIOS_KEY_ESC || IsMenuKey (scanCode))
        !           139:                        {
        !           140:                                burn (password.Text, sizeof (password.Text));
        !           141:                                PrintEndl();
        !           142:                                return scanCode;
        !           143:                        }
        !           144:                }
        !           145: 
        !           146:                if (!IsPrintable (asciiCode) || pos == MAX_PASSWORD)
        !           147:                {
        !           148:                        Beep();
        !           149:                        continue;
        !           150:                }
        !           151: 
        !           152:                password.Text[pos++] = asciiCode;
        !           153:                if (pos < MAX_PASSWORD)
        !           154:                        PrintChar ('*');
        !           155:                else
        !           156:                        PrintCharAtCusor ('*');
        !           157:        }
        !           158: 
        !           159: ret:
        !           160:        password.Length = pos;
        !           161:        return TC_BIOS_KEY_ENTER;
        !           162: }
        !           163: 
        !           164: 
        !           165: static void ExecuteBootSector (byte drive, byte *sectorBuffer)
        !           166: {
        !           167:        Print ("Booting...\r\n");
        !           168:        CopyMemory (sectorBuffer, 0x0000, 0x7c00, TC_LB_SIZE);
        !           169:        Jump (0x0000, 0x7c00, drive);
        !           170: }
        !           171: 
        !           172: 
        !           173: static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headSaltCrc32)
        !           174: {
        !           175:        byte header[HEADER_SIZE];
        !           176:        uint64 headerSec;
        !           177:        headerSec.HighPart = 0;
        !           178:        headerSec.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
        !           179: 
        !           180:        if (ReadSectors (header, drive, headerSec, 1) != BiosResultSuccess)
        !           181:                return false;
        !           182: 
        !           183:        if (VolumeReadHeader (TRUE, (char *) header, &password, cryptoInfo, nullptr) == 0)
        !           184:        {
        !           185:                if (headSaltCrc32)
        !           186:                        *headSaltCrc32 = GetCrc32 (header, PKCS5_SALT_SIZE);
        !           187:                return true;
        !           188:        }
        !           189: 
        !           190:        return false;
        !           191: }
        !           192: 
        !           193: 
        !           194: static bool MountVolume (byte drive, byte &exitKey)
        !           195: {
        !           196:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
        !           197: 
        !           198:        // Open volume header
        !           199:        while (true)
        !           200:        {
        !           201:                exitKey = AskPassword (bootArguments->BootPassword);
        !           202: 
        !           203:                if (exitKey != TC_BIOS_KEY_ENTER)
        !           204:                        return false;
        !           205: 
        !           206:                if (OpenVolume (BootDrive, bootArguments->BootPassword, &BootCryptoInfo, &bootArguments->HeaderSaltCrc32))
        !           207:                        break;
        !           208: 
        !           209:                Print ("Incorrect password or not a TrueCrypt volume.\r\n\r\n");
        !           210:        }
        !           211:        
        !           212:        // Check memory
        !           213:        uint16 codeSeg;
        !           214:        __asm mov codeSeg, cs
        !           215:        if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT)
        !           216:        {
        !           217:                PrintError ("Insufficient memory for encryption");
        !           218:                EncryptedVirtualPartition.Drive = TC_FIRST_BIOS_DRIVE - 1;
        !           219:                GetKeyboardChar ();
        !           220:                return false;
        !           221:        }
        !           222: 
        !           223:        // Setup boot arguments
        !           224:        bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo;
        !           225:        bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo);
        !           226:        bootArguments->BootLoaderVersion = VERSION_NUM;
        !           227:        TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature);
        !           228: 
        !           229:        if (BootCryptoInfo->EncryptedAreaLength.HighPart != 0 || BootCryptoInfo->EncryptedAreaLength.LowPart != 0)
        !           230:        {
        !           231:                // Setup virtual encrypted partition
        !           232:                EncryptedVirtualPartition.Drive = BootDrive;
        !           233: 
        !           234:                EncryptedVirtualPartition.StartSector.HighPart = BootCryptoInfo->EncryptedAreaStart.HighPart;
        !           235:                EncryptedVirtualPartition.StartSector.LowPart = BootCryptoInfo->EncryptedAreaStart.LowPart;
        !           236:                EncryptedVirtualPartition.StartSector = EncryptedVirtualPartition.StartSector >> TC_LB_SIZE_BIT_SHIFT_DIVISOR;
        !           237: 
        !           238:                EncryptedVirtualPartition.EndSector.HighPart = BootCryptoInfo->EncryptedAreaLength.HighPart;
        !           239:                EncryptedVirtualPartition.EndSector.LowPart = BootCryptoInfo->EncryptedAreaLength.LowPart;
        !           240:                EncryptedVirtualPartition.EndSector = (EncryptedVirtualPartition.EndSector - 1) >> TC_LB_SIZE_BIT_SHIFT_DIVISOR;
        !           241:                EncryptedVirtualPartition.EndSector = EncryptedVirtualPartition.EndSector + EncryptedVirtualPartition.StartSector;
        !           242:        }
        !           243:        else
        !           244:        {
        !           245:                // Drive not encrypted
        !           246:                EncryptedVirtualPartition.Drive = TC_FIRST_BIOS_DRIVE - 1;
        !           247:        }
        !           248: 
        !           249:        return true;
        !           250: }
        !           251: 
        !           252: 
        !           253: static byte BootEncryptedDrive ()
        !           254: {
        !           255:        Partition partition;
        !           256:        size_t partCount;
        !           257: 
        !           258:        // Find active partition
        !           259:        if (GetActivePartition (BootDrive, partition, partCount, false) != BiosResultSuccess || partCount < 1)
        !           260:        {
        !           261:                PrintError ("No bootable partition found");
        !           262:                goto err;
        !           263:        }
        !           264: 
        !           265:        byte exitKey;
        !           266:        if (!MountVolume (BootDrive, exitKey))
        !           267:                return exitKey;
        !           268:        
        !           269:        InstallInterruptFilters();
        !           270: 
        !           271:        // Execute boot sector of the active partition
        !           272:        byte bootSector[TC_LB_SIZE];
        !           273:        if (ReadSectors (bootSector, partition.Drive, partition.StartSector, 1) == BiosResultSuccess)
        !           274:        {
        !           275:                ExecuteBootSector (partition.Drive, bootSector);
        !           276:        }
        !           277: 
        !           278: err:
        !           279:        byte scanCode;
        !           280:        GetKeyboardChar (&scanCode);
        !           281:        return scanCode;
        !           282: }
        !           283: 
        !           284: 
        !           285: static void BootMenu ()
        !           286: {
        !           287:        BiosResult result;
        !           288:        Partition partitions[16];
        !           289:        Partition bootablePartitions[9];
        !           290:        size_t partitionCount;
        !           291:        size_t bootablePartitionCount = 0;
        !           292: 
        !           293:        for (byte drive = TC_FIRST_BIOS_DRIVE; drive <= TC_LAST_BIOS_DRIVE; ++drive)
        !           294:        {
        !           295:                if (GetDrivePartitions (drive, partitions, array_capacity (partitions), partitionCount, false, true) == BiosResultSuccess)
        !           296:                {
        !           297:                        for (size_t i = 0; i < partitionCount; ++i)
        !           298:                        {
        !           299:                                const Partition &partition = partitions[i];
        !           300: 
        !           301:                                byte bootSector[TC_LB_SIZE];
        !           302:                                result = ReadSectors (bootSector, drive, partition.StartSector, 1);
        !           303: 
        !           304:                                if (result == BiosResultSuccess && *(uint16 *) (bootSector + TC_LB_SIZE - 2) == 0xaa55)
        !           305:                                {
        !           306:                                        // Windows writes boot loader on all NTFS/FAT filesytems it creates and, therefore,
        !           307:                                        // NTFS/FAT partitions must have the boot indicator set to be considered bootable.
        !           308:                                        if (!partition.Active
        !           309:                                                && (*(uint32 *) (bootSector + 3) == 0x5346544e  // 'NTFS'
        !           310:                                                        || *(uint16 *) (bootSector + 54) == 0x4146 && bootSector[56] == 'T' // 'FAT'
        !           311:                                                        || *(uint16 *) (bootSector + 82) == 0x4146 && bootSector[84] == 'T'))
        !           312:                                        {
        !           313:                                                continue;
        !           314:                                        }
        !           315: 
        !           316:                                        // Bootable sector found
        !           317:                                        if (bootablePartitionCount < array_capacity (bootablePartitions))
        !           318:                                                bootablePartitions[bootablePartitionCount++] = partition;
        !           319:                                }
        !           320:                        }
        !           321:                }
        !           322:        }
        !           323: 
        !           324:        if (bootablePartitionCount < 1)
        !           325:        {
        !           326:                PrintError ("No bootable partition found");
        !           327:                GetKeyboardChar();
        !           328:                return;
        !           329:        }
        !           330: 
        !           331:        char partChar;
        !           332:        while (true)
        !           333:        {
        !           334:                InitScreen();
        !           335:                Print ("Bootable Partitions:\r\n");
        !           336:                PrintRepeatedChar ('\xC4', 20);
        !           337:                Print ("\r\n");
        !           338: 
        !           339:                for (size_t i = 0; i < bootablePartitionCount; ++i)
        !           340:                {
        !           341:                        const Partition &partition = bootablePartitions[i];
        !           342:                        Print ("["); Print (i + 1); Print ("]    ");
        !           343:                        Print ("Drive: "); Print (partition.Drive - TC_FIRST_BIOS_DRIVE);
        !           344:                        Print (", Partition: "); Print (partition.Number + 1);
        !           345:                        Print (", Size: "); Print (partition.SectorCount >> 11); Print (" MB\r\n");
        !           346:                }
        !           347: 
        !           348:                if (bootablePartitionCount == 1)
        !           349:                {
        !           350:                        // There's only one bootable partition so we'll boot it directly instead of showing boot manager
        !           351:                        partChar = '1';
        !           352:                }
        !           353:                else
        !           354:                {
        !           355:                        Print ("[Esc]  Cancel\r\n\r\n");
        !           356:                        Print ("Press 1-9 to select partition: ");
        !           357: 
        !           358:                        if (GetString (&partChar, 1) == 0)
        !           359:                                return;
        !           360: 
        !           361:                        PrintEndl();
        !           362: 
        !           363:                        if (partChar < '1' || partChar > '0' + bootablePartitionCount)
        !           364:                        {
        !           365:                                Beep();
        !           366:                                continue;
        !           367:                        }
        !           368:                }
        !           369: 
        !           370:                const Partition &partition = bootablePartitions[partChar - '0' - 1];
        !           371: 
        !           372:                byte bootSector[TC_LB_SIZE];
        !           373:                if (ReadSectors (bootSector, partition.Drive, partition.StartSector, 1) == BiosResultSuccess)
        !           374:                {
        !           375:                        ExecuteBootSector (partition.Drive, bootSector);
        !           376:                }
        !           377:        }
        !           378: }
        !           379: 
        !           380: 
        !           381: static void DecryptDrive (byte drive)
        !           382: {
        !           383:        byte exitKey;
        !           384:        if (!MountVolume (drive, exitKey))
        !           385:                return;
        !           386: 
        !           387:        const int sectorsPerIoBlock = 0x7f; // Maximum safe value supported by BIOS
        !           388: 
        !           389:        bool headerUpdateRequired = false;
        !           390:        uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector;
        !           391:        uint64 sector = EncryptedVirtualPartition.EndSector + 1;
        !           392: 
        !           393:        byte sectorBuf[TC_LB_SIZE];
        !           394:        int fragmentSectorCount = sectorsPerIoBlock;
        !           395:        int statCount;
        !           396: 
        !           397:        if (EncryptedVirtualPartition.Drive == TC_FIRST_BIOS_DRIVE - 1)
        !           398:        {
        !           399:                // Drive not encrypted
        !           400:                sectorsRemaining.HighPart = 0;
        !           401:                sectorsRemaining.LowPart = 0;
        !           402:                headerUpdateRequired = true;
        !           403:        }
        !           404:        else
        !           405:        {
        !           406:                Print ("\r\nDo NOT turn off power. Press ESC to abort.\r\n");
        !           407:        }
        !           408: 
        !           409:        while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
        !           410:        {
        !           411:                if (IsKeyboardCharAvailable ())
        !           412:                {
        !           413:                        byte keyScanCode;
        !           414:                        GetKeyboardChar (&keyScanCode);
        !           415:                        if (keyScanCode == TC_BIOS_KEY_ESC)
        !           416:                                break;
        !           417:                }
        !           418: 
        !           419:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
        !           420:                        fragmentSectorCount = sectorsRemaining.LowPart;
        !           421: 
        !           422:                sector = sector - fragmentSectorCount;
        !           423: 
        !           424:                if (!(statCount++ & 0xf))
        !           425:                {
        !           426:                        Print ("\rRemaining: ");
        !           427:                        Print (sectorsRemaining >> 11); Print (" MB ");
        !           428:                }
        !           429: 
        !           430:                if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, false) != BiosResultSuccess)
        !           431:                        break;
        !           432: 
        !           433:                for (int i = 0; i < fragmentSectorCount; ++i)
        !           434:                {
        !           435:                        CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * sizeof (sectorBuf), sectorBuf, sizeof (sectorBuf));
        !           436: 
        !           437:                        uint64 s = sector + i;
        !           438:                        DecryptDataUnits (sectorBuf, &s, 1, BootCryptoInfo);
        !           439: 
        !           440:                        CopyMemory (sectorBuf, TC_BOOT_LOADER_BUFFER_SEGMENT, i * sizeof (sectorBuf), sizeof (sectorBuf));
        !           441:                } 
        !           442: 
        !           443:                if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, false) != BiosResultSuccess)
        !           444:                        break;
        !           445: 
        !           446:                sectorsRemaining = sectorsRemaining - fragmentSectorCount;
        !           447:                headerUpdateRequired = true;
        !           448:        }
        !           449: 
        !           450:        crypto_close (BootCryptoInfo);
        !           451:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
        !           452: 
        !           453:        if (headerUpdateRequired)
        !           454:        {
        !           455:                byte header[HEADER_SIZE];
        !           456:                uint64 headerSector;
        !           457:                headerSector.HighPart = 0;
        !           458:                headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
        !           459: 
        !           460:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
        !           461:                {
        !           462:                        memset (header, 0, sizeof (header));
        !           463:                        Print ("\rDrive decrypted.\r\n");
        !           464:                }
        !           465:                else
        !           466:                {
        !           467:                        // Update encrypted area size in volume header
        !           468: 
        !           469:                        CRYPTO_INFO *headerCryptoInfo = crypto_open();
        !           470:                        ReadSectors (header, drive, headerSector, 1);
        !           471: 
        !           472:                        if (VolumeReadHeader (TRUE, (char *) header, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0)
        !           473:                        {
        !           474:                                DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
        !           475: 
        !           476:                                byte *sizeField = header + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
        !           477:                                uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
        !           478: 
        !           479:                                for (int i = 7; i >= 0; --i)
        !           480:                                {
        !           481:                                        sizeField[i] = (byte) encryptedAreaLength.LowPart;
        !           482:                                        encryptedAreaLength = encryptedAreaLength >> 8;
        !           483:                                }
        !           484:                                
        !           485:                                EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
        !           486:                        }
        !           487: 
        !           488:                        crypto_close (headerCryptoInfo);
        !           489:                        Print ("\r\nAborted.\r\n");
        !           490:                }
        !           491: 
        !           492:                WriteSectors (header, drive, headerSector, 1);
        !           493:        }
        !           494: 
        !           495: err:
        !           496:        memset (bootArguments, 0, sizeof (*bootArguments));
        !           497:        GetKeyboardChar();
        !           498: }
        !           499: 
        !           500: 
        !           501: static void RepairMenu ()
        !           502: {
        !           503:        DriveGeometry bootLoaderDriveGeometry;
        !           504:        if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry) != BiosResultSuccess)
        !           505:        {
        !           506:                GetKeyboardChar();
        !           507:                return;
        !           508:        }
        !           509: 
        !           510:        while (true)
        !           511:        {
        !           512:                InitScreen();
        !           513:                Print ("Available "); Print ("Repair Options"); Print (":\r\n");
        !           514:                PrintRepeatedChar ('\xC4', 25);
        !           515:                Print ("\r\n");
        !           516: 
        !           517:                enum
        !           518:                {
        !           519:                        RestoreNone = 0,
        !           520:                        DecryptVolume,
        !           521:                        RestoreTrueCryptLoader,
        !           522:                        RestoreVolumeHeader,
        !           523:                        RestoreOriginalSystemLoader
        !           524:                };
        !           525: 
        !           526:                static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" };
        !           527: 
        !           528:                int optionCount = 1;
        !           529:                if (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER)
        !           530:                        optionCount = array_capacity (options);
        !           531:                else if (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK)
        !           532:                        optionCount = array_capacity (options) - 1;
        !           533: 
        !           534:                int selection = AskSelection (options, optionCount);
        !           535:                PrintEndl();
        !           536: 
        !           537:                if (selection == RestoreNone)
        !           538:                        return;
        !           539: 
        !           540:                if (selection == DecryptVolume)
        !           541:                {
        !           542:                        DecryptDrive (BootDrive);
        !           543:                        continue;
        !           544:                }
        !           545: 
        !           546:                bool writeConfirmed = false;
        !           547:                BiosResult result;
        !           548:                byte sectorBuf[TC_LB_SIZE];
        !           549: 
        !           550:                uint64 sector;
        !           551:                sector.HighPart = 0;
        !           552:                ChsAddress chs;
        !           553: 
        !           554:                for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR);
        !           555:                        i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i)
        !           556:                {
        !           557:                        sector.LowPart = (selection == RestoreOriginalSystemLoader ? TC_ORIG_BOOT_LOADER_BACKUP_SECTOR : 0) + i;
        !           558: 
        !           559:                        // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used.
        !           560:                        // Therefore, only CHS addressing can be used.
        !           561:                        LbaToChs (bootLoaderDriveGeometry, sector, chs);
        !           562: 
        !           563:                        result = ReadSectors (sectorBuf, BootLoaderDrive, chs, 1);
        !           564:                        if (result != BiosResultSuccess)
        !           565:                                goto err;
        !           566: 
        !           567:                        sector.LowPart = i;
        !           568: 
        !           569:                        // MBR
        !           570:                        if (i == TC_MBR_SECTOR)
        !           571:                        {
        !           572:                                // Preserve partition table
        !           573:                                byte bootSecBuf[TC_LB_SIZE];
        !           574: 
        !           575:                                result = ReadSectors (bootSecBuf, TC_FIRST_BIOS_DRIVE, sector, 1);
        !           576:                                if (result != BiosResultSuccess)
        !           577:                                        goto err;
        !           578: 
        !           579:                                memcpy (sectorBuf + TC_MAX_MBR_BOOT_CODE_SIZE,
        !           580:                                        bootSecBuf + TC_MAX_MBR_BOOT_CODE_SIZE,
        !           581:                                        sizeof (bootSecBuf) - TC_MAX_MBR_BOOT_CODE_SIZE);
        !           582: 
        !           583:                                // Clear rescue disk flags
        !           584:                                if (selection == RestoreTrueCryptLoader)
        !           585:                                        sectorBuf[TC_BOOT_SECTOR_CONFIG_OFFSET] &= ~(TC_BOOT_CFG_FLAG_RESCUE_DISK | TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER);
        !           586:                        }
        !           587: 
        !           588:                        // Volume header
        !           589:                        if (i == TC_BOOT_VOLUME_HEADER_SECTOR)
        !           590:                        {
        !           591:                                if (selection == RestoreTrueCryptLoader)
        !           592:                                        continue;
        !           593: 
        !           594:                                if (selection == RestoreVolumeHeader)
        !           595:                                {
        !           596:                                        while (true)
        !           597:                                        {
        !           598:                                                Password password;
        !           599:                                                byte exitKey = AskPassword (password);
        !           600: 
        !           601:                                                if (exitKey != TC_BIOS_KEY_ENTER)
        !           602:                                                        goto abort;
        !           603: 
        !           604:                                                CRYPTO_INFO *cryptoInfo;
        !           605: 
        !           606:                                                // Restore volume header only if the current one cannot be used
        !           607:                                                if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo))
        !           608:                                                {
        !           609:                                                        Print ("Original header preserved.\r\n");
        !           610:                                                        crypto_close (cryptoInfo);
        !           611:                                                        goto err;
        !           612:                                                }
        !           613: 
        !           614:                                                if (VolumeReadHeader (TRUE, (char *) sectorBuf, &password, &cryptoInfo, nullptr) == 0)
        !           615:                                                {
        !           616:                                                        crypto_close (cryptoInfo);
        !           617:                                                        break;
        !           618:                                                }
        !           619: 
        !           620:                                                Print ("Incorrect password or not a TrueCrypt volume.\r\n\r\n");
        !           621:                                        }
        !           622:                                }
        !           623:                        }
        !           624: 
        !           625:                        if (!writeConfirmed && !AskYesNo ("Modify Drive 0"))
        !           626:                                goto abort;
        !           627:                        writeConfirmed = true;
        !           628: 
        !           629:                        if (WriteSectors (sectorBuf, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess)
        !           630:                                goto err;
        !           631:                }
        !           632: done:
        !           633:                switch (selection)
        !           634:                {
        !           635:                case RestoreTrueCryptLoader:
        !           636:                        Print ("TrueCrypt Boot Loader");
        !           637:                        break;
        !           638: 
        !           639:                case RestoreVolumeHeader:
        !           640:                        Print ("Header");
        !           641:                        break;
        !           642: 
        !           643:                case RestoreOriginalSystemLoader:
        !           644:                        Print ("System loader");
        !           645:                        break;
        !           646:                }
        !           647:                Print (" restored.\r\n");
        !           648: 
        !           649: err:   GetKeyboardChar();
        !           650: abort: ;
        !           651:        }
        !           652: }
        !           653: 
        !           654: 
        !           655: #ifndef DEBUG
        !           656: extern "C" void _acrtused () { }  // Required by linker
        !           657: #endif
        !           658: 
        !           659: 
        !           660: void main ()
        !           661: {
        !           662:        __asm mov BootLoaderDrive, dl
        !           663:        __asm mov BootSectorFlags, dh
        !           664: 
        !           665: #ifdef TC_TRACING_ENABLED
        !           666:        InitDebugPort();
        !           667: #endif
        !           668: 
        !           669:        BootDrive = BootLoaderDrive;
        !           670:        if (BootDrive < TC_FIRST_BIOS_DRIVE)
        !           671:                BootDrive = TC_FIRST_BIOS_DRIVE;
        !           672: 
        !           673:        if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess)
        !           674:        {
        !           675:                BootDrive = TC_FIRST_BIOS_DRIVE;
        !           676:                if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess)
        !           677:                        BootDriveGeometryValid = TRUE;
        !           678:        }
        !           679:        else
        !           680:                BootDriveGeometryValid = TRUE;
        !           681: 
        !           682:        while (true)
        !           683:        {
        !           684:                InitScreen();
        !           685:                PrintMainMenu();
        !           686: 
        !           687:                byte exitKey = BootEncryptedDrive();
        !           688:                
        !           689:                if (exitKey == TC_MENU_KEY_REPAIR)
        !           690:                {
        !           691:                        RepairMenu();
        !           692:                        continue;
        !           693:                }
        !           694: 
        !           695:                BootMenu();
        !           696:        }
        !           697: }

unix.superglobalmegacorp.com

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