From 475de1dadacd6605bcf1783004f40d218be60d70 Mon Sep 17 00:00:00 2001 From: longpanda Date: Thu, 25 Jun 2026 19:23:48 +0800 Subject: [PATCH] Fix the boot issue with old UEFI version firmware when secure boot is disabled. --- .../MdeModulePkg/Application/Ventoy/Ventoy.c | 53 ++++- .../Application/VtoyShim/VtoyShim.c | 190 +++++++++++++----- .../Application/VtoyShim/VtoyShim.h | 13 +- .../Application/VtoyUtil/VtoyUtil.c | 54 ++++- .../grub-2.04/grub-core/ventoy/ventoy.c | 15 ++ 5 files changed, 241 insertions(+), 84 deletions(-) diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c index 3ca80f62..b316605f 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c @@ -1232,25 +1232,58 @@ EFI_STATUS EFIAPI ventoy_boot(IN EFI_HANDLE ImageHandle) } #if defined (MDE_CPU_X64) -STATIC BOOLEAN EFIAPI CheckVtoyShim(VOID) + +STATIC BOOLEAN EFIAPI IsSecureBootEnabled(VOID) { UINT8 SecureBoot = 0; UINTN DataSize; EFI_STATUS Status; - EFI_GUID Guid = VTOY_SHIM_POLICY_GUID; - VOID *Prot = NULL; DataSize = sizeof(SecureBoot); Status = gST->RuntimeServices->GetVariable(L"SecureBoot", &gEfiGlobalVariableGuid, NULL, &DataSize, &SecureBoot); - if (!EFI_ERROR(Status) && SecureBoot) + if (EFI_ERROR(Status)) { - Status = gBS->LocateProtocol(&Guid, NULL, (VOID**)&Prot); - if (EFI_ERROR(Status)) - { - VtoyDebug("Failed to locate Vtoy Shim Protocol %lx\r\n", Status); - return FALSE; - } + return FALSE; + } + + return SecureBoot ? TRUE : FALSE; +} + +STATIC BOOLEAN EFIAPI IsSetupMode(VOID) +{ + UINT8 SetupMode = 0; + UINTN DataSize; + EFI_STATUS Status; + + DataSize = sizeof(SetupMode); + Status = gST->RuntimeServices->GetVariable(L"SetupMode", &gEfiGlobalVariableGuid, NULL, + &DataSize, &SetupMode); + if (EFI_ERROR(Status)) + { + return FALSE; + } + + return SetupMode ? TRUE : FALSE; +} + +STATIC BOOLEAN EFIAPI CheckVtoyShim(VOID) +{ + EFI_STATUS Status; + EFI_GUID Guid = VTOY_SHIM_POLICY_GUID; + VOID *Prot = NULL; + + /* If secure boot is not enabled or in SetupMode, nothing needed */ + if (!IsSecureBootEnabled() || IsSetupMode()) + { + return TRUE; + } + + Status = gBS->LocateProtocol(&Guid, NULL, (VOID**)&Prot); + if (EFI_ERROR(Status)) + { + VtoyDebug("Failed to locate Vtoy Shim Protocol %lx\r\n", Status); + return FALSE; } return TRUE; diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.c index fd89e53d..c4f574c7 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.c @@ -35,14 +35,16 @@ #define CUR_SBAT_VER 1 STATIC EFI_GUID gVtoySbatGUID = { 0xf755068a, 0xe04f, 0x452b, { 0x9d, 0x6d, 0x7c, 0x55, 0x96, 0xb3, 0xc0, 0x7d }}; -STATIC EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *gDpToText = NULL; -STATIC EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *gTextToDp = NULL; +STATIC EFI_GUID gShimLockGUID = SHIM_LOCK_GUID; STATIC EFI_SECURITY_FILE_AUTHENTICATION_STATE gSysSecFileAuth = NULL; STATIC EFI_SECURITY2_FILE_AUTHENTICATION gSysSec2FileAuth = NULL; STATIC BOOLEAN gVtoyByPassSB = FALSE; /* must be FALSE by default for revoke */ STATIC VTOY_SHIM gVtoyShimProtocol; STATIC EFI_HANDLE gVtoyShimProtHandle; -STATIC SHIM_LOCK *gShimLock = NULL; +STATIC SHIM_LOCK gShimLock; + +STATIC EFI_EXIT_BOOT_SERVICES gSysExitBootServices = NULL; +STATIC EFI_GET_VARIABLE gSysGetVariable = NULL; STATIC VOID EFIAPI VtoyLog(CONST CHAR16 *Format, ...) { @@ -66,7 +68,7 @@ STATIC VOID EFIAPI DumpDevicePath(const EFI_DEVICE_PATH_PROTOCOL *DevicePath) { CHAR16 *DPStr = NULL; - DPStr = gDpToText->ConvertDevicePathToText(DevicePath, TRUE, TRUE); + DPStr = ConvertDevicePathToText(DevicePath, TRUE, TRUE); if (DPStr) { vLog(L"%s", DPStr); @@ -95,8 +97,11 @@ STATIC VOID EFIAPI ShowSBWarning(BOOLEAN Reboot, const EFI_DEVICE_PATH_PROTOCOL if (Reboot) { vLog(L"\r\n###### Press Enter to reboot... ######"); - gST->ConIn->Reset(gST->ConIn, FALSE); - gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &Index); + if (gST->ConIn) + { + gST->ConIn->Reset(gST->ConIn, FALSE); + gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &Index); + } gRT->ResetSystem(EfiResetWarm, EFI_SECURITY_VIOLATION, 0, NULL); } else @@ -129,7 +134,6 @@ STATIC VOID * EFIAPI FindShimFuncAddr(UINT64 FuncOffset) } } - EFI_STATUS EFIAPI LaunchRealGrub(EFI_HANDLE ImageHandle, CONST CHAR16 *FileName) { EFI_STATUS Status; @@ -156,7 +160,7 @@ EFI_STATUS EFIAPI LaunchRealGrub(EFI_HANDLE ImageHandle, CONST CHAR16 *FileName) goto END; } - DevDpStr = gDpToText->ConvertDevicePathToText(DeviceDP, FALSE, TRUE); + DevDpStr = ConvertDevicePathToText(DeviceDP, FALSE, TRUE); if (!DevDpStr) { vLog(L"Failed to convert device path to text"); @@ -175,7 +179,7 @@ EFI_STATUS EFIAPI LaunchRealGrub(EFI_HANDLE ImageHandle, CONST CHAR16 *FileName) UnicodeSPrint(NewDpStr, BufferSize, L"%s/EFI/BOOT/%s", DevDpStr, FileName); - TargetDp = gTextToDp->ConvertTextToDevicePath(NewDpStr); + TargetDp = ConvertTextToDevicePath(NewDpStr); if (!TargetDp) { vLog(L"Failed to convert new text <%s> to device path", NewDpStr); @@ -200,9 +204,9 @@ EFI_STATUS EFIAPI LaunchRealGrub(EFI_HANDLE ImageHandle, CONST CHAR16 *FileName) END: - CheckBSFreePool(DevDpStr); + CheckFreePool(DevDpStr); CheckFreePool(NewDpStr); - CheckBSFreePool(TargetDp); + CheckFreePool(TargetDp); return Status; } @@ -243,7 +247,7 @@ STATIC EFI_STATUS EFIAPI ReadAuthFile goto END; } - DpStr = gDpToText->ConvertDevicePathToText(DevPath, FALSE, TRUE); + DpStr = ConvertDevicePathToText(DevPath, FALSE, TRUE); if (!DpStr) { Status = EFI_OUT_OF_RESOURCES; @@ -311,7 +315,7 @@ END: } CheckFreePool(TmpPath); - CheckBSFreePool(DpStr); + CheckFreePool(DpStr); if (EFI_ERROR(Status)) { @@ -332,7 +336,7 @@ STATIC BOOLEAN VtoyCheckRevoke(VOID *Buffer, UINTN Size) UINT32 uiVer = 0; EFI_IMAGE_DOS_HEADER *DosHead = (EFI_IMAGE_DOS_HEADER *)Buffer; - if (Size > sizeof(EFI_IMAGE_DOS_HEADER)) + if (Size > sizeof(EFI_IMAGE_DOS_HEADER) && DosHead->e_magic == 0x5A4D) { if (CompareMem(DosHead->e_res2, &gVtoySbatGUID, 16) == 0) { @@ -386,12 +390,12 @@ STATIC EFI_STATUS EFIAPI SecurityPolicyAuth * Use shim verify API. * If it's OK, it may be signed with a MOK key. (e.g. Ventoy EFI files) */ - if (gShimLock && gShimLock->Verify) + if (gShimLock.Verify) { Status = ReadAuthFile(DevicePathConst, &Buffer, &Size); if (!EFI_ERROR(Status)) { - Status = gShimLock->Verify(Buffer, Size); + Status = gShimLock.Verify(Buffer, Size); if (!EFI_ERROR(Status)) { bRevokeChkOK = VtoyCheckRevoke(Buffer, Size); @@ -448,11 +452,11 @@ STATIC EFI_STATUS EFIAPI Security2PolicyAuth * Use shim verify API. * If it's OK, it may be signed with a MOK key. (e.g. Ventoy EFI files) */ - if (gShimLock && gShimLock->Verify) + if (gShimLock.Verify) { if (FileBuffer && FileSize > 0 && FileSize < 0xFFFFFFFFUL) { - Status = gShimLock->Verify(FileBuffer, (UINT32)FileSize); + Status = gShimLock.Verify(FileBuffer, (UINT32)FileSize); if (!EFI_ERROR(Status)) { bRevokeChkOK = VtoyCheckRevoke(FileBuffer, FileSize); @@ -522,13 +526,13 @@ STATIC VOID EFIAPI UnHookSecurityPolicy(VOID) return; } - if (Security2 && gSysSec2FileAuth) + if (Security2 && gSysSec2FileAuth && Security2->FileAuthentication == Security2PolicyAuth) { Security2->FileAuthentication = gSysSec2FileAuth; gSysSec2FileAuth = NULL; } - if (Security && gSysSecFileAuth) + if (Security && gSysSecFileAuth && Security->FileAuthenticationState == SecurityPolicyAuth) { Security->FileAuthenticationState = gSysSecFileAuth; gSysSecFileAuth = NULL; @@ -599,47 +603,38 @@ STATIC BOOLEAN EFIAPI IsSecureBootEnabled(VOID) return SecureBoot ? TRUE : FALSE; } -STATIC EFI_STATUS EFIAPI EnvInit(VOID) +STATIC BOOLEAN EFIAPI IsSetupMode(VOID) { - EFI_STATUS Status; + UINT8 SetupMode = 0; + UINTN DataSize; + EFI_STATUS Status; - Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID**)&gDpToText); - if (EFI_ERROR(Status) || !gDpToText || !gDpToText->ConvertDevicePathToText) + DataSize = sizeof(SetupMode); + Status = gST->RuntimeServices->GetVariable(L"SetupMode", &gEfiGlobalVariableGuid, NULL, + &DataSize, &SetupMode); + if (EFI_ERROR(Status)) { - vLog(L"Failed to locate PathToText Protocol %lx", Status); - return Status; + return FALSE; } - Status = gBS->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID**)&gTextToDp); - if (EFI_ERROR(Status) || !gTextToDp || !gTextToDp->ConvertTextToDevicePath) - { - vLog(L"Failed to locate PathFromText Protocol %lx", Status); - return Status; - } - - return EFI_SUCCESS; + return SetupMode ? TRUE : FALSE; } - -EFI_STATUS EFIAPI VtoyShimEfiMain +STATIC EFI_STATUS EFIAPI ShimEfiMain ( IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable + IN EFI_SYSTEM_TABLE *SystemTable, + IN BOOLEAN IsSecureBoot, + IN BOOLEAN IsSetup ) { EFI_STATUS Status; - EFI_GUID Guid = SHIM_LOCK_GUID; - unhook_system_services_pf Func = NULL; + SHIM_LOCK *ShimLock = NULL; + shim_void_func_pf Func1 = NULL; + shim_void_func_pf Func2 = NULL; - Status = EnvInit(); - if (EFI_ERROR(Status)) - { - vErr(L"Failed to prepare env"); - return Status; - } - - /* If secure boot is not enabled, nothing needed, just launch Ventoy grub */ - if (!IsSecureBootEnabled()) + /* If secure boot is not enabled or in SetupMode, nothing needed, just launch Ventoy grub */ + if (!IsSecureBoot || IsSetup) { Status = LaunchRealGrub(ImageHandle, REAL_GRUB_FILE); if (EFI_ERROR(Status)) @@ -649,13 +644,18 @@ EFI_STATUS EFIAPI VtoyShimEfiMain return Status; } - Status = gBS->LocateProtocol(&Guid, NULL, (VOID**)&gShimLock); - if (EFI_ERROR(Status) || !gShimLock) + /* We must be launched by shim */ + Status = gBS->LocateProtocol(&gShimLockGUID, NULL, (VOID**)&ShimLock); + if (EFI_ERROR(Status) || !ShimLock) { vErr(L"Failed to locate SHIM LOCK Protocol %lx", Status); return Status; } + /* Backup shim Lock because we will remove it later */ + gShimLock.Verify = ShimLock->Verify; + gShimLock.Hash = ShimLock->Hash; + gShimLock.Context = ShimLock->Context; Status = InstallVtoyShimProtocol(); if (EFI_ERROR(Status)) @@ -679,15 +679,17 @@ EFI_STATUS EFIAPI VtoyShimEfiMain * It may break in future versions of shim, and a better approach may exist. * */ - Func = FindShimFuncAddr(NM_UNHOOK_SYSTEM_SERVICES_OFFSET); - if (!Func) + Func1 = FindShimFuncAddr(NM_UNHOOK_SYSTEM_SERVICES_OFFSET); + Func2 = FindShimFuncAddr(NM_UNINSTALL_SHIM_PROTOCOLS_OFFSET); + if (!Func1 || !Func2) { - vErr(L"Can not find shim unhook_system_services"); + vErr(L"Can not find shim func %p %p", Func1, Func2); Status = EFI_NOT_FOUND; goto END; } - Func(); /* call shim unhook_system_services() */ + Func1(); /* call shim unhook_system_services() */ + Func2(); /* call shim uninstall_shim_protocols() */ /* Hook the system security policy */ @@ -716,3 +718,83 @@ END: return Status; } +STATIC EFI_STATUS EFIAPI VtoyExitBootServices +( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey +) +{ + UnHookSecurityPolicy(); + UnInstallVtoyShimProtocol(); + + gST->RuntimeServices->GetVariable = gSysGetVariable; + gBS->ExitBootServices = gSysExitBootServices; + + return gSysExitBootServices(ImageHandle, MapKey); +} + +EFI_STATUS EFIAPI VtoyGetVariable +( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL +) +{ + BOOLEAN bChk = FALSE; + EFI_STATUS Status; + + if (gVtoyByPassSB && VariableName && VendorGuid && DataSize && Data && (*DataSize) > 0) + { + bChk = TRUE; + } + + Status = gSysGetVariable(VariableName, VendorGuid, Attributes, DataSize, Data); + if (bChk && (!EFI_ERROR(Status))) + { + if (CompareMem(&gShimLockGUID, VendorGuid, 16) == 0 && + StrCmp(VariableName, L"MokSBState") == 0) + { + *(UINT8 *)Data = 1; + } + } + + return Status; +} + + +EFI_STATUS EFIAPI VtoyShimEfiMain +( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable +) +{ + BOOLEAN IsSetup = FALSE; + BOOLEAN IsSecureBoot = FALSE; + EFI_STATUS Status; + + IsSetup = IsSetupMode(); + IsSecureBoot = IsSecureBootEnabled(); + + if (!IsSecureBoot || IsSetup) + { + Status = ShimEfiMain(ImageHandle, SystemTable, IsSecureBoot, IsSetup); + } + else + { + gSysExitBootServices = gBS->ExitBootServices; + gBS->ExitBootServices = VtoyExitBootServices; + + gSysGetVariable = gST->RuntimeServices->GetVariable; + gST->RuntimeServices->GetVariable = VtoyGetVariable; + + Status = ShimEfiMain(ImageHandle, SystemTable, IsSecureBoot, IsSetup); + + gBS->ExitBootServices = gSysExitBootServices; + gST->RuntimeServices->GetVariable = gSysGetVariable; + } + + return Status; +} + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.h b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.h index 052cbd5f..7c7b6c2c 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.h +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyShim/VtoyShim.h @@ -66,19 +66,21 @@ typedef struct _SHIM_IMAGE_LOADER { EFI_IMAGE_UNLOAD UnloadImage; } SHIM_IMAGE_LOADER; -typedef VOID (*unhook_system_services_pf)(VOID); +typedef VOID (*shim_void_func_pf)(VOID); /* * The two offset here are extract from the shim file which used in Ventoy. * nm BOOTX64.EFI | grep shim_load_image * nm BOOTX64.EFI | grep unhook_system_services + * nm BOOTX64.EFI | grep uninstall_shim_protocols * * It means that they must be updated every time Ventoy update the shim file. * */ #define NM_SHIM_LOAD_IMAGE_OFFSET 0x2dc12 #define NM_UNHOOK_SYSTEM_SERVICES_OFFSET 0x2e278 +#define NM_UNINSTALL_SHIM_PROTOCOLS_OFFSET 0x26264 @@ -95,15 +97,6 @@ do { \ }\ } while (0) -#define CheckBSFreePool(p) \ -do { \ - if (p) { \ - gBS->FreePool(p); \ - (p) = NULL; \ - }\ -} while (0) - - #define VTOY_SHIM_POLICY_GUID {0x90a29d14, 0x3968, 0x48fe, { 0x85, 0x81, 0x6b, 0x7f, 0x7d, 0xc4, 0x70, 0x55 }}; diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c index f5ff0066..cfaf43f8 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VtoyUtil/VtoyUtil.c @@ -146,25 +146,59 @@ STATIC EFI_STATUS ParseCmdline(IN EFI_HANDLE ImageHandle) } #if defined (MDE_CPU_X64) -STATIC BOOLEAN EFIAPI CheckVtoyShim(VOID) + +STATIC BOOLEAN EFIAPI IsSecureBootEnabled(VOID) { UINT8 SecureBoot = 0; UINTN DataSize; EFI_STATUS Status; - EFI_GUID Guid = VTOY_SHIM_POLICY_GUID; - VOID *Prot = NULL; DataSize = sizeof(SecureBoot); Status = gST->RuntimeServices->GetVariable(L"SecureBoot", &gEfiGlobalVariableGuid, NULL, &DataSize, &SecureBoot); - if (!EFI_ERROR(Status) && SecureBoot) + if (EFI_ERROR(Status)) { - Status = gBS->LocateProtocol(&Guid, NULL, (VOID**)&Prot); - if (EFI_ERROR(Status)) - { - gST->ConOut->OutputString(gST->ConOut, L"Can not locate Vtoy Shim\r\n"); - return FALSE; - } + return FALSE; + } + + return SecureBoot ? TRUE : FALSE; +} + +STATIC BOOLEAN EFIAPI IsSetupMode(VOID) +{ + UINT8 SetupMode = 0; + UINTN DataSize; + EFI_STATUS Status; + + DataSize = sizeof(SetupMode); + Status = gST->RuntimeServices->GetVariable(L"SetupMode", &gEfiGlobalVariableGuid, NULL, + &DataSize, &SetupMode); + if (EFI_ERROR(Status)) + { + return FALSE; + } + + return SetupMode ? TRUE : FALSE; +} + + +STATIC BOOLEAN EFIAPI CheckVtoyShim(VOID) +{ + EFI_STATUS Status; + EFI_GUID Guid = VTOY_SHIM_POLICY_GUID; + VOID *Prot = NULL; + + /* If secure boot is not enabled or in SetupMode, nothing needed */ + if (!IsSecureBootEnabled() || IsSetupMode()) + { + return TRUE; + } + + Status = gBS->LocateProtocol(&Guid, NULL, (VOID**)&Prot); + if (EFI_ERROR(Status)) + { + gST->ConOut->OutputString(gST->ConOut, L"Can not locate Vtoy Shim\r\n"); + return FALSE; } return TRUE; diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c index c442b715..59cd096b 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c @@ -359,12 +359,27 @@ int ventoy_set_sb_policy(void) static void ventoy_get_uefi_sb(void) { + grub_uint8_t secure_boot = 0; + grub_uint8_t setup_mode = 0; grub_uint8_t *var = NULL; grub_size_t size = 0; grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; var = grub_efi_get_variable("SecureBoot", &global, &size); if (var && size == 1 && *var == 1) + { + secure_boot = 1; + } + grub_check_free(var); + + size = 0; + var = grub_efi_get_variable("SetupMode", &global, &size); + if (var && size == 1 && *var == 1) + { + setup_mode = 1; + } + + if (secure_boot == 1 && setup_mode == 0) { g_sys_sb = 1; }