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

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

unix.superglobalmegacorp.com

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