Annotation of truecrypt/boot/windows/bootmain.cpp, revision 1.1.1.9

1.1       root        1: /*
1.1.1.8   root        2:  Copyright (c) 2008-2009 TrueCrypt Foundation. All rights reserved.
1.1       root        3: 
1.1.1.9 ! root        4:  Governed by the TrueCrypt License 2.7 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 "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"
1.1.1.2   root       24: #include "BootMemory.h"
1.1.1.6   root       25: #include "BootStrings.h"
1.1       root       26: #include "IntFilter.h"
                     27: 
                     28: 
                     29: static void InitScreen ()
                     30: {
                     31:        ClearScreen();
                     32: 
1.1.1.8   root       33:        const char *title =
1.1.1.5   root       34: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                     35:                " TrueCrypt Boot Loader "
                     36: #else
                     37:                " TrueCrypt Rescue Disk "
                     38: #endif
1.1.1.8   root       39:                VERSION_STRING;
                     40: 
                     41:        Print (title);
                     42:        PrintRepeatedChar (' ', title[26] ? 8 : 9);
                     43:        Print ("Copyright (C) 2008-2009 TrueCrypt Foundation\r\n");
1.1       root       44: 
1.1.1.5   root       45:        PrintRepeatedChar ('\xDC', TC_BIOS_MAX_CHARS_PER_LINE);
1.1.1.6   root       46: 
                     47: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                     48:        if (CustomUserMessage[0])
                     49:        {
                     50:                PrintEndl();
                     51:                Print (CustomUserMessage);
                     52:        }
                     53: #endif
                     54: 
1.1       root       55:        PrintEndl (2);
                     56: }
                     57: 
                     58: 
                     59: static void PrintMainMenu ()
                     60: {
1.1.1.6   root       61:        if (PreventBootMenu)
                     62:                return;
                     63: 
1.1       root       64:        Print ("    Keyboard Controls:\r\n");
1.1.1.5   root       65:        Print ("    [Esc]  ");
                     66: 
                     67: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                     68: 
1.1.1.6   root       69:        Print ((BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE
                     70:                ? "Boot Non-Hidden System (Boot Manager)"
1.1.1.5   root       71:                : "Skip Authentication (Boot Manager)");
                     72:        
                     73: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                     74: 
                     75:        Print ("Skip Authentication (Boot Manager)");
                     76:        Print ("\r\n    [F8]   "); Print ("Repair Options");
                     77: 
                     78: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
1.1       root       79: 
                     80:        PrintEndl (3);
                     81: }
                     82: 
                     83: 
                     84: static bool IsMenuKey (byte scanCode)
                     85: {
1.1.1.5   root       86: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
1.1       root       87:        return scanCode == TC_MENU_KEY_REPAIR;
1.1.1.5   root       88: #else
                     89:        return false;
                     90: #endif
1.1       root       91: }
                     92: 
                     93: 
                     94: static bool AskYesNo (const char *message)
                     95: {
                     96:        Print (message);
                     97:        Print ("? (y/n): ");
                     98:        while (true)
                     99:        {
                    100:                switch (GetKeyboardChar())
                    101:                {
                    102:                case 'y':
                    103:                case 'Y':
1.1.1.3   root      104:                case 'z':
1.1.1.6   root      105:                case 'Z':
                    106:                        Print ("y\r\n");
1.1       root      107:                        return true;
                    108: 
                    109:                case 'n':
                    110:                case 'N':
1.1.1.6   root      111:                        Print ("n\r\n");
1.1       root      112:                        return false;
                    113: 
                    114:                default:
                    115:                        Beep();
                    116:                }
                    117:        }
                    118: }
                    119: 
                    120: 
                    121: static int AskSelection (const char *options[], size_t optionCount)
                    122: {
                    123:        for (int i = 0; i < optionCount; ++i)
                    124:        {
                    125:                Print ("["); Print (i + 1); Print ("]    ");
                    126:                Print (options[i]);
                    127:                PrintEndl();
                    128:        }
                    129:        Print ("[Esc]  Cancel\r\n\r\n");
                    130: 
                    131:        Print ("To select, press 1-9: ");
                    132: 
                    133:        char str;
                    134: 
                    135:        while (true)
                    136:        {
                    137:                if (GetString (&str, 1) == 0)
                    138:                        return 0;
                    139: 
                    140:                if (str >= '1' && str <= optionCount + '0')
                    141:                        return str - '0';
                    142: 
                    143:                Beep();
                    144:                PrintBackspace();
                    145:        }
                    146: }
                    147: 
                    148: 
1.1.1.6   root      149: static byte AskPassword (Password &password)
1.1       root      150: {
                    151:        size_t pos = 0;
                    152:        byte scanCode;
                    153:        byte asciiCode;
                    154: 
1.1.1.5   root      155:        Print ("Enter password");
1.1.1.6   root      156:        Print (PreventNormalSystemBoot ? " for hidden system:\r\n" : ": ");
1.1       root      157: 
                    158:        while (true)
                    159:        {
                    160:                asciiCode = GetKeyboardChar (&scanCode);
                    161: 
                    162:                switch (scanCode)
                    163:                {
                    164:                case TC_BIOS_KEY_ENTER:
1.1.1.2   root      165:                        ClearBiosKeystrokeBuffer();
1.1       root      166:                        PrintEndl();
1.1.1.2   root      167: 
                    168:                        password.Length = pos;
                    169:                        return scanCode;
1.1       root      170: 
                    171:                case TC_BIOS_KEY_BACKSPACE:
                    172:                        if (pos > 0)
                    173:                        {
                    174:                                if (pos < MAX_PASSWORD)
                    175:                                        PrintBackspace();
                    176:                                else
1.1.1.6   root      177:                                        PrintCharAtCursor (' ');
1.1       root      178: 
                    179:                                --pos;
                    180:                        }
                    181:                        continue;
                    182: 
                    183:                default:
                    184:                        if (scanCode == TC_BIOS_KEY_ESC || IsMenuKey (scanCode))
                    185:                        {
                    186:                                burn (password.Text, sizeof (password.Text));
1.1.1.2   root      187:                                ClearBiosKeystrokeBuffer();
                    188: 
1.1       root      189:                                PrintEndl();
                    190:                                return scanCode;
                    191:                        }
                    192:                }
                    193: 
                    194:                if (!IsPrintable (asciiCode) || pos == MAX_PASSWORD)
                    195:                {
                    196:                        Beep();
                    197:                        continue;
                    198:                }
                    199: 
                    200:                password.Text[pos++] = asciiCode;
                    201:                if (pos < MAX_PASSWORD)
                    202:                        PrintChar ('*');
                    203:                else
1.1.1.6   root      204:                        PrintCharAtCursor ('*');
1.1       root      205:        }
                    206: }
                    207: 
                    208: 
                    209: static void ExecuteBootSector (byte drive, byte *sectorBuffer)
                    210: {
                    211:        Print ("Booting...\r\n");
                    212:        CopyMemory (sectorBuffer, 0x0000, 0x7c00, TC_LB_SIZE);
1.1.1.3   root      213: 
1.1.1.6   root      214:        BootStarted = true;
                    215: 
1.1.1.3   root      216:        uint32 addr = 0x7c00;
                    217:        __asm
                    218:        {
                    219:                cli
1.1.1.8   root      220:                mov dl, drive   // Boot drive
                    221:                mov dh, 0
1.1.1.3   root      222:                xor ax, ax
1.1.1.8   root      223:                mov si, ax
1.1.1.3   root      224:                mov ds, ax
                    225:                mov es, ax
                    226:                mov ss, ax
1.1.1.8   root      227:                mov sp, 0x7c00
1.1.1.3   root      228:                sti
1.1.1.8   root      229: 
1.1.1.3   root      230:                jmp cs:addr
                    231:        }
1.1       root      232: }
                    233: 
                    234: 
1.1.1.6   root      235: static bool OpenVolume (byte drive, Password &password, CRYPTO_INFO **cryptoInfo, uint32 *headerSaltCrc32, bool skipNormal, bool skipHidden)
1.1       root      236: {
1.1.1.6   root      237:        int volumeType;
                    238:        bool hiddenVolume;
1.1       root      239:        uint64 headerSec;
1.1.1.5   root      240:        
1.1.1.3   root      241:        AcquireSectorBuffer();
1.1       root      242: 
1.1.1.6   root      243:        for (volumeType = 1; volumeType <= 2; ++volumeType)
1.1       root      244:        {
1.1.1.6   root      245:                hiddenVolume = (volumeType == 2);
1.1.1.5   root      246: 
1.1.1.6   root      247:                if (hiddenVolume)
                    248:                {
                    249:                        if (skipHidden || PartitionFollowingActive.Drive != drive || PartitionFollowingActive.SectorCount <= ActivePartition.SectorCount)
                    250:                                continue;
1.1.1.5   root      251: 
1.1.1.6   root      252:                        headerSec = PartitionFollowingActive.StartSector + TC_HIDDEN_VOLUME_HEADER_OFFSET / TC_LB_SIZE;
                    253:                }
                    254:                else
1.1.1.5   root      255:                {
1.1.1.6   root      256:                        if (skipNormal)
                    257:                                continue;
                    258: 
                    259:                        headerSec.HighPart = 0;
                    260:                        headerSec.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
1.1.1.5   root      261:                }
                    262: 
1.1.1.6   root      263:                if (ReadSectors (SectorBuffer, drive, headerSec, 1) != BiosResultSuccess)
                    264:                        continue;
                    265: 
                    266:                if (ReadVolumeHeader (!hiddenVolume, (char *) SectorBuffer, &password, cryptoInfo, nullptr) == ERR_SUCCESS)
1.1.1.5   root      267:                {
1.1.1.6   root      268:                        // Prevent opening a non-system hidden volume
                    269:                        if (hiddenVolume && !((*cryptoInfo)->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM))
                    270:                        {
                    271:                                crypto_close (*cryptoInfo);
                    272:                                continue;
                    273:                        }
                    274: 
                    275:                        if (headerSaltCrc32)
                    276:                                *headerSaltCrc32 = GetCrc32 (SectorBuffer, PKCS5_SALT_SIZE);
1.1.1.5   root      277: 
1.1.1.6   root      278:                        break;
                    279:                }
1.1       root      280:        }
                    281: 
1.1.1.3   root      282:        ReleaseSectorBuffer();
1.1.1.6   root      283:        return volumeType != 3;
1.1       root      284: }
                    285: 
                    286: 
1.1.1.2   root      287: static bool CheckMemoryRequirements ()
                    288: {
                    289:        uint16 codeSeg;
                    290:        __asm mov codeSeg, cs
                    291:        if (codeSeg == TC_BOOT_LOADER_LOWMEM_SEGMENT)
                    292:        {
1.1.1.6   root      293:                PrintError ("BIOS reserved too much memory: ", true, false);
1.1.1.2   root      294: 
                    295:                uint16 memFree;
                    296:                __asm
                    297:                {
                    298:                        push es
                    299:                        xor ax, ax
                    300:                        mov es, ax
                    301:                        mov ax, es:[0x413]
                    302:                        mov memFree, ax
                    303:                        pop es
                    304:                }
                    305: 
1.1.1.6   root      306:                Print (memFree);
1.1.1.8   root      307:                PrintEndl();
1.1.1.6   root      308:                Print (TC_BOOT_STR_UPGRADE_BIOS);
1.1.1.5   root      309: 
1.1.1.2   root      310:                return false;
                    311:        }
                    312: 
                    313:        return true;
                    314: }
                    315: 
                    316: 
1.1.1.5   root      317: static bool MountVolume (byte drive, byte &exitKey, bool skipNormal, bool skipHidden)
1.1       root      318: {
                    319:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
1.1.1.3   root      320:        int incorrectPasswordCount = 0;
1.1       root      321: 
1.1.1.5   root      322:        EraseMemory (bootArguments, sizeof (*bootArguments));
                    323: 
1.1       root      324:        // Open volume header
                    325:        while (true)
                    326:        {
1.1.1.6   root      327:                exitKey = AskPassword (bootArguments->BootPassword);
1.1       root      328: 
                    329:                if (exitKey != TC_BIOS_KEY_ENTER)
                    330:                        return false;
                    331: 
1.1.1.5   root      332:                if (OpenVolume (BootDrive, bootArguments->BootPassword, &BootCryptoInfo, &bootArguments->HeaderSaltCrc32, skipNormal, skipHidden))
1.1       root      333:                        break;
                    334: 
1.1.1.5   root      335:                if (GetShiftFlags() & TC_BIOS_SHIFTMASK_CAPSLOCK)
                    336:                        Print ("Warning: Caps Lock is on.\r\n");
                    337: 
1.1.1.4   root      338:                Print ("Incorrect password.\r\n\r\n");
1.1.1.3   root      339: 
1.1.1.6   root      340:                if (++incorrectPasswordCount == 4)
1.1.1.3   root      341:                {
1.1.1.6   root      342: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                    343:                        Print ("The key data may be damaged. Use 'Repair Options' > 'Restore key data'.\r\n\r\n");
                    344: #else
1.1.1.3   root      345:                        Print ("If you are sure the password is correct, the key data may be damaged. Boot your\r\n"
                    346:                                   "TrueCrypt Rescue Disk and select 'Repair Options' > 'Restore key data'.\r\n\r\n");
1.1.1.6   root      347: #endif
1.1.1.3   root      348:                }
1.1       root      349:        }
                    350: 
                    351:        // Setup boot arguments
1.1.1.5   root      352:        bootArguments->BootLoaderVersion = VERSION_NUM;
1.1       root      353:        bootArguments->CryptoInfoOffset = (uint16) BootCryptoInfo;
                    354:        bootArguments->CryptoInfoLength = sizeof (*BootCryptoInfo);
1.1.1.5   root      355:        
                    356:        if (BootCryptoInfo->hiddenVolume)
                    357:                bootArguments->HiddenSystemPartitionStart = PartitionFollowingActive.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
                    358: 
1.1       root      359:        TC_SET_BOOT_ARGUMENTS_SIGNATURE (bootArguments->Signature);
                    360: 
1.1.1.5   root      361:        // Setup virtual encrypted partition
1.1       root      362:        if (BootCryptoInfo->EncryptedAreaLength.HighPart != 0 || BootCryptoInfo->EncryptedAreaLength.LowPart != 0)
                    363:        {
                    364:                EncryptedVirtualPartition.Drive = BootDrive;
                    365: 
1.1.1.5   root      366:                EncryptedVirtualPartition.StartSector = BootCryptoInfo->EncryptedAreaStart >> TC_LB_SIZE_BIT_SHIFT_DIVISOR;
                    367:                
                    368:                HiddenVolumeStartUnitNo = EncryptedVirtualPartition.StartSector;
                    369:                HiddenVolumeStartSector = PartitionFollowingActive.StartSector;
                    370:                HiddenVolumeStartSector += EncryptedVirtualPartition.StartSector;
                    371: 
                    372:                EncryptedVirtualPartition.SectorCount = BootCryptoInfo->EncryptedAreaLength >> TC_LB_SIZE_BIT_SHIFT_DIVISOR;
                    373: 
                    374:                EncryptedVirtualPartition.EndSector = EncryptedVirtualPartition.SectorCount - 1;
                    375:                EncryptedVirtualPartition.EndSector += EncryptedVirtualPartition.StartSector;
1.1       root      376:        }
                    377:        else
                    378:        {
                    379:                // Drive not encrypted
1.1.1.5   root      380:                EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE;
1.1       root      381:        }
                    382: 
                    383:        return true;
                    384: }
                    385: 
                    386: 
                    387: static byte BootEncryptedDrive ()
                    388: {
1.1.1.5   root      389:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
1.1.1.6   root      390:        byte exitKey;
                    391:        BootCryptoInfo = NULL;
1.1       root      392: 
1.1.1.5   root      393:        if (!GetActiveAndFollowingPartition (BootDrive))
1.1       root      394:                goto err;
                    395: 
1.1.1.6   root      396:        if (!MountVolume (BootDrive, exitKey, PreventNormalSystemBoot, false))
1.1       root      397:                return exitKey;
                    398:        
1.1.1.2   root      399:        if (!CheckMemoryRequirements ())
                    400:                goto err;
1.1.1.5   root      401: 
                    402:        if (BootCryptoInfo->hiddenVolume)
                    403:        {
                    404:                EncryptedVirtualPartition = ActivePartition;
                    405:                bootArguments->DecoySystemPartitionStart = ActivePartition.StartSector << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
1.1.1.2   root      406:        }
                    407: 
                    408:        if (!InstallInterruptFilters())
                    409:                goto err;
1.1       root      410: 
1.1.1.5   root      411:        bootArguments->BootArgumentsCrc32 = GetCrc32 ((byte *) bootArguments, (byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments);
                    412: 
1.1.1.3   root      413:        while (true)
1.1       root      414:        {
1.1.1.3   root      415:                // Execute boot sector of the active partition
1.1.1.5   root      416:                if (ReadSectors (SectorBuffer, ActivePartition.Drive, ActivePartition.StartSector, 1) == BiosResultSuccess)
1.1.1.3   root      417:                {
1.1.1.6   root      418:                        if (*(uint16 *) (SectorBuffer + 510) != 0xaa55)
                    419:                        {
                    420:                                PrintError (TC_BOOT_STR_NO_BOOT_PARTITION);
                    421:                                GetKeyboardChar();
                    422:                        }
                    423: 
1.1.1.5   root      424:                        ExecuteBootSector (ActivePartition.Drive, SectorBuffer);
1.1.1.3   root      425:                }
                    426: 
                    427:                GetKeyboardChar();
1.1       root      428:        }
                    429: 
                    430: err:
1.1.1.3   root      431:        if (BootCryptoInfo)
                    432:        {
                    433:                crypto_close (BootCryptoInfo);
                    434:                BootCryptoInfo = NULL;
                    435:        }
                    436: 
1.1.1.5   root      437:        EncryptedVirtualPartition.Drive = TC_INVALID_BIOS_DRIVE;
                    438:        EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments));
1.1.1.2   root      439: 
1.1       root      440:        byte scanCode;
                    441:        GetKeyboardChar (&scanCode);
                    442:        return scanCode;
                    443: }
                    444: 
                    445: 
                    446: static void BootMenu ()
                    447: {
                    448:        BiosResult result;
                    449:        Partition partitions[16];
                    450:        Partition bootablePartitions[9];
                    451:        size_t partitionCount;
                    452:        size_t bootablePartitionCount = 0;
                    453: 
                    454:        for (byte drive = TC_FIRST_BIOS_DRIVE; drive <= TC_LAST_BIOS_DRIVE; ++drive)
                    455:        {
1.1.1.5   root      456:                if (GetDrivePartitions (drive, partitions, array_capacity (partitions), partitionCount, false, nullptr, true) == BiosResultSuccess)
1.1       root      457:                {
                    458:                        for (size_t i = 0; i < partitionCount; ++i)
                    459:                        {
                    460:                                const Partition &partition = partitions[i];
1.1.1.3   root      461:                                result = ReadSectors (SectorBuffer, drive, partition.StartSector, 1);
1.1       root      462: 
1.1.1.3   root      463:                                if (result == BiosResultSuccess && *(uint16 *) (SectorBuffer + TC_LB_SIZE - 2) == 0xaa55)
1.1       root      464:                                {
                    465:                                        // Windows writes boot loader on all NTFS/FAT filesytems it creates and, therefore,
                    466:                                        // NTFS/FAT partitions must have the boot indicator set to be considered bootable.
                    467:                                        if (!partition.Active
1.1.1.3   root      468:                                                && (*(uint32 *) (SectorBuffer + 3) == 0x5346544e  // 'NTFS'
1.1.1.8   root      469:                                                        || *(uint32 *) (SectorBuffer + 3) == 0x41465845 && SectorBuffer[7] == 'T' // 'exFAT'
1.1.1.3   root      470:                                                        || *(uint16 *) (SectorBuffer + 54) == 0x4146 && SectorBuffer[56] == 'T' // 'FAT'
                    471:                                                        || *(uint16 *) (SectorBuffer + 82) == 0x4146 && SectorBuffer[84] == 'T'))
1.1       root      472:                                        {
                    473:                                                continue;
                    474:                                        }
                    475: 
                    476:                                        // Bootable sector found
                    477:                                        if (bootablePartitionCount < array_capacity (bootablePartitions))
                    478:                                                bootablePartitions[bootablePartitionCount++] = partition;
                    479:                                }
                    480:                        }
                    481:                }
                    482:        }
                    483: 
                    484:        if (bootablePartitionCount < 1)
                    485:        {
1.1.1.6   root      486:                PrintError (TC_BOOT_STR_NO_BOOT_PARTITION);
1.1       root      487:                GetKeyboardChar();
                    488:                return;
                    489:        }
                    490: 
                    491:        char partChar;
                    492:        while (true)
                    493:        {
                    494:                InitScreen();
                    495:                Print ("Bootable Partitions:\r\n");
                    496:                PrintRepeatedChar ('\xC4', 20);
                    497:                Print ("\r\n");
                    498: 
                    499:                for (size_t i = 0; i < bootablePartitionCount; ++i)
                    500:                {
                    501:                        const Partition &partition = bootablePartitions[i];
                    502:                        Print ("["); Print (i + 1); Print ("]    ");
                    503:                        Print ("Drive: "); Print (partition.Drive - TC_FIRST_BIOS_DRIVE);
                    504:                        Print (", Partition: "); Print (partition.Number + 1);
1.1.1.5   root      505:                        Print (", Size: "); PrintSectorCountInMB (partition.SectorCount); PrintEndl();
1.1       root      506:                }
                    507: 
                    508:                if (bootablePartitionCount == 1)
                    509:                {
                    510:                        // There's only one bootable partition so we'll boot it directly instead of showing boot manager
                    511:                        partChar = '1';
                    512:                }
                    513:                else
                    514:                {
                    515:                        Print ("[Esc]  Cancel\r\n\r\n");
                    516:                        Print ("Press 1-9 to select partition: ");
                    517: 
                    518:                        if (GetString (&partChar, 1) == 0)
                    519:                                return;
                    520: 
                    521:                        PrintEndl();
                    522: 
                    523:                        if (partChar < '1' || partChar > '0' + bootablePartitionCount)
                    524:                        {
                    525:                                Beep();
                    526:                                continue;
                    527:                        }
                    528:                }
                    529: 
                    530:                const Partition &partition = bootablePartitions[partChar - '0' - 1];
                    531: 
1.1.1.3   root      532:                if (ReadSectors (SectorBuffer, partition.Drive, partition.StartSector, 1) == BiosResultSuccess)
1.1       root      533:                {
1.1.1.3   root      534:                        ExecuteBootSector (partition.Drive, SectorBuffer);
1.1       root      535:                }
                    536:        }
                    537: }
                    538: 
                    539: 
1.1.1.5   root      540: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                    541: 
                    542: static bool CopyActivePartitionToHiddenVolume (byte drive, byte &exitKey)
                    543: {
                    544:        bool status = false;
                    545: 
                    546:        uint64 sectorsRemaining;
                    547:        uint64 sectorOffset;
                    548:        sectorOffset.LowPart = 0;
                    549:        sectorOffset.HighPart = 0;
                    550: 
                    551:        int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS
                    552:        int statCount;
                    553: 
                    554:        if (!CheckMemoryRequirements ())
                    555:                goto err;
                    556: 
                    557:        if (!GetActiveAndFollowingPartition (drive))
                    558:                goto err;
                    559: 
                    560:        if (PartitionFollowingActive.Drive == TC_INVALID_BIOS_DRIVE)
1.1.1.6   root      561:                TC_THROW_FATAL_EXCEPTION;
                    562: 
                    563:        // Check if BIOS can read the last sector of the hidden system
                    564:        AcquireSectorBuffer();
                    565: 
                    566:        if (ReadSectors (SectorBuffer, PartitionFollowingActive.Drive, PartitionFollowingActive.EndSector - (TC_VOLUME_HEADER_GROUP_SIZE / TC_LB_SIZE - 2), 1) != BiosResultSuccess
1.1.1.8   root      567:                || GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc)
1.1.1.5   root      568:        {
1.1.1.8   root      569:                if (!IsLbaSupported (PartitionFollowingActive.Drive))
                    570:                        Print ("BIOS: LBA N/A\r\n");
                    571: 
1.1.1.6   root      572:                PrintError ("Your BIOS does not support large drives");
                    573:                Print (TC_BOOT_STR_UPGRADE_BIOS);
                    574: 
                    575:                ReleaseSectorBuffer();
1.1.1.5   root      576:                goto err;
                    577:        }
                    578: 
1.1.1.6   root      579:        ReleaseSectorBuffer();
                    580: 
1.1.1.5   root      581:        if (!MountVolume (drive, exitKey, true, false))
                    582:                return false;
                    583: 
                    584:        sectorsRemaining = EncryptedVirtualPartition.SectorCount;
                    585: 
                    586:        if (!(sectorsRemaining == ActivePartition.SectorCount))
1.1.1.7   root      587:                TC_THROW_FATAL_EXCEPTION;
1.1.1.5   root      588: 
                    589:        InitScreen();
                    590:        Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n");
                    591: 
                    592:        while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
                    593:        {
                    594:                if (EscKeyPressed())
                    595:                {
                    596:                        Print ("\rIf aborted, copying will have to start from the beginning (if attempted again).\r\n");
                    597:                        if (AskYesNo ("Abort"))
                    598:                                break;
                    599:                }
                    600: 
                    601:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
                    602:                        fragmentSectorCount = sectorsRemaining.LowPart;
                    603: 
                    604:                if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess)
1.1.1.7   root      605:                {
                    606:                        Print ("To fix bad sectors: 1) Terminate 2) Encrypt and decrypt sys partition 3) Retry\r\n");
                    607:                        crypto_close (BootCryptoInfo);
                    608:                        goto err;
                    609:                }
1.1.1.5   root      610: 
                    611:                AcquireSectorBuffer();
                    612: 
                    613:                for (int i = 0; i < fragmentSectorCount; ++i)
                    614:                {
                    615:                        CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE);
                    616: 
                    617:                        uint64 s = HiddenVolumeStartUnitNo + sectorOffset + i;
                    618:                        EncryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo);
                    619: 
                    620:                        CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE);
                    621:                } 
                    622: 
                    623:                ReleaseSectorBuffer();
                    624: 
                    625:                if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, HiddenVolumeStartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess)
1.1.1.7   root      626:                {
                    627:                        crypto_close (BootCryptoInfo);
                    628:                        goto err;
                    629:                }
1.1.1.5   root      630: 
                    631:                sectorsRemaining = sectorsRemaining - fragmentSectorCount;
                    632:                sectorOffset = sectorOffset + fragmentSectorCount;
                    633: 
                    634:                if (!(statCount++ & 0xf))
                    635:                {
                    636:                        Print ("\rRemaining: ");
                    637:                        PrintSectorCountInMB (sectorsRemaining);
                    638:                }
                    639:        }
                    640: 
                    641:        crypto_close (BootCryptoInfo);
                    642: 
                    643:        if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
                    644:        {
                    645:                status = true;
                    646:                Print ("\rCopying completed.");
                    647:        }
                    648: 
                    649:        PrintEndl (2);
                    650:        goto ret;
                    651: 
                    652: err:
                    653:        exitKey = TC_BIOS_KEY_ESC;
                    654:        GetKeyboardChar();
                    655: 
                    656: ret:
                    657:        EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments));
                    658:        return status;
                    659: }
                    660: 
                    661: 
                    662: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                    663: 
                    664: 
1.1       root      665: static void DecryptDrive (byte drive)
                    666: {
                    667:        byte exitKey;
1.1.1.5   root      668:        if (!MountVolume (drive, exitKey, false, true))
1.1       root      669:                return;
                    670: 
1.1.1.5   root      671:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
1.1       root      672: 
                    673:        bool headerUpdateRequired = false;
                    674:        uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector;
                    675:        uint64 sector = EncryptedVirtualPartition.EndSector + 1;
                    676: 
1.1.1.5   root      677:        int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS
1.1       root      678:        int statCount;
                    679: 
1.1.1.5   root      680:        bool skipBadSectors = false;
                    681: 
1.1.1.6   root      682:        Print ("\r\nUse only if Windows cannot start. Decryption under Windows is much faster\r\n"
                    683:                        "(in TrueCrypt, select 'System' > 'Permanently Decrypt').\r\n\r\n");
1.1.1.5   root      684: 
                    685:        if (!AskYesNo ("Decrypt now"))
                    686:        {
                    687:                crypto_close (BootCryptoInfo);
                    688:                goto ret;
                    689:        }
                    690: 
                    691:        if (EncryptedVirtualPartition.Drive == TC_INVALID_BIOS_DRIVE)
1.1       root      692:        {
1.1.1.3   root      693:                // Drive already decrypted
1.1       root      694:                sectorsRemaining.HighPart = 0;
                    695:                sectorsRemaining.LowPart = 0;
                    696:        }
                    697:        else
                    698:        {
1.1.1.3   root      699:                Print ("\r\nTo safely interrupt and defer decryption, press Esc.\r\n"
                    700:                        "WARNING: You can turn off power only after you press Esc.\r\n\r\n");
1.1       root      701:        }
                    702: 
                    703:        while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
                    704:        {
1.1.1.5   root      705:                if (EscKeyPressed())
                    706:                        break;
1.1       root      707: 
                    708:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
                    709:                        fragmentSectorCount = sectorsRemaining.LowPart;
                    710: 
                    711:                sector = sector - fragmentSectorCount;
                    712: 
                    713:                if (!(statCount++ & 0xf))
                    714:                {
                    715:                        Print ("\rRemaining: ");
1.1.1.5   root      716:                        PrintSectorCountInMB (sectorsRemaining);
1.1       root      717:                }
                    718: 
1.1.1.5   root      719:                if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) == BiosResultSuccess)
1.1       root      720:                {
1.1.1.5   root      721:                        AcquireSectorBuffer();
1.1       root      722: 
1.1.1.5   root      723:                        for (int i = 0; i < fragmentSectorCount; ++i)
                    724:                        {
                    725:                                CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE);
1.1       root      726: 
1.1.1.5   root      727:                                uint64 s = sector + i;
                    728:                                DecryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo);
1.1       root      729: 
1.1.1.5   root      730:                                CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE);
                    731:                        } 
1.1.1.3   root      732: 
1.1.1.5   root      733:                        ReleaseSectorBuffer();
                    734: 
                    735:                        if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) != BiosResultSuccess && !skipBadSectors)
                    736:                                goto askBadSectorSkip;
                    737:                }
                    738:                else if (!skipBadSectors)
                    739:                        goto askBadSectorSkip;
1.1       root      740: 
                    741:                sectorsRemaining = sectorsRemaining - fragmentSectorCount;
                    742:                headerUpdateRequired = true;
1.1.1.5   root      743:                continue;
                    744: 
                    745: askBadSectorSkip:
                    746:                if (!AskYesNo ("Skip all bad sectors"))
                    747:                        break;
                    748: 
                    749:                skipBadSectors = true;
                    750:                sector = sector + fragmentSectorCount;
                    751:                fragmentSectorCount = 1;
1.1       root      752:        }
                    753: 
                    754:        crypto_close (BootCryptoInfo);
                    755: 
                    756:        if (headerUpdateRequired)
                    757:        {
1.1.1.3   root      758:                AcquireSectorBuffer();
1.1       root      759:                uint64 headerSector;
                    760:                headerSector.HighPart = 0;
                    761:                headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
                    762: 
1.1.1.3   root      763:                // Update encrypted area size in volume header
1.1       root      764: 
1.1.1.3   root      765:                CRYPTO_INFO *headerCryptoInfo = crypto_open();
1.1.1.5   root      766:                while (ReadSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess);
1.1       root      767: 
1.1.1.6   root      768:                if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0)
1.1.1.3   root      769:                {
                    770:                        DecryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
1.1       root      771: 
1.1.1.3   root      772:                        uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
1.1       root      773: 
1.1.1.3   root      774:                        for (int i = 7; i >= 0; --i)
                    775:                        {
1.1.1.5   root      776:                                SectorBuffer[TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH + i] = (byte) encryptedAreaLength.LowPart;
1.1.1.3   root      777:                                encryptedAreaLength = encryptedAreaLength >> 8;
1.1       root      778:                        }
                    779: 
1.1.1.5   root      780:                        uint32 headerCrc32 = GetCrc32 (SectorBuffer + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
                    781: 
                    782:                        for (i = 3; i >= 0; --i)
                    783:                        {
                    784:                                SectorBuffer[TC_HEADER_OFFSET_HEADER_CRC + i] = (byte) headerCrc32;
                    785:                                headerCrc32 >>= 8;
                    786:                        }
                    787: 
1.1.1.3   root      788:                        EncryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
1.1       root      789:                }
                    790: 
1.1.1.3   root      791:                crypto_close (headerCryptoInfo);
                    792: 
1.1.1.5   root      793:                while (WriteSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess);
1.1.1.3   root      794:                ReleaseSectorBuffer();
1.1       root      795:        }
                    796: 
1.1.1.3   root      797:        if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
                    798:                Print ("\rDrive decrypted.\r\n");
                    799:        else
                    800:                Print ("\r\nDecryption deferred.\r\n");
                    801: 
1.1       root      802:        GetKeyboardChar();
1.1.1.5   root      803: ret:
                    804:        EraseMemory (bootArguments, sizeof (*bootArguments));
1.1       root      805: }
                    806: 
                    807: 
                    808: static void RepairMenu ()
                    809: {
                    810:        DriveGeometry bootLoaderDriveGeometry;
1.1.1.6   root      811: 
                    812:        if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry, true) != BiosResultSuccess)
1.1       root      813:        {
1.1.1.6   root      814:                // Some BIOSes may fail to get the geometry of an emulated floppy drive
                    815:                bootLoaderDriveGeometry.Cylinders = 80;
                    816:                bootLoaderDriveGeometry.Heads = 2;
                    817:                bootLoaderDriveGeometry.Sectors = 18;
1.1       root      818:        }
                    819: 
                    820:        while (true)
                    821:        {
                    822:                InitScreen();
                    823:                Print ("Available "); Print ("Repair Options"); Print (":\r\n");
                    824:                PrintRepeatedChar ('\xC4', 25);
1.1.1.5   root      825:                PrintEndl();
1.1       root      826: 
                    827:                enum
                    828:                {
                    829:                        RestoreNone = 0,
                    830:                        DecryptVolume,
                    831:                        RestoreTrueCryptLoader,
                    832:                        RestoreVolumeHeader,
                    833:                        RestoreOriginalSystemLoader
                    834:                };
                    835: 
                    836:                static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" };
                    837: 
1.1.1.5   root      838:                int selection = AskSelection (options,
                    839:                        (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER) ? array_capacity (options) : array_capacity (options) - 1);
1.1       root      840: 
                    841:                PrintEndl();
                    842: 
1.1.1.2   root      843:                switch (selection)
1.1       root      844:                {
1.1.1.2   root      845:                        case RestoreNone:
                    846:                                return;
                    847: 
                    848:                        case DecryptVolume:
1.1.1.5   root      849:                                DecryptDrive (BootDrive);
1.1.1.2   root      850:                                continue;
                    851: 
                    852:                        case RestoreOriginalSystemLoader:
1.1.1.6   root      853:                                if (!AskYesNo ("Is the system partition/drive decrypted"))
1.1.1.3   root      854:                                {
                    855:                                        Print ("Please decrypt it first.\r\n");
                    856:                                        GetKeyboardChar();
1.1.1.2   root      857:                                        continue;
1.1.1.3   root      858:                                }
1.1.1.4   root      859:                                break;
1.1       root      860:                }
                    861: 
                    862:                bool writeConfirmed = false;
                    863:                BiosResult result;
                    864: 
                    865:                uint64 sector;
                    866:                sector.HighPart = 0;
                    867:                ChsAddress chs;
                    868: 
1.1.1.3   root      869:                byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE];
                    870:                AcquireSectorBuffer();
                    871: 
1.1       root      872:                for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR);
                    873:                        i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i)
                    874:                {
1.1.1.5   root      875:                        sector.LowPart = i;
                    876: 
                    877:                        if (selection == RestoreOriginalSystemLoader)
                    878:                                sector.LowPart += TC_ORIG_BOOT_LOADER_BACKUP_SECTOR;
                    879:                        else if (selection == RestoreTrueCryptLoader)
                    880:                                sector.LowPart += TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR;
1.1       root      881: 
                    882:                        // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used.
                    883:                        // Therefore, only CHS addressing can be used.
                    884:                        LbaToChs (bootLoaderDriveGeometry, sector, chs);
                    885:                        sector.LowPart = i;
                    886: 
                    887:                        if (i == TC_MBR_SECTOR)
                    888:                        {
1.1.1.3   root      889:                                // Read current partition table
                    890:                                result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1);
1.1       root      891:                                if (result != BiosResultSuccess)
                    892:                                        goto err;
                    893: 
1.1.1.3   root      894:                                memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable));
                    895:                        }
                    896: 
                    897:                        result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1);
                    898:                        if (result != BiosResultSuccess)
                    899:                                goto err;
                    900: 
                    901:                        if (i == TC_MBR_SECTOR)
                    902:                        {
                    903:                                // Preserve current partition table
                    904:                                memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable));
1.1       root      905:                        }
                    906: 
                    907:                        // Volume header
                    908:                        if (i == TC_BOOT_VOLUME_HEADER_SECTOR)
                    909:                        {
                    910:                                if (selection == RestoreTrueCryptLoader)
                    911:                                        continue;
                    912: 
                    913:                                if (selection == RestoreVolumeHeader)
                    914:                                {
                    915:                                        while (true)
                    916:                                        {
                    917:                                                Password password;
                    918:                                                byte exitKey = AskPassword (password);
                    919: 
                    920:                                                if (exitKey != TC_BIOS_KEY_ENTER)
                    921:                                                        goto abort;
                    922: 
                    923:                                                CRYPTO_INFO *cryptoInfo;
                    924: 
1.1.1.3   root      925:                                                CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE);
                    926:                                                ReleaseSectorBuffer();
                    927: 
1.1       root      928:                                                // Restore volume header only if the current one cannot be used
1.1.1.5   root      929:                                                if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true))
1.1       root      930:                                                {
                    931:                                                        Print ("Original header preserved.\r\n");
                    932:                                                        crypto_close (cryptoInfo);
                    933:                                                        goto err;
                    934:                                                }
                    935: 
1.1.1.3   root      936:                                                AcquireSectorBuffer();
                    937:                                                CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE);
                    938: 
1.1.1.6   root      939:                                                if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0)
1.1       root      940:                                                {
                    941:                                                        crypto_close (cryptoInfo);
                    942:                                                        break;
                    943:                                                }
                    944: 
1.1.1.4   root      945:                                                Print ("Incorrect password.\r\n\r\n");
1.1       root      946:                                        }
                    947:                                }
                    948:                        }
                    949: 
1.1.1.3   root      950:                        if (!writeConfirmed && !AskYesNo ("Modify drive 0"))
1.1       root      951:                                goto abort;
                    952:                        writeConfirmed = true;
                    953: 
1.1.1.3   root      954:                        if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess)
1.1       root      955:                                goto err;
                    956:                }
                    957: done:
                    958:                switch (selection)
                    959:                {
                    960:                case RestoreTrueCryptLoader:
                    961:                        Print ("TrueCrypt Boot Loader");
                    962:                        break;
                    963: 
                    964:                case RestoreVolumeHeader:
                    965:                        Print ("Header");
                    966:                        break;
                    967: 
                    968:                case RestoreOriginalSystemLoader:
                    969:                        Print ("System loader");
                    970:                        break;
                    971:                }
                    972:                Print (" restored.\r\n");
                    973: 
                    974: err:   GetKeyboardChar();
1.1.1.3   root      975: abort: ReleaseSectorBuffer();
1.1       root      976:        }
                    977: }
                    978: 
1.1.1.5   root      979: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                    980: 
1.1       root      981: 
                    982: #ifndef DEBUG
                    983: extern "C" void _acrtused () { }  // Required by linker
                    984: #endif
                    985: 
                    986: 
                    987: void main ()
                    988: {
                    989:        __asm mov BootLoaderDrive, dl
                    990:        __asm mov BootSectorFlags, dh
                    991: 
1.1.1.3   root      992: #ifdef TC_BOOT_TRACING_ENABLED
1.1       root      993:        InitDebugPort();
                    994: #endif
                    995: 
1.1.1.3   root      996: #ifdef TC_BOOT_STACK_CHECKING_ENABLED
                    997:        InitStackChecker();
                    998: #endif
                    999: 
1.1.1.6   root     1000: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1001:        ReadBootSectorUserConfiguration();
                   1002: #endif
                   1003: 
1.1.1.5   root     1004:        InitVideoMode();
                   1005:        InitScreen();
                   1006: 
                   1007:        // Determine boot drive
1.1       root     1008:        BootDrive = BootLoaderDrive;
                   1009:        if (BootDrive < TC_FIRST_BIOS_DRIVE)
                   1010:                BootDrive = TC_FIRST_BIOS_DRIVE;
                   1011: 
1.1.1.5   root     1012:        // Query boot drive geometry
1.1       root     1013:        if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess)
                   1014:        {
                   1015:                BootDrive = TC_FIRST_BIOS_DRIVE;
                   1016:                if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess)
                   1017:                        BootDriveGeometryValid = TRUE;
                   1018:        }
                   1019:        else
                   1020:                BootDriveGeometryValid = TRUE;
                   1021: 
1.1.1.5   root     1022: 
                   1023: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1024: 
                   1025:        // Check whether the user is not using the Rescue Disk to create a hidden system
                   1026: 
                   1027:        if (ReadWriteMBR (false, BootDrive, true) == BiosResultSuccess
                   1028:                && *(uint32 *) (SectorBuffer + 6) == 0x65757254
                   1029:                && *(uint32 *) (SectorBuffer + 10) == 0x70797243
                   1030:                && (SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE)
                   1031:        {
                   1032:                PrintError ("It appears you are creating a hidden OS.");
                   1033:                if (AskYesNo ("Is this correct"))
                   1034:                {
                   1035:                        Print ("Please remove the Rescue Disk from the drive and restart.");
                   1036:                        while (true);
                   1037:                }
                   1038:        }
                   1039: 
                   1040: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1041: 
                   1042: 
                   1043:        // Main menu
                   1044: 
1.1       root     1045:        while (true)
                   1046:        {
1.1.1.5   root     1047:                byte exitKey;
1.1       root     1048:                InitScreen();
                   1049: 
1.1.1.5   root     1050: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1051: 
                   1052:                // Hidden system setup
                   1053:                byte hiddenSystemCreationPhase = BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
                   1054: 
                   1055:                if (hiddenSystemCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE)
                   1056:                {
1.1.1.6   root     1057:                        PreventNormalSystemBoot = true;
1.1.1.5   root     1058:                        PrintMainMenu();
                   1059: 
                   1060:                        if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING)
                   1061:                        {
                   1062:                                if (CopyActivePartitionToHiddenVolume (BootDrive, exitKey))
                   1063:                                {
1.1.1.6   root     1064:                                        BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING;
1.1.1.5   root     1065:                                        UpdateBootSectorConfiguration (BootLoaderDrive);
                   1066:                                }
                   1067:                                else if (exitKey == TC_BIOS_KEY_ESC)
                   1068:                                        goto bootMenu;
                   1069:                                else
                   1070:                                        continue;
                   1071:                        }
                   1072:                }
                   1073:                else
                   1074:                        PrintMainMenu();
                   1075: 
                   1076:                exitKey = BootEncryptedDrive();
                   1077: 
                   1078: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
1.1       root     1079:                
1.1.1.5   root     1080:                PrintMainMenu();
                   1081:                exitKey = BootEncryptedDrive();
                   1082: 
1.1       root     1083:                if (exitKey == TC_MENU_KEY_REPAIR)
                   1084:                {
                   1085:                        RepairMenu();
                   1086:                        continue;
                   1087:                }
                   1088: 
1.1.1.5   root     1089: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1090: 
                   1091: bootMenu:
1.1.1.6   root     1092:                if (!PreventBootMenu)
                   1093:                        BootMenu();
1.1       root     1094:        }
                   1095: }

unix.superglobalmegacorp.com

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