📄 bootmain.cpp
字号:
uint64 sectorOffset;
sectorOffset.LowPart = 0;
sectorOffset.HighPart = 0;
int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS
int statCount;
if (!CheckMemoryRequirements ())
goto err;
if (!GetActiveAndFollowingPartition (drive))
goto err;
if (PartitionFollowingActive.Drive == TC_INVALID_BIOS_DRIVE)
TC_THROW_FATAL_EXCEPTION;
// Check if BIOS can read the last sector of the hidden system
AcquireSectorBuffer();
if (ReadSectors (SectorBuffer, PartitionFollowingActive.Drive, PartitionFollowingActive.EndSector - (TC_VOLUME_HEADER_GROUP_SIZE / TC_LB_SIZE - 2), 1) != BiosResultSuccess
|| (uint16) GetCrc32 (SectorBuffer, sizeof (SectorBuffer)) != OuterVolumeBackupHeaderCrc)
{
PrintError ("Your BIOS does not support large drives");
Print (TC_BOOT_STR_UPGRADE_BIOS);
ReleaseSectorBuffer();
goto err;
}
ReleaseSectorBuffer();
if (!MountVolume (drive, exitKey, true, false))
return false;
sectorsRemaining = EncryptedVirtualPartition.SectorCount;
if (!(sectorsRemaining == ActivePartition.SectorCount))
TC_THROW_FATAL_EXCEPTION;
InitScreen();
Print ("\r\nCopying system to hidden volume. To abort, press Esc.\r\n\r\n");
while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
{
if (EscKeyPressed())
{
Print ("\rIf aborted, copying will have to start from the beginning (if attempted again).\r\n");
if (AskYesNo ("Abort"))
break;
}
if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
fragmentSectorCount = sectorsRemaining.LowPart;
if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, ActivePartition.StartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess)
{
Print ("To fix bad sectors: 1) Terminate 2) Encrypt and decrypt sys partition 3) Retry\r\n");
crypto_close (BootCryptoInfo);
goto err;
}
AcquireSectorBuffer();
for (int i = 0; i < fragmentSectorCount; ++i)
{
CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE);
uint64 s = HiddenVolumeStartUnitNo + sectorOffset + i;
EncryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo);
CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE);
}
ReleaseSectorBuffer();
if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, HiddenVolumeStartSector + sectorOffset, fragmentSectorCount, false) != BiosResultSuccess)
{
crypto_close (BootCryptoInfo);
goto err;
}
sectorsRemaining = sectorsRemaining - fragmentSectorCount;
sectorOffset = sectorOffset + fragmentSectorCount;
if (!(statCount++ & 0xf))
{
Print ("\rRemaining: ");
PrintSectorCountInMB (sectorsRemaining);
}
}
crypto_close (BootCryptoInfo);
if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
{
status = true;
Print ("\rCopying completed.");
}
PrintEndl (2);
goto ret;
err:
exitKey = TC_BIOS_KEY_ESC;
GetKeyboardChar();
ret:
EraseMemory ((void *) TC_BOOT_LOADER_ARGS_OFFSET, sizeof (BootArguments));
return status;
}
#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
static void DecryptDrive (byte drive)
{
byte exitKey;
if (!MountVolume (drive, exitKey, false, true))
return;
BootArguments *bootArguments = (BootArguments *) TC_BOOT_LOADER_ARGS_OFFSET;
bool headerUpdateRequired = false;
uint64 sectorsRemaining = EncryptedVirtualPartition.EndSector + 1 - EncryptedVirtualPartition.StartSector;
uint64 sector = EncryptedVirtualPartition.EndSector + 1;
int fragmentSectorCount = 0x7f; // Maximum safe value supported by BIOS
int statCount;
bool skipBadSectors = false;
Print ("\r\nUse only if Windows cannot start. Decryption under Windows is much faster\r\n"
"(in TrueCrypt, select 'System' > 'Permanently Decrypt').\r\n\r\n");
if (!AskYesNo ("Decrypt now"))
{
crypto_close (BootCryptoInfo);
goto ret;
}
if (EncryptedVirtualPartition.Drive == TC_INVALID_BIOS_DRIVE)
{
// Drive already decrypted
sectorsRemaining.HighPart = 0;
sectorsRemaining.LowPart = 0;
}
else
{
Print ("\r\nTo safely interrupt and defer decryption, press Esc.\r\n"
"WARNING: You can turn off power only after you press Esc.\r\n\r\n");
}
while (sectorsRemaining.HighPart != 0 || sectorsRemaining.LowPart != 0)
{
if (EscKeyPressed())
break;
if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart < fragmentSectorCount)
fragmentSectorCount = sectorsRemaining.LowPart;
sector = sector - fragmentSectorCount;
if (!(statCount++ & 0xf))
{
Print ("\rRemaining: ");
PrintSectorCountInMB (sectorsRemaining);
}
if (ReadWriteSectors (false, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) == BiosResultSuccess)
{
AcquireSectorBuffer();
for (int i = 0; i < fragmentSectorCount; ++i)
{
CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, SectorBuffer, TC_LB_SIZE);
uint64 s = sector + i;
DecryptDataUnits (SectorBuffer, &s, 1, BootCryptoInfo);
CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, i * TC_LB_SIZE, TC_LB_SIZE);
}
ReleaseSectorBuffer();
if (ReadWriteSectors (true, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, drive, sector, fragmentSectorCount, skipBadSectors) != BiosResultSuccess && !skipBadSectors)
goto askBadSectorSkip;
}
else if (!skipBadSectors)
goto askBadSectorSkip;
sectorsRemaining = sectorsRemaining - fragmentSectorCount;
headerUpdateRequired = true;
continue;
askBadSectorSkip:
if (!AskYesNo ("Skip all bad sectors"))
break;
skipBadSectors = true;
sector = sector + fragmentSectorCount;
fragmentSectorCount = 1;
}
crypto_close (BootCryptoInfo);
if (headerUpdateRequired)
{
AcquireSectorBuffer();
uint64 headerSector;
headerSector.HighPart = 0;
headerSector.LowPart = TC_BOOT_VOLUME_HEADER_SECTOR;
// Update encrypted area size in volume header
CRYPTO_INFO *headerCryptoInfo = crypto_open();
while (ReadSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess);
if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &bootArguments->BootPassword, NULL, headerCryptoInfo) == 0)
{
DecryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
uint64 encryptedAreaLength = sectorsRemaining << TC_LB_SIZE_BIT_SHIFT_DIVISOR;
for (int i = 7; i >= 0; --i)
{
SectorBuffer[TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH + i] = (byte) encryptedAreaLength.LowPart;
encryptedAreaLength = encryptedAreaLength >> 8;
}
uint32 headerCrc32 = GetCrc32 (SectorBuffer + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
for (i = 3; i >= 0; --i)
{
SectorBuffer[TC_HEADER_OFFSET_HEADER_CRC + i] = (byte) headerCrc32;
headerCrc32 >>= 8;
}
EncryptBuffer (SectorBuffer + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerCryptoInfo);
}
crypto_close (headerCryptoInfo);
while (WriteSectors (SectorBuffer, drive, headerSector, 1) != BiosResultSuccess);
ReleaseSectorBuffer();
}
if (sectorsRemaining.HighPart == 0 && sectorsRemaining.LowPart == 0)
Print ("\rDrive decrypted.\r\n");
else
Print ("\r\nDecryption deferred.\r\n");
GetKeyboardChar();
ret:
EraseMemory (bootArguments, sizeof (*bootArguments));
}
static void RepairMenu ()
{
DriveGeometry bootLoaderDriveGeometry;
if (GetDriveGeometry (BootLoaderDrive, bootLoaderDriveGeometry, true) != BiosResultSuccess)
{
// Some BIOSes may fail to get the geometry of an emulated floppy drive
bootLoaderDriveGeometry.Cylinders = 80;
bootLoaderDriveGeometry.Heads = 2;
bootLoaderDriveGeometry.Sectors = 18;
}
while (true)
{
InitScreen();
Print ("Available "); Print ("Repair Options"); Print (":\r\n");
PrintRepeatedChar ('\xC4', 25);
PrintEndl();
enum
{
RestoreNone = 0,
DecryptVolume,
RestoreTrueCryptLoader,
RestoreVolumeHeader,
RestoreOriginalSystemLoader
};
static const char *options[] = { "Permanently decrypt system partition/drive", "Restore TrueCrypt Boot Loader", "Restore key data (volume header)", "Restore original system loader" };
int selection = AskSelection (options,
(BootSectorFlags & TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER) ? array_capacity (options) : array_capacity (options) - 1);
PrintEndl();
switch (selection)
{
case RestoreNone:
return;
case DecryptVolume:
DecryptDrive (BootDrive);
continue;
case RestoreOriginalSystemLoader:
if (!AskYesNo ("Is the system partition/drive decrypted"))
{
Print ("Please decrypt it first.\r\n");
GetKeyboardChar();
continue;
}
break;
}
bool writeConfirmed = false;
BiosResult result;
uint64 sector;
sector.HighPart = 0;
ChsAddress chs;
byte mbrPartTable[TC_LB_SIZE - TC_MAX_MBR_BOOT_CODE_SIZE];
AcquireSectorBuffer();
for (int i = (selection == RestoreVolumeHeader ? TC_BOOT_VOLUME_HEADER_SECTOR : TC_MBR_SECTOR);
i < TC_BOOT_LOADER_AREA_SECTOR_COUNT; ++i)
{
sector.LowPart = i;
if (selection == RestoreOriginalSystemLoader)
sector.LowPart += TC_ORIG_BOOT_LOADER_BACKUP_SECTOR;
else if (selection == RestoreTrueCryptLoader)
sector.LowPart += TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR;
// The backup medium may be a floppy-emulated bootable CD. The emulation may fail if LBA addressing is used.
// Therefore, only CHS addressing can be used.
LbaToChs (bootLoaderDriveGeometry, sector, chs);
sector.LowPart = i;
if (i == TC_MBR_SECTOR)
{
// Read current partition table
result = ReadSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1);
if (result != BiosResultSuccess)
goto err;
memcpy (mbrPartTable, SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbrPartTable));
}
result = ReadSectors (SectorBuffer, BootLoaderDrive, chs, 1);
if (result != BiosResultSuccess)
goto err;
if (i == TC_MBR_SECTOR)
{
// Preserve current partition table
memcpy (SectorBuffer + TC_MAX_MBR_BOOT_CODE_SIZE, mbrPartTable, sizeof (mbrPartTable));
}
// Volume header
if (i == TC_BOOT_VOLUME_HEADER_SECTOR)
{
if (selection == RestoreTrueCryptLoader)
continue;
if (selection == RestoreVolumeHeader)
{
while (true)
{
Password password;
byte exitKey = AskPassword (password);
if (exitKey != TC_BIOS_KEY_ENTER)
goto abort;
CRYPTO_INFO *cryptoInfo;
CopyMemory (SectorBuffer, TC_BOOT_LOADER_BUFFER_SEGMENT, 0, TC_LB_SIZE);
ReleaseSectorBuffer();
// Restore volume header only if the current one cannot be used
if (OpenVolume (TC_FIRST_BIOS_DRIVE, password, &cryptoInfo, nullptr, false, true))
{
Print ("Original header preserved.\r\n");
crypto_close (cryptoInfo);
goto err;
}
AcquireSectorBuffer();
CopyMemory (TC_BOOT_LOADER_BUFFER_SEGMENT, 0, SectorBuffer, TC_LB_SIZE);
if (ReadVolumeHeader (TRUE, (char *) SectorBuffer, &password, &cryptoInfo, nullptr) == 0)
{
crypto_close (cryptoInfo);
break;
}
Print ("Incorrect password.\r\n\r\n");
}
}
}
if (!writeConfirmed && !AskYesNo ("Modify drive 0"))
goto abort;
writeConfirmed = true;
if (WriteSectors (SectorBuffer, TC_FIRST_BIOS_DRIVE, sector, 1) != BiosResultSuccess)
goto err;
}
done:
switch (selection)
{
case RestoreTrueCryptLoader:
Print ("TrueCrypt Boot Loader");
break;
case RestoreVolumeHeader:
Print ("Header");
break;
case RestoreOriginalSystemLoader:
Print ("System loader");
break;
}
Print (" restored.\r\n");
err: GetKeyboardChar();
abort: ReleaseSectorBuffer();
}
}
#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
#ifndef DEBUG
extern "C" void _acrtused () { } // Required by linker
#endif
void main ()
{
__asm mov BootLoaderDrive, dl
__asm mov BootSectorFlags, dh
#ifdef TC_BOOT_TRACING_ENABLED
InitDebugPort();
#endif
#ifdef TC_BOOT_STACK_CHECKING_ENABLED
InitStackChecker();
#endif
#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
ReadBootSectorUserConfiguration();
#endif
InitVideoMode();
InitScreen();
// Determine boot drive
BootDrive = BootLoaderDrive;
if (BootDrive < TC_FIRST_BIOS_DRIVE)
BootDrive = TC_FIRST_BIOS_DRIVE;
// Query boot drive geometry
if (GetDriveGeometry (BootDrive, BootDriveGeometry, true) != BiosResultSuccess)
{
BootDrive = TC_FIRST_BIOS_DRIVE;
if (GetDriveGeometry (BootDrive, BootDriveGeometry) == BiosResultSuccess)
BootDriveGeometryValid = TRUE;
}
else
BootDriveGeometryValid = TRUE;
#ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
// Check whether the user is not using the Rescue Disk to create a hidden system
if (ReadWriteMBR (false, BootDrive, true) == BiosResultSuccess
&& *(uint32 *) (SectorBuffer + 6) == 0x65757254
&& *(uint32 *) (SectorBuffer + 10) == 0x70797243
&& (SectorBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) != TC_HIDDEN_OS_CREATION_PHASE_NONE)
{
PrintError ("It appears you are creating a hidden OS.");
if (AskYesNo ("Is this correct"))
{
Print ("Please remove the Rescue Disk from the drive and restart.");
while (true);
}
}
#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
// Main menu
while (true)
{
byte exitKey;
InitScreen();
#ifndef TC_WINDOWS_BOOT_RESCUE_DISK_MODE
// Hidden system setup
byte hiddenSystemCreationPhase = BootSectorFlags & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
if (hiddenSystemCreationPhase != TC_HIDDEN_OS_CREATION_PHASE_NONE)
{
PreventNormalSystemBoot = true;
PrintMainMenu();
if (hiddenSystemCreationPhase == TC_HIDDEN_OS_CREATION_PHASE_CLONING)
{
if (CopyActivePartitionToHiddenVolume (BootDrive, exitKey))
{
BootSectorFlags = (BootSectorFlags & ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE) | TC_HIDDEN_OS_CREATION_PHASE_WIPING;
UpdateBootSectorConfiguration (BootLoaderDrive);
}
else if (exitKey == TC_BIOS_KEY_ESC)
goto bootMenu;
else
continue;
}
}
else
PrintMainMenu();
exitKey = BootEncryptedDrive();
#else // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
PrintMainMenu();
exitKey = BootEncryptedDrive();
if (exitKey == TC_MENU_KEY_REPAIR)
{
RepairMenu();
continue;
}
#endif // TC_WINDOWS_BOOT_RESCUE_DISK_MODE
bootMenu:
if (!PreventBootMenu)
BootMenu();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -