From 9741c9209d0deedcc5d60434e5e7df3c531ff192 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Fri, 22 Nov 2019 00:08:41 +0100 Subject: Windows: Add new registry flags for SystemFavoritesService to control updating of EFI BIOS boot menu on shutdown. This will help better manage multi-boot scenarios where we should not mess up with boot order (e.g. grub2 case) --- src/Common/BootEncryption.cpp | 50 +++++++++++++++++++++++++++---------------- src/Common/BootEncryption.h | 8 +++++-- src/Mount/Mount.c | 11 ++++++++-- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/Common/BootEncryption.cpp b/src/Common/BootEncryption.cpp index 583a8cb2..3ad7320c 100644 --- a/src/Common/BootEncryption.cpp +++ b/src/Common/BootEncryption.cpp @@ -1030,7 +1030,7 @@ namespace VeraCrypt static EfiBoot EfiBootInst; - BootEncryption::BootEncryption (HWND parent, bool postOOBE, bool setBootNext) + BootEncryption::BootEncryption (HWND parent, bool postOOBE, bool setBootEntry, bool forceFirstBootEntry, bool setBootNext) : DriveConfigValid (false), ParentWindow (parent), RealSystemDriveSizeValid (false), @@ -1042,7 +1042,9 @@ namespace VeraCrypt SelectedPrfAlgorithmId (0), VolumeHeaderValid (false), PostOOBEMode (postOOBE), - SetBootNext (setBootNext) + SetBootNext (setBootNext), + SetBootEntry (setBootEntry), + ForceFirstBootEntry (forceFirstBootEntry) { HiddenOSCandidatePartition.IsGPT = FALSE; HiddenOSCandidatePartition.Number = (size_t) -1; @@ -2682,7 +2684,7 @@ namespace VeraCrypt } } - void EfiBoot::SetStartExec(wstring description, wstring execPath, bool setBootNext, uint16 statrtOrderNum , wchar_t* type, uint32 attr) { + void EfiBoot::SetStartExec(wstring description, wstring execPath, bool setBootEntry, bool forceFirstBootEntry, bool setBootNext, uint16 statrtOrderNum , wchar_t* type, uint32 attr) { SetPrivilege(SE_SYSTEM_ENVIRONMENT_NAME, TRUE); // Check EFI if (!IsEfiBoot()) { @@ -2799,27 +2801,37 @@ namespace VeraCrypt } } - // Create new entry if absent - if (startOrderNumPos == UINT_MAX) { - if (bDeviceInfoValid) - { - for (uint32 i = startOrderLen / 2; i > 0; --i) { + if (setBootEntry) + { + // Create new entry if absent + if (startOrderNumPos == UINT_MAX) { + if (bDeviceInfoValid) + { + if (forceFirstBootEntry) + { + for (uint32 i = startOrderLen / 2; i > 0; --i) { + startOrder[i] = startOrder[i - 1]; + } + startOrder[0] = statrtOrderNum; + } + else + { + startOrder[startOrderLen/2] = statrtOrderNum; + } + startOrderLen += 2; + startOrderUpdate = true; + } + } else if ((startOrderNumPos > 0) && forceFirstBootEntry) { + for (uint32 i = startOrderNumPos; i > 0; --i) { startOrder[i] = startOrder[i - 1]; } startOrder[0] = statrtOrderNum; - startOrderLen += 2; startOrderUpdate = true; } - } else if (startOrderNumPos > 0) { - for (uint32 i = startOrderNumPos; i > 0; --i) { - startOrder[i] = startOrder[i - 1]; - } - startOrder[0] = statrtOrderNum; - startOrderUpdate = true; - } - if (startOrderUpdate) { - SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen); + if (startOrderUpdate) { + SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen); + } } if (setBootNext) @@ -3333,7 +3345,7 @@ namespace VeraCrypt // restore boot menu entry in case of PostOOBE if (PostOOBEMode) - EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi", SetBootNext); + EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi", SetBootEntry, ForceFirstBootEntry, SetBootNext); if (EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc")) { diff --git a/src/Common/BootEncryption.h b/src/Common/BootEncryption.h index a94f1918..decacb8b 100644 --- a/src/Common/BootEncryption.h +++ b/src/Common/BootEncryption.h @@ -209,7 +209,7 @@ namespace VeraCrypt bool IsEfiBoot(); void DeleteStartExec(uint16 statrtOrderNum = 0xDC5B, wchar_t* type = NULL); - void SetStartExec(wstring description, wstring execPath, bool setBootNext = true, uint16 statrtOrderNum = 0xDC5B, wchar_t* type = NULL, uint32 attr = 1); + void SetStartExec(wstring description, wstring execPath, bool setBootEntry = true, bool forceFirstBootEntry = true, bool setBootNext = true, uint16 statrtOrderNum = 0xDC5B, wchar_t* type = NULL, uint32 attr = 1); void SaveFile(const wchar_t* name, byte* data, DWORD size); void GetFileSize(const wchar_t* name, unsigned __int64& size); void ReadFile(const wchar_t* name, byte* data, DWORD size); @@ -240,7 +240,7 @@ namespace VeraCrypt class BootEncryption { public: - BootEncryption (HWND parent, bool postOOBE = false, bool setBootNext = false); + BootEncryption (HWND parent, bool postOOBE = false, bool setBootEntry = true, bool forceFirstBootEntry = true, bool setBootNext = false); ~BootEncryption (); enum FilterType @@ -353,6 +353,8 @@ namespace VeraCrypt bool VolumeHeaderValid; bool PostOOBEMode; bool SetBootNext; + bool SetBootEntry; + bool ForceFirstBootEntry; }; } @@ -371,6 +373,8 @@ namespace VeraCrypt #define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_UPDATE_LOADER 0x1 #define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_FORCE_SET_BOOTNEXT 0x2 +#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_SET_BOOTENTRY 0x4 +#define VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_FORCE_FIRST_BOOTENTRY 0x8 #define VC_WINDOWS_UPGRADE_POSTOOBE_CMDLINE_OPTION L"/PostOOBE" diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 9ba4ae86..7f677580 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -9436,9 +9436,16 @@ static DWORD WINAPI SystemFavoritesServiceCtrlHandler ( DWORD dwControl, { // re-install our bootloader again in case the update process has removed it. bool bForceSetNextBoot = false; - if (BootEncObj->ReadServiceConfigurationFlags () & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_FORCE_SET_BOOTNEXT) + bool bSetBootentry = true; + bool bForceFirstBootEntry = true; + uint32 flags = BootEncObj->ReadServiceConfigurationFlags (); + if (flags & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_FORCE_SET_BOOTNEXT) bForceSetNextBoot = true; - BootEncryption bootEnc (NULL, true, bForceSetNextBoot); + if (flags & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_SET_BOOTENTRY) + bSetBootentry = false; + if (flags & VC_SYSTEM_FAVORITES_SERVICE_CONFIG_DONT_FORCE_FIRST_BOOTENTRY) + bForceFirstBootEntry = false; + BootEncryption bootEnc (NULL, true, bSetBootentry, bForceFirstBootEntry, bForceSetNextBoot); bootEnc.InstallBootLoader (true); } } -- cgit v1.2.3