From ae5935875efbed3b6238a1896e81430a5780e1f0 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Wed, 16 Sep 2015 08:24:21 -0400 Subject: [PATCH] PRELIMINARY workaround for Shim 0.8 bug. --- NEWS.txt | 9 +++++ docs/refind/installing.html | 6 ++-- refind/global.h | 69 +++++++++++++++++++------------------ refind/lib.c | 1 + refind/main.c | 24 ++++++++++--- 5 files changed, 68 insertions(+), 41 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 1ffbed4..c049f13 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,12 @@ +0.9.2 (9/??/2015): +------------------ + +- Implemented a workaround for a bug in Shim 0.8 that prevented + authentication of more than one binary. If any filesystem drivers were + installed, the first one would be verified, leaving rEFInd to be unable + to launch anything else unless it was signed by a key in the computer's + main Secure Boot db list. + 0.9.1 (9/13/2015): ------------------ diff --git a/docs/refind/installing.html b/docs/refind/installing.html index 6615d19..4bd53f8 100644 --- a/docs/refind/installing.html +++ b/docs/refind/installing.html @@ -17,7 +17,7 @@ href="mailto:rodsmith@rodsbooks.com">rodsmith@rodsbooks.com

Originally written: 3/14/2012; last Web page update: -9/13/2015, referencing rEFInd 0.9.1

+9/14/2015, referencing rEFInd 0.9.1

This Web page is provided free of charge and with no annoying outside ads; however, I did take time to prepare it, and Web hosting does cost money. If you find this Web page useful, please consider making a small donation to help keep this site up and running. Thanks!

@@ -258,7 +258,7 @@ $ sudo apt-get install refind

Quick install.sh Instructions

- +

By default, the install.sh script installs rEFInd to your disk's ESP. Under Mac OS X, you can instead install rEFInd to your current OS X boot partition by passing the script the --notesp option, or to a non-boot HFS+ partition by using the --ownhfs devicefile option. Under either OS, you can install to something other than the currently-running OS by using the --root /mountpoint option. (See Table 1 for details.)

@@ -514,7 +514,7 @@ Filesystem 1K-blocks Used Available Use% Mounted on

Installing rEFInd Manually Using Mac OS X

- +

Before installing rEFInd on a Mac, you must determine whether it uses a 32-bit or 64-bit EFI implementation. Most Intel-based Macs have 64-bit EFIs, so you should use the refind_x64.efi file with them; but very early Intel-based Macs have 32-bit EFIs (and sometimes 32-bit CPUs), which require the refind_ia32.efi file. You can determine whether your Mac needs the x86-64 or IA32 build by typing the following command in a Mac Terminal window:

diff --git a/refind/global.h b/refind/global.h index e8d57eb..875fc20 100644 --- a/refind/global.h +++ b/refind/global.h @@ -272,40 +272,41 @@ typedef struct { } LEGACY_ENTRY; typedef struct { - BOOLEAN TextOnly; - BOOLEAN ScanAllLinux; - BOOLEAN DeepLegacyScan; - BOOLEAN EnableAndLockVMX; - BOOLEAN FoldLinuxKernels; - UINTN RequestedScreenWidth; - UINTN RequestedScreenHeight; - UINTN BannerBottomEdge; - UINTN RequestedTextMode; - UINTN Timeout; - UINTN HideUIFlags; - UINTN MaxTags; // max. number of OS entries to show simultaneously in graphics mode - UINTN GraphicsFor; - UINTN LegacyType; - UINTN ScanDelay; - UINTN ScreensaverTime; - UINTN IconSizes[3]; - UINTN BannerScale; - REFIT_VOLUME *DiscoveredRoot; - CHAR16 *BannerFileName; - EG_IMAGE *ScreenBackground; - CHAR16 *ConfigFilename; - CHAR16 *SelectionSmallFileName; - CHAR16 *SelectionBigFileName; - CHAR16 *DefaultSelection; - CHAR16 *AlsoScan; - CHAR16 *DontScanVolumes; - CHAR16 *DontScanDirs; - CHAR16 *DontScanFiles; - CHAR16 *WindowsRecoveryFiles; - CHAR16 *DriverDirs; - CHAR16 *IconsDir; - UINTN ShowTools[NUM_TOOLS]; - CHAR8 ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan + BOOLEAN TextOnly; + BOOLEAN ScanAllLinux; + BOOLEAN DeepLegacyScan; + BOOLEAN EnableAndLockVMX; + BOOLEAN FoldLinuxKernels; + UINTN RequestedScreenWidth; + UINTN RequestedScreenHeight; + UINTN BannerBottomEdge; + UINTN RequestedTextMode; + UINTN Timeout; + UINTN HideUIFlags; + UINTN MaxTags; // max. number of OS entries to show simultaneously in graphics mode + UINTN GraphicsFor; + UINTN LegacyType; + UINTN ScanDelay; + UINTN ScreensaverTime; + UINTN IconSizes[3]; + UINTN BannerScale; + REFIT_VOLUME *DiscoveredRoot; + EFI_DEVICE_PATH *SelfDevicePath; + CHAR16 *BannerFileName; + EG_IMAGE *ScreenBackground; + CHAR16 *ConfigFilename; + CHAR16 *SelectionSmallFileName; + CHAR16 *SelectionBigFileName; + CHAR16 *DefaultSelection; + CHAR16 *AlsoScan; + CHAR16 *DontScanVolumes; + CHAR16 *DontScanDirs; + CHAR16 *DontScanFiles; + CHAR16 *WindowsRecoveryFiles; + CHAR16 *DriverDirs; + CHAR16 *IconsDir; + UINTN ShowTools[NUM_TOOLS]; + CHAR8 ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan } REFIT_CONFIG; // Global variables diff --git a/refind/lib.c b/refind/lib.c index 40c1814..6bf2d5d 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -193,6 +193,7 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle) // find the current directory DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath); + GlobalConfig.SelfDevicePath = FileDevicePath(SelfLoadedImage->DeviceHandle, DevicePathAsString); CleanUpPathNameSlashes(DevicePathAsString); MyFreePool(SelfDirPath); Temp = FindPath(DevicePathAsString); diff --git a/refind/main.c b/refind/main.c index 9e2ee29..f674ecf 100644 --- a/refind/main.c +++ b/refind/main.c @@ -145,7 +145,7 @@ static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, REFIT_CONFIG GlobalConfig = { FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, 0, { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE }, BANNER_NOSCALE, - NULL, NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -173,7 +173,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.9.1"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.9.1.1"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2015 Roderick W. Smith"); @@ -276,7 +276,7 @@ EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, IN BOOLEAN IsDriver) { EFI_STATUS Status, ReturnStatus; - EFI_HANDLE ChildImageHandle; + EFI_HANDLE ChildImageHandle, ChildImageHandle2; EFI_LOADED_IMAGE *ChildLoadedImage = NULL; REFIT_VOLUME *Volume = NULL; UINTN DevicePathIndex; @@ -300,7 +300,7 @@ EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, if (Verbose) Print(L"Starting %s\nUsing load options '%s'\n", ImageTitle, FullLoadOptions ? FullLoadOptions : L""); - // load the image into memory (and execute it, in the case of a shim/MOK image). + // load the image into memory ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) { FindVolumeAndFilename(DevicePaths[DevicePathIndex], &Volume, &Filename); @@ -325,6 +325,22 @@ EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, // ImageData, ImageSize, &ChildImageHandle); ReturnStatus = Status = refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, DevicePaths[DevicePathIndex], NULL, 0, &ChildImageHandle); + if (secure_mode() && ShimLoaded()) { + // Load ourself into memory. This is a trick to work around a bug in Shim 0.8, + // which ties itself into the BS->LoadImage() and BS->StartImage() functions and + // then unregisters itself from the EFI system table when its replacement + // StartImage() function is called *IF* the previous LoadImage() was for the same + // program. The result is that rEFInd can validate only the first program it + // launches (often a filesystem driver). Loading a second program (rEFInd itself, + // here, to keep it smaller than a kernel) works around this problem. See the + // replacements.c file in Shim, and especially its start_image() function, for + // the source of the problem. + // NOTE: This doesn't check the return status or handle errors. It could + // conceivably do weird things if, say, rEFInd were on a USB drive that the + // user pulls before launching a program. + refit_call6_wrapper(BS->LoadImage, FALSE, SelfImageHandle, GlobalConfig.SelfDevicePath, + NULL, 0, &ChildImageHandle2); + } } else { Print(L"Invalid loader file!\n"); ReturnStatus = EFI_LOAD_ERROR; -- 2.39.2