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

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))
                    585:        {
                    586:                PrintError ("Hidden volume size differs from system partition");
                    587:                crypto_close (BootCryptoInfo);
                    588:                goto err;
                    589:        }
                    590: 
                    591:        InitScreen();
                    592:        Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n");
                    593: 
                    594:        while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
                    595:        {
                    596:                if (EscKeyPressed())
                    597:                {
                    598:                        Print ("\rIf aborted, copying will have to start from the beginning (if attempted again).\r\n");
                    599:                        if (AskYesNo ("Abort"))
                    600:                                break;
                    601:                }
                    602: 
                    603:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
                    604:                        fragmentSectorCount = sectorsRemaining.LowPart;
                    605: 
                    606:                if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess)
                    607:                        break;
                    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)
                    624:                        break;
                    625: 
                    626:                sectorsRemaining = sectorsRemaining - fragmentSectorCount;
                    627:                sectorOffset = sectorOffset + fragmentSectorCount;
                    628: 
                    629:                if (!(statCount++ & 0xf))
                    630:                {
                    631:                        Print ("\rRemaining: ");
                    632:                        PrintSectorCountInMB (sectorsRemaining);
                    633:                }
                    634:        }
                    635: 
                    636:        crypto_close (BootCryptoInfo);
                    637: 
                    638:        if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
                    639:        {
                    640:                status = true;
                    641:                Print ("\rCopying completed.");
                    642:        }
                    643: 
                    644:        PrintEndl (2);
                    645:        goto ret;
                    646: 
                    647: err:
                    648:        exitKey = TC_BIOS_KEY_ESC;
                    649:        GetKeyboardChar();
                    650: 
                    651: ret:
                    652:        EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments));
                    653:        return status;
                    654: }
                    655: 
                    656: 
                    657: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                    658: 
                    659: 
1.1       root      660: static void DecryptDrive (byte drive)
                    661: {
                    662:        byte exitKey;
1.1.1.5   root      663:        if (!MountVolume (drive, exitKey, false, true))
1.1       root      664:                return;
                    665: 
1.1.1.5   root      666:        BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
1.1       root      667: 
                    668:        bool headerUpdateRequired = false;
                    669:        uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector;
                    670:        uint64 sector = EncryptedVirtualPartition.EndSector + 1;
                    671: 
1.1.1.5   root      672:        int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS
1.1       root      673:        int statCount;
                    674: 
1.1.1.5   root      675:        bool skipBadSectors = false;
                    676: 
1.1.1.6 ! root      677:        Print ("\r\nUse only if Windows cannot start. Decryption under Windows is much faster\r\n"
        !           678:                        "(in TrueCrypt, select 'System' > 'Permanently Decrypt').\r\n\r\n");
1.1.1.5   root      679: 
                    680:        if (!AskYesNo ("Decrypt now"))
                    681:        {
                    682:                crypto_close (BootCryptoInfo);
                    683:                goto ret;
                    684:        }
                    685: 
                    686:        if (EncryptedVirtualPartition.Drive == TC_INVALID_BIOS_DRIVE)
1.1       root      687:        {
1.1.1.3   root      688:                // Drive already decrypted
1.1       root      689:                sectorsRemaining.HighPart = 0;
                    690:                sectorsRemaining.LowPart = 0;
                    691:        }
                    692:        else
                    693:        {
1.1.1.3   root      694:                Print ("\r\nTo safely interrupt and defer decryption, press Esc.\r\n"
                    695:                        "WARNING: You can turn off power only after you press Esc.\r\n\r\n");
1.1       root      696:        }
                    697: 
                    698:        while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
                    699:        {
1.1.1.5   root      700:                if (EscKeyPressed())
                    701:                        break;
1.1       root      702: 
                    703:                if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
                    704:                        fragmentSectorCount = sectorsRemaining.LowPart;
                    705: 
                    706:                sector = sector - fragmentSectorCount;
                    707: 
                    708:                if (!(statCount++ & 0xf))
                    709:                {
                    710:                        Print ("\rRemaining: ");
1.1.1.5   root      711:                        PrintSectorCountInMB (sectorsRemaining);
1.1       root      712:                }
                    713: 
1.1.1.5   root      714:                if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) == BiosResultSuccess)
1.1       root      715:                {
1.1.1.5   root      716:                        AcquireSectorBuffer();
1.1       root      717: 
1.1.1.5   root      718:                        for (int i = 0; i < fragmentSectorCount; ++i)
                    719:                        {
                    720:                                CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE);
1.1       root      721: 
1.1.1.5   root      722:                                uint64 s = sector + i;
                    723:                                DecryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo);
1.1       root      724: 
1.1.1.5   root      725:                                CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE);
                    726:                        } 
1.1.1.3   root      727: 
1.1.1.5   root      728:                        ReleaseSectorBuffer();
                    729: 
                    730:                        if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) != BiosResultSuccess && !skipBadSectors)
                    731:                                goto askBadSectorSkip;
                    732:                }
                    733:                else if (!skipBadSectors)
                    734:                        goto askBadSectorSkip;
1.1       root      735: 
                    736:                sectorsRemaining = sectorsRemaining - fragmentSectorCount;
                    737:                headerUpdateRequired = true;
1.1.1.5   root      738:                continue;
                    739: 
                    740: askBadSectorSkip:
                    741:                if (!AskYesNo ("Skip all bad sectors"))
                    742:                        break;
                    743: 
                    744:                skipBadSectors = true;
                    745:                sector = sector + fragmentSectorCount;
                    746:                fragmentSectorCount = 1;
1.1       root      747:        }
                    748: 
                    749:        crypto_close (BootCryptoInfo);
                    750: 
                    751:        if (headerUpdateRequired)
                    752:        {
1.1.1.3   root      753:                AcquireSectorBuffer();
1.1       root      754:                uint64 headerSector;
                    755:                headerSector.HighPart = 0;
                    756:                headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
                    757: 
1.1.1.3   root      758:                // Update encrypted area size in volume header
1.1       root      759: 
1.1.1.3   root      760:                CRYPTO_INFO *headerCryptoInfo = crypto_open();
1.1.1.5   root      761:                while (ReadSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess);
1.1       root      762: 
1.1.1.6 ! root      763:                if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0)
1.1.1.3   root      764:                {
                    765:                        DecryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
1.1       root      766: 
1.1.1.3   root      767:                        uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
1.1       root      768: 
1.1.1.3   root      769:                        for (int i = 7; i >= 0; --i)
                    770:                        {
1.1.1.5   root      771:                                SectorBuffer[TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH + i] = (byte) encryptedAreaLength.LowPart;
1.1.1.3   root      772:                                encryptedAreaLength = encryptedAreaLength >> 8;
1.1       root      773:                        }
                    774: 
1.1.1.5   root      775:                        uint32 headerCrc32 = GetCrc32 (SectorBuffer + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
                    776: 
                    777:                        for (i = 3; i >= 0; --i)
                    778:                        {
                    779:                                SectorBuffer[TC_HEADER_OFFSET_HEADER_CRC + i] = (byte) headerCrc32;
                    780:                                headerCrc32 >>= 8;
                    781:                        }
                    782: 
1.1.1.3   root      783:                        EncryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
1.1       root      784:                }
                    785: 
1.1.1.3   root      786:                crypto_close (headerCryptoInfo);
                    787: 
1.1.1.5   root      788:                while (WriteSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess);
1.1.1.3   root      789:                ReleaseSectorBuffer();
1.1       root      790:        }
                    791: 
1.1.1.3   root      792:        if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
                    793:                Print ("\rDrive decrypted.\r\n");
                    794:        else
                    795:                Print ("\r\nDecryption deferred.\r\n");
                    796: 
1.1       root      797:        GetKeyboardChar();
1.1.1.5   root      798: ret:
                    799:        EraseMemory (bootArguments, sizeof (*bootArguments));
1.1       root      800: }
                    801: 
                    802: 
                    803: static void RepairMenu ()
                    804: {
                    805:        DriveGeometry bootLoaderDriveGeometry;
1.1.1.6 ! root      806: 
        !           807:        if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry, true) != BiosResultSuccess)
1.1       root      808:        {
1.1.1.6 ! root      809:                // Some BIOSes may fail to get the geometry of an emulated floppy drive
        !           810:                bootLoaderDriveGeometry.Cylinders = 80;
        !           811:                bootLoaderDriveGeometry.Heads = 2;
        !           812:                bootLoaderDriveGeometry.Sectors = 18;
1.1       root      813:        }
                    814: 
                    815:        while (true)
                    816:        {
                    817:                InitScreen();
                    818:                Print ("Available "); Print ("Repair Options"); Print (":\r\n");
                    819:                PrintRepeatedChar ('\xC4', 25);
1.1.1.5   root      820:                PrintEndl();
1.1       root      821: 
                    822:                enum
                    823:                {
                    824:                        RestoreNone = 0,
                    825:                        DecryptVolume,
                    826:                        RestoreTrueCryptLoader,
                    827:                        RestoreVolumeHeader,
                    828:                        RestoreOriginalSystemLoader
                    829:                };
                    830: 
                    831:                static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" };
                    832: 
1.1.1.5   root      833:                int selection = AskSelection (options,
                    834:                        (BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER) ? array_capacity (options) : array_capacity (options) - 1);
1.1       root      835: 
                    836:                PrintEndl();
                    837: 
1.1.1.2   root      838:                switch (selection)
1.1       root      839:                {
1.1.1.2   root      840:                        case RestoreNone:
                    841:                                return;
                    842: 
                    843:                        case DecryptVolume:
1.1.1.5   root      844:                                DecryptDrive (BootDrive);
1.1.1.2   root      845:                                continue;
                    846: 
                    847:                        case RestoreOriginalSystemLoader:
1.1.1.6 ! root      848:                                if (!AskYesNo ("Is the system partition/drive decrypted"))
1.1.1.3   root      849:                                {
                    850:                                        Print ("Please decrypt it first.\r\n");
                    851:                                        GetKeyboardChar();
1.1.1.2   root      852:                                        continue;
1.1.1.3   root      853:                                }
1.1.1.4   root      854:                                break;
1.1       root      855:                }
                    856: 
                    857:                bool writeConfirmed = false;
                    858:                BiosResult result;
                    859: 
                    860:                uint64 sector;
                    861:                sector.HighPart = 0;
                    862:                ChsAddress chs;
                    863: 
1.1.1.3   root      864:                byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE];
                    865:                AcquireSectorBuffer();
                    866: 
1.1       root      867:                for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR);
                    868:                        i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i)
                    869:                {
1.1.1.5   root      870:                        sector.LowPart = i;
                    871: 
                    872:                        if (selection == RestoreOriginalSystemLoader)
                    873:                                sector.LowPart += TC_ORIG_BOOT_LOADER_BACKUP_SECTOR;
                    874:                        else if (selection == RestoreTrueCryptLoader)
                    875:                                sector.LowPart += TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR;
1.1       root      876: 
                    877:                        // The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used.
                    878:                        // Therefore, only CHS addressing can be used.
                    879:                        LbaToChs (bootLoaderDriveGeometry, sector, chs);
                    880:                        sector.LowPart = i;
                    881: 
                    882:                        if (i == TC_MBR_SECTOR)
                    883:                        {
1.1.1.3   root      884:                                // Read current partition table
                    885:                                result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1);
1.1       root      886:                                if (result != BiosResultSuccess)
                    887:                                        goto err;
                    888: 
1.1.1.3   root      889:                                memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable));
                    890:                        }
                    891: 
                    892:                        result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1);
                    893:                        if (result != BiosResultSuccess)
                    894:                                goto err;
                    895: 
                    896:                        if (i == TC_MBR_SECTOR)
                    897:                        {
                    898:                                // Preserve current partition table
                    899:                                memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable));
1.1       root      900:                        }
                    901: 
                    902:                        // Volume header
                    903:                        if (i == TC_BOOT_VOLUME_HEADER_SECTOR)
                    904:                        {
                    905:                                if (selection == RestoreTrueCryptLoader)
                    906:                                        continue;
                    907: 
                    908:                                if (selection == RestoreVolumeHeader)
                    909:                                {
                    910:                                        while (true)
                    911:                                        {
                    912:                                                Password password;
                    913:                                                byte exitKey = AskPassword (password);
                    914: 
                    915:                                                if (exitKey != TC_BIOS_KEY_ENTER)
                    916:                                                        goto abort;
                    917: 
                    918:                                                CRYPTO_INFO *cryptoInfo;
                    919: 
1.1.1.3   root      920:                                                CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE);
                    921:                                                ReleaseSectorBuffer();
                    922: 
1.1       root      923:                                                // Restore volume header only if the current one cannot be used
1.1.1.5   root      924:                                                if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true))
1.1       root      925:                                                {
                    926:                                                        Print ("Original header preserved.\r\n");
                    927:                                                        crypto_close (cryptoInfo);
                    928:                                                        goto err;
                    929:                                                }
                    930: 
1.1.1.3   root      931:                                                AcquireSectorBuffer();
                    932:                                                CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE);
                    933: 
1.1.1.6 ! root      934:                                                if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0)
1.1       root      935:                                                {
                    936:                                                        crypto_close (cryptoInfo);
                    937:                                                        break;
                    938:                                                }
                    939: 
1.1.1.4   root      940:                                                Print ("Incorrect password.\r\n\r\n");
1.1       root      941:                                        }
                    942:                                }
                    943:                        }
                    944: 
1.1.1.3   root      945:                        if (!writeConfirmed && !AskYesNo ("Modify drive 0"))
1.1       root      946:                                goto abort;
                    947:                        writeConfirmed = true;
                    948: 
1.1.1.3   root      949:                        if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess)
1.1       root      950:                                goto err;
                    951:                }
                    952: done:
                    953:                switch (selection)
                    954:                {
                    955:                case RestoreTrueCryptLoader:
                    956:                        Print ("TrueCrypt Boot Loader");
                    957:                        break;
                    958: 
                    959:                case RestoreVolumeHeader:
                    960:                        Print ("Header");
                    961:                        break;
                    962: 
                    963:                case RestoreOriginalSystemLoader:
                    964:                        Print ("System loader");
                    965:                        break;
                    966:                }
                    967:                Print (" restored.\r\n");
                    968: 
                    969: err:   GetKeyboardChar();
1.1.1.3   root      970: abort: ReleaseSectorBuffer();
1.1       root      971:        }
                    972: }
                    973: 
1.1.1.5   root      974: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                    975: 
1.1       root      976: 
                    977: #ifndef DEBUG
                    978: extern "C" void _acrtused () { }  // Required by linker
                    979: #endif
                    980: 
                    981: 
                    982: void main ()
                    983: {
                    984:        __asm mov BootLoaderDrive, dl
                    985:        __asm mov BootSectorFlags, dh
                    986: 
1.1.1.3   root      987: #ifdef TC_BOOT_TRACING_ENABLED
1.1       root      988:        InitDebugPort();
                    989: #endif
                    990: 
1.1.1.3   root      991: #ifdef TC_BOOT_STACK_CHECKING_ENABLED
                    992:        InitStackChecker();
                    993: #endif
                    994: 
1.1.1.6 ! root      995: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
        !           996:        ReadBootSectorUserConfiguration();
        !           997: #endif
        !           998: 
1.1.1.5   root      999:        InitVideoMode();
                   1000:        InitScreen();
                   1001: 
                   1002:        // Determine boot drive
1.1       root     1003:        BootDrive = BootLoaderDrive;
                   1004:        if (BootDrive < TC_FIRST_BIOS_DRIVE)
                   1005:                BootDrive = TC_FIRST_BIOS_DRIVE;
                   1006: 
1.1.1.5   root     1007:        // Query boot drive geometry
1.1       root     1008:        if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess)
                   1009:        {
                   1010:                BootDrive = TC_FIRST_BIOS_DRIVE;
                   1011:                if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess)
                   1012:                        BootDriveGeometryValid = TRUE;
                   1013:        }
                   1014:        else
                   1015:                BootDriveGeometryValid = TRUE;
                   1016: 
1.1.1.5   root     1017: 
                   1018: #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1019: 
                   1020:        // Check whether the user is not using the Rescue Disk to create a hidden system
                   1021: 
                   1022:        if (ReadWriteMBR (false, BootDrive, true) == BiosResultSuccess
                   1023:                && *(uint32 *) (SectorBuffer + 6) == 0x65757254
                   1024:                && *(uint32 *) (SectorBuffer + 10) == 0x70797243
                   1025:                && (SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE)
                   1026:        {
                   1027:                PrintError ("It appears you are creating a hidden OS.");
                   1028:                if (AskYesNo ("Is this correct"))
                   1029:                {
                   1030:                        Print ("Please remove the Rescue Disk from the drive and restart.");
                   1031:                        while (true);
                   1032:                }
                   1033:        }
                   1034: 
                   1035: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1036: 
                   1037: 
                   1038:        // Main menu
                   1039: 
1.1       root     1040:        while (true)
                   1041:        {
1.1.1.5   root     1042:                byte exitKey;
1.1       root     1043:                InitScreen();
                   1044: 
1.1.1.5   root     1045: #ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1046: 
                   1047:                // Hidden system setup
                   1048:                byte hiddenSystemCreationPhase = BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
                   1049: 
                   1050:                if (hiddenSystemCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE)
                   1051:                {
1.1.1.6 ! root     1052:                        PreventNormalSystemBoot = true;
1.1.1.5   root     1053:                        PrintMainMenu();
                   1054: 
                   1055:                        if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING)
                   1056:                        {
                   1057:                                if (CopyActivePartitionToHiddenVolume (BootDrive, exitKey))
                   1058:                                {
1.1.1.6 ! root     1059:                                        BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING;
1.1.1.5   root     1060:                                        UpdateBootSectorConfiguration (BootLoaderDrive);
                   1061:                                }
                   1062:                                else if (exitKey == TC_BIOS_KEY_ESC)
                   1063:                                        goto bootMenu;
                   1064:                                else
                   1065:                                        continue;
                   1066:                        }
                   1067:                }
                   1068:                else
                   1069:                        PrintMainMenu();
                   1070: 
                   1071:                exitKey = BootEncryptedDrive();
                   1072: 
                   1073: #else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
1.1       root     1074:                
1.1.1.5   root     1075:                PrintMainMenu();
                   1076:                exitKey = BootEncryptedDrive();
                   1077: 
1.1       root     1078:                if (exitKey == TC_MENU_KEY_REPAIR)
                   1079:                {
                   1080:                        RepairMenu();
                   1081:                        continue;
                   1082:                }
                   1083: 
1.1.1.5   root     1084: #endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
                   1085: 
                   1086: bootMenu:
1.1.1.6 ! root     1087:                if (!PreventBootMenu)
        !          1088:                        BootMenu();
1.1       root     1089:        }
                   1090: }

unix.superglobalmegacorp.com

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