From 65478cb010b22ae8ad46ff670433b14cdd3a9ab4 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Sun, 27 Apr 2014 22:12:17 -0400 Subject: [PATCH] Added support for GPT partition name for display and use in "volume" in manual boot stanza, in addition to filesystem name. --- NEWS.txt | 7 +++++++ refind/Make.tiano | 2 +- refind/Makefile | 2 +- refind/config.c | 9 +++++---- refind/global.h | 1 + refind/lib.c | 43 ++++++++++++++++++++++++++----------------- refind/lib.h | 33 ++++----------------------------- refind/main.c | 13 ++++++++----- 8 files changed, 53 insertions(+), 57 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index a864e8e..eb424b0 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,6 +1,13 @@ 0.7.10 (?/??/2014): ------------------- +- rEFInd now uses the partition's name (as stored in the GPT data + structures) as a fallback for the filesystem's name if the latter can't + be found. Exceptions are if the partition name is one of three generic + names used by GPT fdisk: "Microsoft basic data", "Linux filesystem", or + "Apple HFS/HFS+". These are ignored in favor of the descriptive fallback + (e.g., "20 GiB Btrfs volume") + - It's now possible to specify a volume by partition GUID number in a manual boot stanza. This should be more reliable (albeit also more awkward) than using a filesystem number (such as fs0: or fs1:). diff --git a/refind/Make.tiano b/refind/Make.tiano index 538b3dd..60fe750 100644 --- a/refind/Make.tiano +++ b/refind/Make.tiano @@ -34,7 +34,7 @@ ALL_EFILIBS = $(EFILIB)/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevel # /usr/local/UDK2010/MyWorkSpace/Build/MdeModule/RELEASE_GCC46/X64/MdeModulePkg/Core/Dxe/DxeMain/OUTPUT/DxeMain/DxeMain.obj -SOURCE_NAMES = config driver_support icns lib main menu screen AutoGen +SOURCE_NAMES = config driver_support icns lib main menu screen gpt AutoGen OBJS = $(SOURCE_NAMES:=.obj) all: $(BUILDME) diff --git a/refind/Makefile b/refind/Makefile index 9b74ccc..506ee11 100644 --- a/refind/Makefile +++ b/refind/Makefile @@ -25,7 +25,7 @@ LOCAL_CPPFLAGS = -I$(SRCDIR) -I$(SRCDIR)/../include -I$(SRCDIR)/../libeg -I$(SR LOCAL_LDFLAGS = -L$(SRCDIR)/../libeg/ -L$(SRCDIR)/../mok/ LOCAL_LIBS = -leg -lmok -OBJS = main.o config.o menu.o screen.o icns.o lib.o driver_support.o +OBJS = main.o config.o menu.o screen.o icns.o gpt.o lib.o driver_support.o #OBJS = main.o config.o menu.o screen.o icns.o lib.o mok.o driver_support.o variables.o sha256.o pecoff.o simple_file.o security_policy.o guid.o all: $(TARGET) diff --git a/refind/config.c b/refind/config.c index c1a7b5d..72bffd7 100644 --- a/refind/config.c +++ b/refind/config.c @@ -659,9 +659,9 @@ VOID ReadConfig(CHAR16 *FileName) MyFreePool(File.Buffer); } /* VOID ReadConfig() */ -// Finds a volume with the specified Identifier (a volume label or a number -// followed by a colon, for the moment). If found, sets *Volume to point to -// that volume. If not, leaves it unchanged. +// Finds a volume with the specified Identifier (a filesystem label, a +// partition name, a partition GUID, or a number followed by a colon). If +// found, sets *Volume to point to that volume. If not, leaves it unchanged. // Returns TRUE if a match was found, FALSE if not. static BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier) { UINTN i = 0, CountedVolumes = 0, Length; @@ -687,7 +687,8 @@ static BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier) { CountedVolumes++; } // if } else { // User specified a volume by label or GUID - if (StriCmp(Identifier, Volumes[i]->VolName) == 0) { + if ((StriCmp(Identifier, Volumes[i]->VolName) == 0) || + (StriCmp(Identifier, Volumes[i]->PartName) == 0)) { *Volume = Volumes[i]; Found = TRUE; } // if diff --git a/refind/global.h b/refind/global.h index 5058d9d..7395192 100644 --- a/refind/global.h +++ b/refind/global.h @@ -174,6 +174,7 @@ typedef struct { EFI_HANDLE DeviceHandle; EFI_FILE *RootDir; CHAR16 *VolName; + CHAR16 *PartName; EFI_GUID VolUuid; EFI_GUID PartGuid; UINTN VolNumber; diff --git a/refind/lib.c b/refind/lib.c index 0053c2b..dc1c1b3 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -48,7 +48,7 @@ #include "screen.h" #include "../include/refit_call_wrapper.h" #include "../include/RemovableMedia.h" -//#include "../include/UsbMass.h" +#include "gpt.h" #ifdef __MAKEWITH_GNUEFI #define EfiReallocatePool ReallocatePool @@ -86,6 +86,7 @@ CHAR16 *SelfDirPath; REFIT_VOLUME *SelfVolume = NULL; REFIT_VOLUME **Volumes = NULL; UINTN VolumesCount = 0; +extern GPT_DATA *gPartitions; // Maximum size for disk sectors #define SECTOR_SIZE 4096 @@ -712,7 +713,7 @@ static CHAR16 *SizeInIEEEUnits(UINT64 SizeInBytes) { // this information can be extracted. // The calling function is responsible for freeing the memory allocated // for the name string. -static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) { +static CHAR16 *GetVolumeName(REFIT_VOLUME *Volume) { EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr; CHAR16 *FoundName = NULL; CHAR16 *SISize, *TypeName; @@ -723,14 +724,21 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) { FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel); } - // Special case: rEFInd HFS+ driver always returns label of "HFS+ volume", so wipe + // Special case: Old versions of the rEFInd HFS+ driver always returns label of "HFS+ volume", so wipe // this so that we can build a new name that includes the size.... if ((FoundName != NULL) && (StrCmp(FoundName, L"HFS+ volume") == 0) && (Volume->FSType == FS_TYPE_HFSPLUS)) { MyFreePool(FoundName); FoundName = NULL; } // if rEFInd HFS+ driver suspected - if (FoundName == NULL) { // filesystem has no name, so use fs type and size + // If no filesystem name, try to use the partition name.... + if ((FoundName == NULL) && (Volume->PartName != NULL) && (StrLen(Volume->PartName) > 0) && + !IsIn(Volume->PartName, IGNORE_PARTITION_NAMES)) { + FoundName = StrDuplicate(Volume->PartName); + } // if use partition name + + // No filesystem or acceptable partition name, so use fs type and size + if (FoundName == NULL) { FoundName = AllocateZeroPool(sizeof(CHAR16) * 256); if (FoundName != NULL) { SISize = SizeInIEEEUnits(FileSystemInfoPtr->VolumeSize); @@ -765,7 +773,7 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) { } // static CHAR16 *GetVolumeName() // Determine the unique GUID of the volume and store it. -static VOID SetPartGuid(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *DevicePath) { +static VOID SetPartGuidAndName(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *DevicePath) { HARDDRIVE_DEVICE_PATH *HdDevicePath; if (Volume == NULL) @@ -773,8 +781,11 @@ static VOID SetPartGuid(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *DevicePa if ((DevicePath->Type == MEDIA_DEVICE_PATH) && (DevicePath->SubType == MEDIA_HARDDRIVE_DP)) { HdDevicePath = (HARDDRIVE_DEVICE_PATH*) DevicePath; - Volume->PartGuid = *((EFI_GUID*) HdDevicePath->Signature); - } + if (HdDevicePath->SignatureType == SIGNATURE_TYPE_GUID) { + Volume->PartGuid = *((EFI_GUID*) HdDevicePath->Signature); + Volume->PartName = PartNameFromGuid(&(Volume->PartGuid)); + } // if + } // if } // VOID SetPartGuid() VOID ScanVolume(REFIT_VOLUME *Volume) @@ -819,7 +830,7 @@ VOID ScanVolume(REFIT_VOLUME *Volume) NextDevicePath = NextDevicePathNode(DevicePath); if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH) { - SetPartGuid(Volume, DevicePath); + SetPartGuidAndName(Volume, DevicePath); } if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH && (DevicePathSubType(DevicePath) == MSG_USB_DP || @@ -861,7 +872,8 @@ VOID ScanVolume(REFIT_VOLUME *Volume) } // look at the BlockIO protocol - Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol, (VOID **) &Volume->WholeDiskBlockIO); + Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol, + (VOID **) &Volume->WholeDiskBlockIO); if (!EFI_ERROR(Status)) { // check the media block size @@ -987,11 +999,11 @@ VOID ScanVolumes(VOID) MyFreePool(Volumes); Volumes = NULL; VolumesCount = 0; + ForgetPartitionTables(); // get all filesystem handles Status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL, &HandleCount, &Handles); UuidList = AllocateZeroPool(sizeof(EFI_GUID) * HandleCount); - // was: &FileSystemProtocol if (Status == EFI_NOT_FOUND) { return; // no filesystems. strange, but true... } @@ -1002,6 +1014,7 @@ VOID ScanVolumes(VOID) for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { Volume = AllocateZeroPool(sizeof(REFIT_VOLUME)); Volume->DeviceHandle = Handles[HandleIndex]; + AddPartitionTable(Volume); ScanVolume(Volume); if (UuidList) { UuidList[HandleIndex] = Volume->VolUuid; @@ -1097,7 +1110,6 @@ VOID ScanVolumes(VOID) MyFreePool(SectorBuffer1); MyFreePool(SectorBuffer2); } - } // for } /* VOID ScanVolumes() */ @@ -1961,9 +1973,6 @@ EFI_GUID StringAsGuid(CHAR16 * InString) { // Returns TRUE if the two GUIDs are equal, FALSE otherwise BOOLEAN GuidsAreEqual(EFI_GUID *Guid1, EFI_GUID *Guid2) { - return ((Guid1->Data1 == Guid2->Data1) && (Guid1->Data2 == Guid2->Data2) && (Guid1->Data3 == Guid2->Data3) && - (Guid1->Data4[0] == Guid2->Data4[0]) && (Guid1->Data4[1] == Guid2->Data4[1]) && - (Guid1->Data4[2] == Guid2->Data4[2]) && (Guid1->Data4[3] == Guid2->Data4[3]) && - (Guid1->Data4[4] == Guid2->Data4[4]) && (Guid1->Data4[5] == Guid2->Data4[5]) && - (Guid1->Data4[6] == Guid2->Data4[6]) && (Guid1->Data4[7] == Guid2->Data4[7])); -} // BOOLEAN CompareGuids() \ No newline at end of file + return (CompareMem(Guid1, Guid2, 16) == 0); +} // BOOLEAN CompareGuids() + diff --git a/refind/lib.h b/refind/lib.h index bc3454c..8a71249 100644 --- a/refind/lib.h +++ b/refind/lib.h @@ -48,35 +48,7 @@ #ifdef __MAKEWITH_GNUEFI #include "efi.h" #include "efilib.h" -#pragma pack(1) - -/** - This protocol can be used on any device handle to obtain generic path/location - information concerning the physical device or logical device. If the handle does - not logically map to a physical device, the handle may not necessarily support - the device path protocol. The device path describes the location of the device - the handle is for. The size of the Device Path can be determined from the structures - that make up the Device Path. -**/ -typedef struct { - UINT8 Type; ///< 0x01 Hardware Device Path. - ///< 0x02 ACPI Device Path. - ///< 0x03 Messaging Device Path. - ///< 0x04 Media Device Path. - ///< 0x05 BIOS Boot Specification Device Path. - ///< 0x7F End of Hardware Device Path. - - UINT8 SubType; ///< Varies by Type - ///< 0xFF End Entire Device Path, or - ///< 0x01 End This Instance of a Device Path and start a new - ///< Device Path. - - UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define - ///< type of data. Size of data is included in Length. - -} EFI_DEVICE_PATH_PROTOCOL; - -#pragma pack() +#define EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH #else #include "../include/tiano_includes.h" #endif @@ -106,6 +78,9 @@ typedef struct { #define IS_EXTENDED_PART_TYPE(type) ((type) == 0x05 || (type) == 0x0f || (type) == 0x85) +// Partition names to be ignored when setting volume name +#define IGNORE_PARTITION_NAMES L"Microsoft basic data,Linux filesystem,Apple HFS/HFS+" + EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle); VOID UninitRefitLib(VOID); EFI_STATUS ReinitRefitLib(VOID); diff --git a/refind/main.c b/refind/main.c index 25c7a5a..3905d00 100644 --- a/refind/main.c +++ b/refind/main.c @@ -49,6 +49,7 @@ #include "icns.h" #include "menu.h" #include "mok.h" +#include "gpt.h" #include "security_policy.h" #include "../include/Handle.h" #include "../include/refit_call_wrapper.h" @@ -143,6 +144,8 @@ REFIT_CONFIG GlobalConfig = { FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, EFI_GUID GlobalGuid = EFI_GLOBAL_VARIABLE; +GPT_DATA *gPartitions = NULL; + // Structure used to hold boot loader filenames and time stamps in // a linked list; used to sort entries within a directory. struct LOADER_LIST { @@ -159,7 +162,7 @@ static VOID AboutrEFInd(VOID) { if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.7.9.2"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.7.9.3"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2014 Roderick W. Smith"); @@ -1329,11 +1332,11 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { BOOLEAN ScanFallbackLoader = TRUE; BOOLEAN FoundBRBackup = FALSE; - MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS); - if (GlobalConfig.ScanAllLinux) - MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L','); - if ((Volume->RootDir != NULL) && (Volume->VolName != NULL) && (Volume->IsReadable)) { + MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS); + if (GlobalConfig.ScanAllLinux) + MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L','); + // check for Mac OS X boot loader if (ShouldScan(Volume, L"System\\Library\\CoreServices")) { StrCpy(FileName, MACOSX_LOADER_PATH); -- 2.39.2