Skip to content

Commit

Permalink
add Windows bootloader detection to better report on the reasons for …
Browse files Browse the repository at this point in the history
…a Windows boot failure

* Unfortunately, Microsoft designed their Windows UEFI bootloaders to not halt and report an
  explicit error when a boot issue arises, but instead *silently* hand over to the next
  available boot device (which is accomplished by having the UEFI bootloader return error
  code EFI_NO_MAPPING).
* This leaves many users very confused as to why their Windows installation media will not
  boot, even more so in light of the BlackLotus Microsoft bootloader revocation, where users
  will get EFI_NO_MAPPING silently being returned when the UEFI lock is enabled and they
  attempt to boot using a pre-2023.05 Windows bootloader.
* Because of this, we attempt to detect Windows bootloaders (which are all compiled from
  binaries containing a 'bootmgr.dll' string) and report a more explicit error and potential
  cause when a Windows UEFI bootloader returns EFI_NO_MAPPING.
  • Loading branch information
pbatard committed Sep 5, 2023
1 parent eebbe49 commit b9adb76
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,14 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE BaseImageHandle, EFI_SYSTEM_TABLE *SystemT
EFI_FILE_SYSTEM_VOLUME_LABEL* VolumeInfo;
EFI_FILE_HANDLE Root;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
// We'll search for "bootmgr.dll" in UEFI bootloaders to identify Windows
// bootloaders, but we don't want to match our own bootloader in the process.
// So we use a modifiable string buffer where the first character is not set.
CHAR8 BootMgrName[] = "_ootmgr.dll", BootMgrNameFirstLetter = 'b';
CHAR8* Buffer;
INTN SecureBootStatus;
UINTN Index, FsType = 0, Try, Event, HandleCount = 0, Size;
BOOLEAN SameDevice;
BOOLEAN SameDevice, WindowsBootMgr = FALSE;

#if defined(_GNU_EFI)
InitializeLib(BaseImageHandle, SystemTable);
Expand Down Expand Up @@ -451,9 +455,35 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE BaseImageHandle, EFI_SYSTEM_TABLE *SystemT
goto out;
}

// Look for a "bootmgr.dll" string in the loaded image to identify a Windows bootloader.
BootMgrName[0] = BootMgrNameFirstLetter;
Status = gBS->OpenProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid,
(VOID**)&LoadedImage, MainImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)) {
PrintWarning(L" Unable to inspect loaded executable");
} else for (Index = 0x40; Index < LoadedImage->ImageSize - sizeof(BootMgrName); Index++) {
if (CompareMem((CHAR8*)((UINTN)LoadedImage->ImageBase + Index),
BootMgrName, sizeof(BootMgrName)) == 0) {
WindowsBootMgr = TRUE;
PrintInfo(L"Starting Microsoft Windows bootmgr...");
break;
}
}

Status = gBS->StartImage(ImageHandle, NULL, NULL);
if (EFI_ERROR(Status))
PrintError(L" Start failure");
if (EFI_ERROR(Status)) {
// Windows bootmgr simply returns EFI_NO_MAPPING on any internal error or security
// violation, instead of halting and explicitly reporting the issue, leaving many
// users extremely confused as to why their media did not boot. This can happen, for
// instance, if the machine has had the BlackLotus UEFI lock enabled and the user
// attempts to boot a pre 2023.05 version of the Windows installers.
// We therefore take it upon ourselves to report what Windows bootmgr will not report.
if (Status == EFI_NO_MAPPING && WindowsBootMgr) {
SetText(TEXT_RED); Print(L"[FAIL]"); DefText();
Print(L" Windows bootmgr encountered a security validation or internal error\n");
} else
PrintError(L" Start failure");
}

out:
SafeFree(ParentDevicePath);
Expand Down

0 comments on commit b9adb76

Please sign in to comment.