]> code.delx.au - refind/commitdiff
Added support for specifying volumes via partition GUID in manual boot
authorsrs5694 <srs5694@users.sourceforge.net>
Sun, 27 Apr 2014 00:21:34 +0000 (20:21 -0400)
committersrs5694 <srs5694@users.sourceforge.net>
Sun, 27 Apr 2014 00:21:34 +0000 (20:21 -0400)
stanzas.

NEWS.txt
mok/security_policy.c
refind/config.c
refind/global.h
refind/lib.c
refind/lib.h
refind/main.c

index c0f1dcb3017919d36fc82b589fb8226b252dc6ec..a864e8ee22f9f3a062026ba48e348628943686b0 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,10 @@
 0.7.10 (?/??/2014):
 -------------------
 
 0.7.10 (?/??/2014):
 -------------------
 
+- 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:).
+
 - Fixed memory-allocation bug that could cause error message displays,
   and possibly hangs, when re-scanning boot loaders.
 
 - Fixed memory-allocation bug that could cause error message displays,
   and possibly hangs, when re-scanning boot loaders.
 
index 2d0d0d126851683473ba88612e62742e294e0a56..33d3be7cf647ea941dde2aa3f7c35c7be782b67c 100644 (file)
@@ -24,9 +24,6 @@ struct _EFI_SECURITY_PROTOCOL;
 struct _EFI_DEVICE_PATH_PROTOCOL;
 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL;
 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL;
 struct _EFI_DEVICE_PATH_PROTOCOL;
 typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL;
 typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL;
-#ifdef __MAKEWITH_GNUEFI
-typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL;
-#endif
 
 #if defined(EFIX64)
 #define MSABI __attribute__((ms_abi))
 
 #if defined(EFIX64)
 #define MSABI __attribute__((ms_abi))
index 447638f373f0350a4a08593c70949cdd56e84ae8..c1a7b5df209ca5a3724efe1ddcad6bc4e013fc96 100644 (file)
@@ -664,13 +664,18 @@ VOID ReadConfig(CHAR16 *FileName)
 // 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) {
 // 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;
+   UINTN     i = 0, CountedVolumes = 0, Length;
    INTN      Number = -1;
    INTN      Number = -1;
-   BOOLEAN   Found = FALSE;
+   BOOLEAN   Found = FALSE, IdIsGuid = FALSE;
+   EFI_GUID  VolGuid, NullGuid = NULL_GUID_VALUE;
 
 
-   if ((StrLen(Identifier) >= 2) && (Identifier[StrLen(Identifier) - 1] == L':') &&
+   VolGuid = StringAsGuid(Identifier);
+   Length = StrLen(Identifier);
+   if ((Length >= 2) && (Identifier[Length - 1] == L':') &&
        (Identifier[0] >= L'0') && (Identifier[0] <= L'9')) {
       Number = (INTN) Atoi(Identifier);
        (Identifier[0] >= L'0') && (Identifier[0] <= L'9')) {
       Number = (INTN) Atoi(Identifier);
+   } else if (IsGuid(Identifier)) {
+      IdIsGuid = TRUE;
    }
    while ((i < VolumesCount) && (!Found)) {
       if (Number >= 0) { // User specified a volume by number
    }
    while ((i < VolumesCount) && (!Found)) {
       if (Number >= 0) { // User specified a volume by number
@@ -681,11 +686,17 @@ static BOOLEAN FindVolume(REFIT_VOLUME **Volume, CHAR16 *Identifier) {
             }
             CountedVolumes++;
          } // if
             }
             CountedVolumes++;
          } // if
-      } else { // User specified a volume by label
+      } else { // User specified a volume by label or GUID
          if (StriCmp(Identifier, Volumes[i]->VolName) == 0) {
             *Volume = Volumes[i];
             Found = TRUE;
          } // if
          if (StriCmp(Identifier, Volumes[i]->VolName) == 0) {
             *Volume = Volumes[i];
             Found = TRUE;
          } // if
+         if (IdIsGuid && !Found) {
+            if (GuidsAreEqual(&VolGuid, &(Volumes[i]->PartGuid)) && !GuidsAreEqual(&NullGuid, &(Volumes[i]->PartGuid))) {
+               *Volume = Volumes[i];
+               Found = TRUE;
+            } // if
+         } // if
       } // if/else
       i++;
    } // while()
       } // if/else
       i++;
    } // while()
index 586ff9b5abd5079954562a10034079660c5fe193..5058d9d0c9979a36ebea9314adff9da1282242bb 100644 (file)
 // Files that may be Windows recovery files
 #define WINDOWS_RECOVERY_FILES  L"EFI\\Microsoft\\Boot\\LrsBootmgr.efi"
 
 // Files that may be Windows recovery files
 #define WINDOWS_RECOVERY_FILES  L"EFI\\Microsoft\\Boot\\LrsBootmgr.efi"
 
+#define NULL_GUID_VALUE { 00000000, 0000, 0000, {0000, 0000, 0000, 0000} };
+
 //
 // global definitions
 //
 //
 // global definitions
 //
@@ -173,6 +175,7 @@ typedef struct {
    EFI_FILE            *RootDir;
    CHAR16              *VolName;
    EFI_GUID            VolUuid;
    EFI_FILE            *RootDir;
    CHAR16              *VolName;
    EFI_GUID            VolUuid;
+   EFI_GUID            PartGuid;
    UINTN               VolNumber;
    EG_IMAGE            *VolIconImage;
    EG_IMAGE            *VolBadgeImage;
    UINTN               VolNumber;
    EG_IMAGE            *VolIconImage;
    EG_IMAGE            *VolBadgeImage;
index e45a226014a995ca76b6f0a89f48ab9f90df41b8..0053c2b51385037d61e5000096470fc26bf51bd5 100644 (file)
@@ -764,6 +764,19 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) {
    return FoundName;
 } // static CHAR16 *GetVolumeName()
 
    return FoundName;
 } // static CHAR16 *GetVolumeName()
 
+// Determine the unique GUID of the volume and store it.
+static VOID SetPartGuid(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *DevicePath) {
+   HARDDRIVE_DEVICE_PATH    *HdDevicePath;
+
+   if (Volume == NULL)
+      return;
+
+   if ((DevicePath->Type == MEDIA_DEVICE_PATH) && (DevicePath->SubType == MEDIA_HARDDRIVE_DP)) {
+      HdDevicePath = (HARDDRIVE_DEVICE_PATH*) DevicePath;
+      Volume->PartGuid = *((EFI_GUID*) HdDevicePath->Signature);
+   }
+} // VOID SetPartGuid()
+
 VOID ScanVolume(REFIT_VOLUME *Volume)
 {
     EFI_STATUS              Status;
 VOID ScanVolume(REFIT_VOLUME *Volume)
 {
     EFI_STATUS              Status;
@@ -805,6 +818,9 @@ VOID ScanVolume(REFIT_VOLUME *Volume)
     while (DevicePath != NULL && !IsDevicePathEndType(DevicePath)) {
         NextDevicePath = NextDevicePathNode(DevicePath);
 
     while (DevicePath != NULL && !IsDevicePathEndType(DevicePath)) {
         NextDevicePath = NextDevicePathNode(DevicePath);
 
+        if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH) {
+           SetPartGuid(Volume, DevicePath);
+        }
         if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH &&
             (DevicePathSubType(DevicePath) == MSG_USB_DP ||
              DevicePathSubType(DevicePath) == MSG_USB_CLASS_DP ||
         if (DevicePathType(DevicePath) == MESSAGING_DEVICE_PATH &&
             (DevicePathSubType(DevicePath) == MSG_USB_DP ||
              DevicePathSubType(DevicePath) == MSG_USB_CLASS_DP ||
@@ -966,7 +982,7 @@ VOID ScanVolumes(VOID)
     UINTN                   SectorSum, i, VolNumber = 0;
     UINT8                   *SectorBuffer1, *SectorBuffer2;
     EFI_GUID                *UuidList;
     UINTN                   SectorSum, i, VolNumber = 0;
     UINT8                   *SectorBuffer1, *SectorBuffer2;
     EFI_GUID                *UuidList;
-    EFI_GUID                NullUuid = { 00000000, 0000, 0000, {0000, 0000, 0000, 0000} };
+    EFI_GUID                NullUuid = NULL_GUID_VALUE;
 
     MyFreePool(Volumes);
     Volumes = NULL;
 
     MyFreePool(Volumes);
     Volumes = NULL;
@@ -1842,6 +1858,68 @@ BOOLEAN EjectMedia(VOID) {
    return (Ejected > 0);
 } // VOID EjectMedia()
 
    return (Ejected > 0);
 } // VOID EjectMedia()
 
+// Converts consecutive characters in the input string into a
+// number, interpreting the string as a hexadecimal number, starting
+// at the specified position and continuing for the specified number
+// of characters or until the end of the string, whichever is first.
+// NumChars must be between 1 and 16. Ignores invalid characters.
+UINT64 StrToHex(CHAR16 *Input, UINTN Pos, UINTN NumChars) {
+   UINT64 retval = 0x00;
+   UINTN  NumDone = 0;
+   CHAR16 a;
+
+   if ((Input == NULL) || (StrLen(Input) < Pos) || (NumChars == 0) || (NumChars > 16)) {
+      return 0;
+   }
+
+   while ((StrLen(Input) >= Pos) && (NumDone < NumChars)) {
+      a = Input[Pos];
+      if ((a >= '0') && (a <= '9')) {
+         retval *= 0x10;
+         retval += (a - '0');
+         NumDone++;
+      }
+      if ((a >= 'a') && (a <= 'f')) {
+         retval *= 0x10;
+         retval += (a - 'a' + 0x0a);
+         NumDone++;
+      }
+      if ((a >= 'A') && (a <= 'F')) {
+         retval *= 0x10;
+         retval += (a - 'A' + 0x0a);
+         NumDone++;
+      }
+      Pos++;
+   } // while()
+   return retval;
+} // StrToHex()
+
+// Returns TRUE if UnknownString can be interpreted as a GUID, FALSE otherwise.
+// Note that the input string must have no extraneous spaces and must be
+// conventionally formatted as a 36-character GUID, complete with dashes in
+// appropriate places.
+BOOLEAN IsGuid(CHAR16 *UnknownString) {
+   UINTN   Length, i;
+   BOOLEAN retval = TRUE;
+   CHAR16  a;
+
+   if (UnknownString == NULL)
+      return FALSE;
+
+   Length = StrLen(UnknownString);
+   if (Length != 36)
+      return FALSE;
+
+   for (i = 0; i < Length; i++) {
+      a = UnknownString[i];
+      if (((i == 8) || (i == 13) || (i == 18) || (i == 23)) && (a != '-')) {
+         retval = FALSE;
+      } else if (((a < 'a') || (a > 'f')) && ((a < 'A') || (a > 'F')) && ((a < '0') && (a > '9'))) {
+         retval = FALSE;
+      } // if/else
+   } // for
+   return retval;
+} // BOOLEAN IsGuid()
 
 // Return the GUID as a string, suitable for display to the user. Note that the calling
 // function is responsible for freeing the allocated memory.
 
 // Return the GUID as a string, suitable for display to the user. Note that the calling
 // function is responsible for freeing the allocated memory.
@@ -1858,3 +1936,34 @@ CHAR16 * GuidAsString(EFI_GUID *GuidData) {
    }
    return TheString;
 } // GuidAsString(EFI_GUID *GuidData)
    }
    return TheString;
 } // GuidAsString(EFI_GUID *GuidData)
+
+EFI_GUID StringAsGuid(CHAR16 * InString) {
+   EFI_GUID  Guid = NULL_GUID_VALUE;
+
+   if (!IsGuid(InString)) {
+      return Guid;
+   }
+
+   Guid.Data1 = (UINT32) StrToHex(InString, 0, 8);
+   Guid.Data2 = (UINT16) StrToHex(InString, 9, 4);
+   Guid.Data3 = (UINT16) StrToHex(InString, 14, 4);
+   Guid.Data4[0] = (UINT8) StrToHex(InString, 19, 2);
+   Guid.Data4[1] = (UINT8) StrToHex(InString, 21, 2);
+   Guid.Data4[2] = (UINT8) StrToHex(InString, 23, 2);
+   Guid.Data4[3] = (UINT8) StrToHex(InString, 26, 2);
+   Guid.Data4[4] = (UINT8) StrToHex(InString, 28, 2);
+   Guid.Data4[5] = (UINT8) StrToHex(InString, 30, 2);
+   Guid.Data4[6] = (UINT8) StrToHex(InString, 32, 2);
+   Guid.Data4[7] = (UINT8) StrToHex(InString, 34, 2);
+
+   return Guid;
+} // EFI_GUID StringAsGuid()
+
+// 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
index b0f555d73d5cbba7ce6782ecf48f99c102d479fc..bc3454cdbcd7ad913b96d5c08ff8bb4480d6ddbc 100644 (file)
 #ifdef __MAKEWITH_GNUEFI
 #include "efi.h"
 #include "efilib.h"
 #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()
 #else
 #include "../include/tiano_includes.h"
 #endif
 #else
 #include "../include/tiano_includes.h"
 #endif
@@ -123,6 +152,10 @@ VOID MyFreePool(IN OUT VOID *Pointer);
 
 BOOLEAN EjectMedia(VOID);
 
 
 BOOLEAN EjectMedia(VOID);
 
+UINT64 StrToHex(CHAR16 *Input, UINTN Position, UINTN NumChars);
+BOOLEAN IsGuid(CHAR16 *UnknownString);
 CHAR16 * GuidAsString(EFI_GUID *GuidData);
 CHAR16 * GuidAsString(EFI_GUID *GuidData);
+EFI_GUID StringAsGuid(CHAR16 * InString);
+BOOLEAN GuidsAreEqual(EFI_GUID *Guid1, EFI_GUID *Guid2);
 
 #endif
\ No newline at end of file
 
 #endif
\ No newline at end of file
index ae35fa3efef1686c628e0805afb9f2fa2f0422ba..25c7a5a1d8c632ad3e56d5ee824f61477da56023 100644 (file)
@@ -159,7 +159,7 @@ static VOID AboutrEFInd(VOID)
 {
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
 {
     if (AboutMenu.EntryCount == 0) {
         AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
-        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.7.9.1");
+        AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.7.9.2");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2014 Roderick W. Smith");
         AddMenuInfoLine(&AboutMenu, L"");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
         AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2014 Roderick W. Smith");