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

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

unix.superglobalmegacorp.com

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