From ea0768929fa3b215a77375130c19ae0710947400 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Mon, 25 Jan 2016 09:39:13 -0500 Subject: [PATCH 1/1] Worked around bug/quirk in some EFIs that prevented filesystem drivers from accessing their filesystems. --- Makefile | 2 +- NEWS.txt | 11 +- debian/copyright | 13 +- refind-install | 1 + refind/driver_support.c | 394 +++++++++++++++++++++++++++++++++++++--- refind/driver_support.h | 35 ++-- refind/global.h | 13 ++ refind/main.c | 169 +---------------- 8 files changed, 431 insertions(+), 207 deletions(-) diff --git a/Makefile b/Makefile index 3601028..588fe2d 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ MOK_DIR=mok GPTSYNC_DIR=gptsync EFILIB_DIR=EfiLib export EDK2BASE=/usr/local/UDK2014/MyWorkSpace -export REFIND_VERSION='L"0.10.1.2"' +export REFIND_VERSION='L"0.10.1.3"' # The "all" target builds with the TianoCore library if possible, but falls # back on the more easily-installed GNU-EFI library if TianoCore isn't diff --git a/NEWS.txt b/NEWS.txt index 79f651e..183d761 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,7 +1,16 @@ 0.10.2 (?/??/2016): ------------------- -- Fixed bug that caused custom volume badges (vol_????.png) to be read only +- Worked around bug/quirk in some EFIs (in HP ProBook 6470b laptop, at + least) that prevented EFI filesystem drivers from working. (Drivers would + load but not provide access to filesystems.) + +- Fixed refind-install bug that caused --usedefault option to not work in OS + X. (This bug did not affect Linux.) + +- Improved Secure Boot detection in refind-install in Linux. + +- Fixed bug that caused custom volume badges (vol_*.png) to be read only from default location ("icons" subdirectory), effectively eliminating the ability to adjust them. diff --git a/debian/copyright b/debian/copyright index 21fab0d..a38d0e4 100644 --- a/debian/copyright +++ b/debian/copyright @@ -5,11 +5,11 @@ Source: http://www.rodsbooks.com/refind Files: * Copyright: 2006 Christoph Pfisterer - 2012 Roderick W. Smith + 2012-2016 Roderick W. Smith License: BSD-3-clause and GPL-3+ Files: debian/* -Copyright: 2014 Roderick W. Smith +Copyright: 2014-2016 Roderick W. Smith 2015 Tianon Gravi License: GPL-3+ @@ -52,7 +52,7 @@ Files: refind/* libeg/image.c libeg/screen.c Copyright: 2006-2010 Christoph Pfisterer - 2012-2015 Roderick W. Smith + 2012-2016 Roderick W. Smith License: BSD-3-clause and GPL-3+ Files: refind/icns.c @@ -72,7 +72,12 @@ License: unrestricted-crc32 without restriction. Files: refind/driver_support.[ch] - libeg/efiConsoleControl.h +Copyright: 2006-2011 Intel Corporation + 2006-2010 Christoph Pfisterer + 2012-2016 Roderick W. Smith +License: BSD-2-clause and BSD-3-clause and GPL-3+ + +Files: libeg/efiConsoleControl.h libeg/efiUgaDraw.h Copyright: 2006-2011 Intel Corporation License: BSD-2-clause diff --git a/refind-install b/refind-install index 37fa811..84d6615 100755 --- a/refind-install +++ b/refind-install @@ -39,6 +39,7 @@ # Revision history: # +# 0.10.2 -- Improved Secure Boot detection in Linux & fixed --usedefault in OS X. # 0.10.1 -- Improve extraction of default kernel options from /proc/cmdline. # Add support for AMD64 (aka AARCH64, aa64) platform. Added # warning when --alldrivers used without --usedefault. diff --git a/refind/driver_support.c b/refind/driver_support.c index a547d65..3faf984 100644 --- a/refind/driver_support.c +++ b/refind/driver_support.c @@ -1,12 +1,7 @@ /* - * File to implement LibScanHandleDatabase(), which is used by rEFInd's - * driver-loading code (inherited from rEFIt), but which has not been - * implemented in GNU-EFI and seems to have been dropped from current - * versions of the Tianocore library. This function was taken from a git - * site with EFI code, but some of the constants it uses were taken from - * a more recent EDK2 package (see below for details). The original files - * bore the following copyright notice: - * + * Functions related to drivers. Original copyright notices below.... + */ +/* * Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
* This program and the accompanying materials are licensed and made available under * the terms and conditions of the BSD License that accompanies this distribution. @@ -17,11 +12,77 @@ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * */ +/* + * refit/main.c + * Main code for the boot menu + * + * Copyright (c) 2006-2010 Christoph Pfisterer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Christoph Pfisterer nor the names of the + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Modifications copyright (c) 2012-2016 Roderick W. Smith + * + * Modifications distributed under the terms of the GNU General Public + * License (GPL) version 3 (GPLv3), or (at your option) any later version. + * + */ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include "driver_support.h" #include "lib.h" +#include "mystrings.h" +#include "screen.h" #include "../include/refit_call_wrapper.h" +#if defined (EFIX64) +#define DRIVER_DIRS L"drivers,drivers_x64" +#elif defined (EFI32) +#define DRIVER_DIRS L"drivers,drivers_ia32" +#elif defined (EFIAARCH64) +#define DRIVER_DIRS L"drivers,drivers_aa64" +#endif + #ifdef __MAKEWITH_GNUEFI // Following "global" constants are from EDK2's AutoGen.c.... EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; @@ -33,22 +94,64 @@ EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x EFI_GUID gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}; EFI_GUID gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }}; EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; -#endif +EFI_GUID gEfiDiskIoProtocolGuid = { 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; +EFI_GUID gEfiSimpleFileSystemProtocolGuid = { 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }}; + +struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; +struct EFI_FILE_PROTOCOL; -// Below is from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec; -// Seems to have been replaced by ParseHandleDatabaseByRelationshipWithType(), but the latter isn't working for me.... +typedef EFI_STATUS -LibScanHandleDatabase ( - EFI_HANDLE DriverBindingHandle, OPTIONAL - UINT32 *DriverBindingHandleIndex, OPTIONAL - EFI_HANDLE ControllerHandle, OPTIONAL - UINT32 *ControllerHandleIndex, OPTIONAL - UINTN *HandleCount, - EFI_HANDLE **HandleBuffer, - UINT32 **HandleType - ) +(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)( + IN struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT struct EFI_FILE_PROTOCOL **Root + ); -{ +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + UINT64 Revision; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; +} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +typedef struct _EFI_FILE_PROTOCOL { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; +} EFI_FILE_PROTOCOL; + +typedef struct _EFI_BLOCK_IO_PROTOCOL { + UINT64 Revision; + EFI_BLOCK_IO_MEDIA *Media; + EFI_BLOCK_RESET Reset; + EFI_BLOCK_READ ReadBlocks; + EFI_BLOCK_WRITE WriteBlocks; + EFI_BLOCK_FLUSH FlushBlocks; +} EFI_BLOCK_IO_PROTOCOL; +#endif + +/* LibScanHandleDatabase() is used by rEFInd's driver-loading code (inherited + * from rEFIt), but has not been implemented in GNU-EFI and seems to have been + * dropped from current versions of the Tianocore library. This function was + * taken from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec, + * The original files are copyright 2006-2011 Intel and BSD-licensed. Minor + * modifications by Roderick Smith are GPLv3. + */ +EFI_STATUS +LibScanHandleDatabase (EFI_HANDLE DriverBindingHandle, OPTIONAL + UINT32 *DriverBindingHandleIndex, OPTIONAL + EFI_HANDLE ControllerHandle, OPTIONAL + UINT32 *ControllerHandleIndex, OPTIONAL + UINTN *HandleCount, + EFI_HANDLE **HandleBuffer, + UINT32 **HandleType) { EFI_STATUS Status; UINTN HandleIndex; EFI_GUID **ProtocolGuidArray; @@ -59,14 +162,12 @@ LibScanHandleDatabase ( UINTN OpenInfoIndex; UINTN ChildIndex; BOOLEAN DriverBindingHandleIndexValid; -// BOOLEAN ControllerHandleIndexValid; DriverBindingHandleIndexValid = FALSE; if (DriverBindingHandleIndex != NULL) { *DriverBindingHandleIndex = 0xffffffff; } -// ControllerHandleIndexValid = FALSE; if (ControllerHandleIndex != NULL) { *ControllerHandleIndex = 0xffffffff; } @@ -111,7 +212,6 @@ LibScanHandleDatabase ( if (ControllerHandle != NULL && ControllerHandleIndex != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) { *ControllerHandleIndex = (UINT32) HandleIndex; -// ControllerHandleIndexValid = TRUE; } } @@ -249,3 +349,249 @@ Error: return Status; } /* EFI_STATUS LibScanHandleDatabase() */ + +#ifdef __MAKEWITH_GNUEFI +/* Modified from EDK2 function of a similar name; original copyright Intel & + * BSD-licensed; modifications by Roderick Smith are GPLv3. */ +EFI_STATUS ConnectAllDriversToAllControllers(VOID) +{ + EFI_STATUS Status; + UINTN AllHandleCount; + EFI_HANDLE *AllHandleBuffer; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINT32 *HandleType; + UINTN HandleIndex; + BOOLEAN Parent; + BOOLEAN Device; + + Status = LibLocateHandle(AllHandles, + NULL, + NULL, + &AllHandleCount, + &AllHandleBuffer); + if (EFI_ERROR(Status)) + return Status; + + for (Index = 0; Index < AllHandleCount; Index++) { + // + // Scan the handle database + // + Status = LibScanHandleDatabase(NULL, + NULL, + AllHandleBuffer[Index], + NULL, + &HandleCount, + &HandleBuffer, + &HandleType); + if (EFI_ERROR (Status)) + goto Done; + + Device = TRUE; + if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE) + Device = FALSE; + if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE) + Device = FALSE; + + if (Device) { + Parent = FALSE; + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE) + Parent = TRUE; + } // for + + if (!Parent) { + if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE) { + Status = refit_call4_wrapper(BS->ConnectController, + AllHandleBuffer[Index], + NULL, + NULL, + TRUE); + } + } + } + + MyFreePool (HandleBuffer); + MyFreePool (HandleType); + } + +Done: + MyFreePool (AllHandleBuffer); + return Status; +} /* EFI_STATUS ConnectAllDriversToAllControllers() */ +#else +EFI_STATUS ConnectAllDriversToAllControllers(VOID) { + BdsLibConnectAllDriversToAllControllers(); + return 0; +} +#endif + +/* + * ConnectFilesystemDriver() is modified from DisconnectInvalidDiskIoChildDrivers() + * in Clover (https://sourceforge.net/projects/cloverefiboot/), which is derived + * from rEFIt. The refit/main.c file from which this function was taken continues + * to bear rEFIt's original copyright/licence notice (BSD); modifications by + * Roderick Smith (2016) are GPLv3. + */ +/** + * Some UEFI's (like HPQ EFI from HP notebooks) have DiskIo protocols + * opened BY_DRIVER (by Partition driver in HP case) even when no file system + * is produced from this DiskIo. This then blocks our FS drivers from connecting + * and producing file systems. + * To fix it: we will disconnect drivers that connected to DiskIo BY_DRIVER + * if this is partition volume and if those drivers did not produce file system, + * then try to connect every unconnected device to the driver whose handle is + * passed to us. + */ +VOID ConnectFilesystemDriver(EFI_HANDLE DriverHandle) { + EFI_STATUS Status; + UINTN HandleCount = 0; + UINTN Index; + UINTN OpenInfoIndex; + EFI_HANDLE *Handles = NULL; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; + UINTN OpenInfoCount; + EFI_HANDLE DriverHandleList[2]; + + // + // Get all DiskIo handles + // + Status = refit_call5_wrapper(gBS->LocateHandleBuffer, + ByProtocol, + &gEfiDiskIoProtocolGuid, + NULL, + &HandleCount, + &Handles); + if (EFI_ERROR(Status) || HandleCount == 0) + return; + + // + // Check every DiskIo handle + // + for (Index = 0; Index < HandleCount; Index++) { + // + // If this is not partition - skip it. + // This is then whole disk and DiskIo + // should be opened here BY_DRIVER by Partition driver + // to produce partition volumes. + // + Status = refit_call3_wrapper(gBS->HandleProtocol, + Handles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo); + if (EFI_ERROR (Status)) + continue; + if (BlockIo->Media == NULL || !BlockIo->Media->LogicalPartition) + continue; + + // + // If SimpleFileSystem is already produced - skip it, this is ok + // + Status = refit_call3_wrapper(gBS->HandleProtocol, + Handles[Index], + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &Fs); + if (Status == EFI_SUCCESS) + continue; + + // + // If no SimpleFileSystem on this handle but DiskIo is opened BY_DRIVER + // then disconnect this connection and try to connect our driver to it + // + Status = refit_call4_wrapper(gBS->OpenProtocolInformation, + Handles[Index], + &gEfiDiskIoProtocolGuid, + &OpenInfo, + &OpenInfoCount); + if (EFI_ERROR (Status)) + continue; + DriverHandleList[1] = NULL; + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) { + Status = refit_call3_wrapper(gBS->DisconnectController, + Handles[Index], + OpenInfo[OpenInfoIndex].AgentHandle, + NULL); + if (!(EFI_ERROR(Status))) { + DriverHandleList[0] = DriverHandle; + refit_call4_wrapper(gBS->ConnectController, + Handles[Index], + DriverHandleList, + NULL, + FALSE); + } // if + } // if + } // for + FreePool (OpenInfo); + } + FreePool(Handles); +} // VOID ConnectFilesystemDriver() + +// Scan a directory for drivers. +// Originally from rEFIt's main.c (BSD), but modified since then (GPLv3). +static UINTN ScanDriverDir(IN CHAR16 *Path) +{ + EFI_STATUS Status; + REFIT_DIR_ITER DirIter; + UINTN NumFound = 0; + EFI_FILE_INFO *DirEntry; + CHAR16 FileName[256]; + + CleanUpPathNameSlashes(Path); + // look through contents of the directory + DirIterOpen(SelfRootDir, Path, &DirIter); + while (DirIterNext(&DirIter, 2, LOADER_MATCH_PATTERNS, &DirEntry)) { + if (DirEntry->FileName[0] == '.') + continue; // skip this + + SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName); + NumFound++; + Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName), + L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE); + } + Status = DirIterClose(&DirIter); + if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { + SPrint(FileName, 255, L"while scanning the %s directory", Path); + CheckError(Status, FileName); + } + return (NumFound); +} // static UINTN ScanDriverDir() + + +// Load all EFI drivers from rEFInd's "drivers" subdirectory and from the +// directories specified by the user in the "scan_driver_dirs" configuration +// file line. +// Originally from rEFIt's main.c (BSD), but modified since then (GPLv3). +VOID LoadDrivers(VOID) { + CHAR16 *Directory, *SelfDirectory; + UINTN i = 0, Length, NumFound = 0; + + // load drivers from the subdirectories of rEFInd's home directory specified + // in the DRIVER_DIRS constant. + while ((Directory = FindCommaDelimited(DRIVER_DIRS, i++)) != NULL) { + SelfDirectory = SelfDirPath ? StrDuplicate(SelfDirPath) : NULL; + CleanUpPathNameSlashes(SelfDirectory); + MergeStrings(&SelfDirectory, Directory, L'\\'); + NumFound += ScanDriverDir(SelfDirectory); + MyFreePool(Directory); + MyFreePool(SelfDirectory); + } + + // Scan additional user-specified driver directories.... + i = 0; + while ((Directory = FindCommaDelimited(GlobalConfig.DriverDirs, i++)) != NULL) { + CleanUpPathNameSlashes(Directory); + Length = StrLen(Directory); + if (Length > 0) { + NumFound += ScanDriverDir(Directory); + } // if + MyFreePool(Directory); + } // while + + // connect all devices + if (NumFound > 0) + ConnectAllDriversToAllControllers(); +} /* VOID LoadDrivers() */ diff --git a/refind/driver_support.h b/refind/driver_support.h index bf4c0e7..fa9ba60 100644 --- a/refind/driver_support.h +++ b/refind/driver_support.h @@ -17,16 +17,28 @@ * */ +#ifndef _DRIVER_SUPPORT +#define _DRIVER_SUPPORT + #ifdef __MAKEWITH_GNUEFI #include -//#include #else #include "../include/tiano_includes.h" #endif #include "global.h" -#ifndef _DRIVER_SUPPORT -#define _DRIVER_SUPPORT +#define EFI_HANDLE_TYPE_UNKNOWN 0x000 +#define EFI_HANDLE_TYPE_IMAGE_HANDLE 0x001 +#define EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE 0x002 +#define EFI_HANDLE_TYPE_DEVICE_DRIVER 0x004 +#define EFI_HANDLE_TYPE_BUS_DRIVER 0x008 +#define EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE 0x010 +#define EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE 0x020 +#define EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE 0x040 +#define EFI_HANDLE_TYPE_DEVICE_HANDLE 0x080 +#define EFI_HANDLE_TYPE_PARENT_HANDLE 0x100 +#define EFI_HANDLE_TYPE_CONTROLLER_HANDLE 0x200 +#define EFI_HANDLE_TYPE_CHILD_HANDLE 0x400 // Below is from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec; // Seems to have been replaced by ParseHandleDatabaseByRelationshipWithType(), but the latter isn't working for me.... @@ -40,19 +52,8 @@ LibScanHandleDatabase ( EFI_HANDLE **HandleBuffer, UINT32 **HandleType ); - - -#define EFI_HANDLE_TYPE_UNKNOWN 0x000 -#define EFI_HANDLE_TYPE_IMAGE_HANDLE 0x001 -#define EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE 0x002 -#define EFI_HANDLE_TYPE_DEVICE_DRIVER 0x004 -#define EFI_HANDLE_TYPE_BUS_DRIVER 0x008 -#define EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE 0x010 -#define EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE 0x020 -#define EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE 0x040 -#define EFI_HANDLE_TYPE_DEVICE_HANDLE 0x080 -#define EFI_HANDLE_TYPE_PARENT_HANDLE 0x100 -#define EFI_HANDLE_TYPE_CONTROLLER_HANDLE 0x200 -#define EFI_HANDLE_TYPE_CHILD_HANDLE 0x400 +EFI_STATUS ConnectAllDriversToAllControllers(VOID); +VOID ConnectFilesystemDriver(EFI_HANDLE DriverHandle); +VOID LoadDrivers(VOID); #endif diff --git a/refind/global.h b/refind/global.h index 8acbf7d..d35f9b0 100644 --- a/refind/global.h +++ b/refind/global.h @@ -158,6 +158,13 @@ // Files that may be Windows recovery files #define WINDOWS_RECOVERY_FILES L"EFI\\Microsoft\\Boot\\LrsBootmgr.efi,Recovery:\\EFI\\BOOT\\bootx64.efi,Recovery:\\EFI\\BOOT\\bootia32.efi" +// Filename patterns that identify EFI boot loaders. Note that a single case (either L"*.efi" or +// L"*.EFI") is fine for most systems; but Gigabyte's buggy Hybrid EFI does a case-sensitive +// comparison when it should do a case-insensitive comparison, so I'm doubling this up. It does +// no harm on other computers, AFAIK. In theory, every case variation should be done for +// completeness, but that's ridiculous.... +#define LOADER_MATCH_PATTERNS L"*.efi,*.EFI" + // Definitions for the "hideui" option in refind.conf #define HIDEUI_FLAG_NONE (0x0000) #define HIDEUI_FLAG_BANNER (0x0001) @@ -340,6 +347,12 @@ EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, OUT UINTN *ErrorInStep, IN BOOLEAN Verbose, IN BOOLEAN IsDriver); +EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, + IN CHAR16 *LoadOptions, IN UINTN LoaderType, + IN CHAR16 *ImageTitle, IN CHAR8 OSType, + OUT UINTN *ErrorInStep, + IN BOOLEAN Verbose, + IN BOOLEAN IsDriver); LOADER_ENTRY *InitializeLoaderEntry(IN LOADER_ENTRY *Entry); REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry); VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN GenerateReturn); diff --git a/refind/main.c b/refind/main.c index 881ac38..69e80fc 100644 --- a/refind/main.c +++ b/refind/main.c @@ -98,7 +98,6 @@ #define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_x64.efi" #define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" #define MEMTEST_NAMES L"memtest86.efi,memtest86_x64.efi,memtest86x64.efi,bootx64.efi" -#define DRIVER_DIRS L"drivers,drivers_x64" #define FALLBACK_FULLNAME L"EFI\\BOOT\\bootx64.efi" #define FALLBACK_BASENAME L"bootx64.efi" #define EFI_STUB_ARCH 0x8664 @@ -109,7 +108,6 @@ EFI_GUID gFreedesktopRootGuid = { 0x4f68bce3, 0xe8cd, 0x4db1, { 0x96, 0xe7, 0xfb #define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_ia32.efi" #define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" #define MEMTEST_NAMES L"memtest86.efi,memtest86_ia32.efi,memtest86ia32.efi,bootia32.efi" -#define DRIVER_DIRS L"drivers,drivers_ia32" #define FALLBACK_FULLNAME L"EFI\\BOOT\\bootia32.efi" #define FALLBACK_BASENAME L"bootia32.efi" #define EFI_STUB_ARCH 0x014c @@ -120,7 +118,6 @@ EFI_GUID gFreedesktopRootGuid = { 0x44479540, 0xf297, 0x41b2, { 0x9a, 0xf7, 0xd1 #define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_aa64.efi" #define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi" #define MEMTEST_NAMES L"memtest86.efi,memtest86_aa64.efi,memtest86aa64.efi,bootaa64.efi" -#define DRIVER_DIRS L"drivers,drivers_aa64" #define FALLBACK_FULLNAME L"EFI\\BOOT\\bootaa64.efi" #define FALLBACK_BASENAME L"bootaa64.efi" #define EFI_STUB_ARCH 0xaa64 @@ -142,13 +139,6 @@ EFI_GUID gFreedesktopRootGuid = { 0x69dad710, 0x2ce4, 0x4e3c, { 0xb1, 0x6c, 0x21 #define IPXE_DISCOVER_NAME L"\\efi\\tools\\ipxe_discover.efi" #define IPXE_NAME L"\\efi\\tools\\ipxe.efi" -// Filename patterns that identify EFI boot loaders. Note that a single case (either L"*.efi" or -// L"*.EFI") is fine for most systems; but Gigabyte's buggy Hybrid EFI does a case-sensitive -// comparison when it should do a case-insensitive comparison, so I'm doubling this up. It does -// no harm on other computers, AFAIK. In theory, every case variation should be done for -// completeness, but that's ridiculous.... -#define LOADER_MATCH_PATTERNS L"*.efi,*.EFI" - // Patterns that identify Linux kernels. Added to the loader match pattern when the // scan_all_linux_kernels option is set in the configuration file. Causes kernels WITHOUT // a ".efi" extension to be found when scanning for boot loaders. @@ -420,6 +410,8 @@ EFI_STATUS StartEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, if (ErrorInStep != NULL) *ErrorInStep = 3; } + if (IsDriver) + ConnectFilesystemDriver(ChildImageHandle); // re-open file handles ReinitRefitLib(); @@ -434,13 +426,12 @@ bailout: return ReturnStatus; } /* EFI_STATUS StartEFIImageList() */ -static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, - IN CHAR16 *LoadOptions, IN UINTN LoaderType, - IN CHAR16 *ImageTitle, IN CHAR8 OSType, - OUT UINTN *ErrorInStep, - IN BOOLEAN Verbose, - IN BOOLEAN IsDriver - ) +EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, + IN CHAR16 *LoadOptions, IN UINTN LoaderType, + IN CHAR16 *ImageTitle, IN CHAR8 OSType, + OUT UINTN *ErrorInStep, + IN BOOLEAN Verbose, + IN BOOLEAN IsDriver) { EFI_DEVICE_PATH *DevicePaths[2]; @@ -1703,149 +1694,6 @@ static LOADER_ENTRY * AddToolEntry(EFI_HANDLE DeviceHandle, IN CHAR16 *LoaderPat return Entry; } /* static LOADER_ENTRY * AddToolEntry() */ -// -// pre-boot driver functions -// - -static UINTN ScanDriverDir(IN CHAR16 *Path) -{ - EFI_STATUS Status; - REFIT_DIR_ITER DirIter; - UINTN NumFound = 0; - EFI_FILE_INFO *DirEntry; - CHAR16 FileName[256]; - - CleanUpPathNameSlashes(Path); - // look through contents of the directory - DirIterOpen(SelfRootDir, Path, &DirIter); - while (DirIterNext(&DirIter, 2, LOADER_MATCH_PATTERNS, &DirEntry)) { - if (DirEntry->FileName[0] == '.') - continue; // skip this - - SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName); - NumFound++; - Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName), - L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE); - } - Status = DirIterClose(&DirIter); - if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { - SPrint(FileName, 255, L"while scanning the %s directory", Path); - CheckError(Status, FileName); - } - return (NumFound); -} - -#ifdef __MAKEWITH_GNUEFI -static EFI_STATUS ConnectAllDriversToAllControllers(VOID) -{ - EFI_STATUS Status; - UINTN AllHandleCount; - EFI_HANDLE *AllHandleBuffer; - UINTN Index; - UINTN HandleCount; - EFI_HANDLE *HandleBuffer; - UINT32 *HandleType; - UINTN HandleIndex; - BOOLEAN Parent; - BOOLEAN Device; - - Status = LibLocateHandle(AllHandles, - NULL, - NULL, - &AllHandleCount, - &AllHandleBuffer); - if (EFI_ERROR(Status)) - return Status; - - for (Index = 0; Index < AllHandleCount; Index++) { - // - // Scan the handle database - // - Status = LibScanHandleDatabase(NULL, - NULL, - AllHandleBuffer[Index], - NULL, - &HandleCount, - &HandleBuffer, - &HandleType); - if (EFI_ERROR (Status)) - goto Done; - - Device = TRUE; - if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE) - Device = FALSE; - if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE) - Device = FALSE; - - if (Device) { - Parent = FALSE; - for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { - if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE) - Parent = TRUE; - } // for - - if (!Parent) { - if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE) { - Status = refit_call4_wrapper(BS->ConnectController, - AllHandleBuffer[Index], - NULL, - NULL, - TRUE); - } - } - } - - MyFreePool (HandleBuffer); - MyFreePool (HandleType); - } - -Done: - MyFreePool (AllHandleBuffer); - return Status; -} /* EFI_STATUS ConnectAllDriversToAllControllers() */ -#else -static EFI_STATUS ConnectAllDriversToAllControllers(VOID) { - BdsLibConnectAllDriversToAllControllers(); - return 0; -} -#endif - -// Load all EFI drivers from rEFInd's "drivers" subdirectory and from the -// directories specified by the user in the "scan_driver_dirs" configuration -// file line. -static VOID LoadDrivers(VOID) -{ - CHAR16 *Directory, *SelfDirectory; - UINTN i = 0, Length, NumFound = 0; - - // load drivers from the subdirectories of rEFInd's home directory specified - // in the DRIVER_DIRS constant. - while ((Directory = FindCommaDelimited(DRIVER_DIRS, i++)) != NULL) { - SelfDirectory = SelfDirPath ? StrDuplicate(SelfDirPath) : NULL; - CleanUpPathNameSlashes(SelfDirectory); - MergeStrings(&SelfDirectory, Directory, L'\\'); - NumFound += ScanDriverDir(SelfDirectory); - MyFreePool(Directory); - MyFreePool(SelfDirectory); - } - - // Scan additional user-specified driver directories.... - i = 0; - while ((Directory = FindCommaDelimited(GlobalConfig.DriverDirs, i++)) != NULL) { - CleanUpPathNameSlashes(Directory); - Length = StrLen(Directory); - if (Length > 0) { - NumFound += ScanDriverDir(Directory); - } // if - MyFreePool(Directory); - } // while - - // connect all devices - if (NumFound > 0) { - ConnectAllDriversToAllControllers(); - } -} /* static VOID LoadDrivers() */ - // Locates boot loaders. NOTE: This assumes that GlobalConfig.LegacyType is set correctly. static VOID ScanForBootloaders(VOID) { UINTN i; @@ -2100,6 +1948,7 @@ static VOID RescanAll(BOOLEAN DisplayMessage) { ConnectAllDriversToAllControllers(); ScanVolumes(); ReadConfig(GlobalConfig.ConfigFilename); + SetVolumeIcons(); ScanForBootloaders(); ScanForTools(); SetupScreen(); -- 2.39.2