]> code.delx.au - refind/blobdiff - refind/lib.c
New ability to specify volume labels in "dont_scan_dirs" token to
[refind] / refind / lib.c
index 048b301e099637e40ae5991802b8b326ff0af2b3..3c9e4c4b66a4d28beb4bb056970cd2ae1cbc66f7 100644 (file)
@@ -469,7 +469,7 @@ static UINT32 IdentifyFilesystemType(IN UINT8 *Buffer, IN UINTN BufferSize) {
    return FoundType;
 }
 
-static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootable)
+static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
 {
     EFI_STATUS              Status;
     UINT8                   Buffer[SAMPLE_SIZE];
@@ -624,7 +624,7 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl
         CheckError(Status, L"while reading boot sector");
 #endif
     }
-}
+} /* VOID ScanVolumeBootcode() */
 
 // default volume badge icon based on disk kind
 static VOID ScanVolumeDefaultIcon(IN OUT REFIT_VOLUME *Volume)
@@ -645,17 +645,18 @@ static VOID ScanVolumeDefaultIcon(IN OUT REFIT_VOLUME *Volume)
 // Return a string representing the input size in IEEE-1541 units.
 // The calling function is responsible for freeing the allocated memory.
 static CHAR16 *SizeInIEEEUnits(UINT64 SizeInBytes) {
-   float SizeInIeee;
-   UINTN Index = 0;
+   UINT64 SizeInIeee;
+   UINTN Index = 0, NumPrefixes;
    CHAR16 *Units, *Prefixes = L" KMGTPEZ";
    CHAR16 *TheValue;
 
-   TheValue = AllocateZeroPool(sizeof(CHAR16) * 80);
+   TheValue = AllocateZeroPool(sizeof(CHAR16) * 256);
    if (TheValue != NULL) {
-      SizeInIeee = (float) SizeInBytes;
-      while ((SizeInIeee > 1024.0) && (Index < (StrLen(Prefixes) - 1))) {
+      NumPrefixes = StrLen(Prefixes);
+      SizeInIeee = SizeInBytes;
+      while ((SizeInIeee > 1024) && (Index < (NumPrefixes - 1))) {
          Index++;
-         SizeInIeee /= 1024.0;
+         SizeInIeee /= 1024;
       } // while
       if (Prefixes[Index] == ' ') {
          Units = StrDuplicate(L"-byte");
@@ -663,7 +664,7 @@ static CHAR16 *SizeInIEEEUnits(UINT64 SizeInBytes) {
          Units = StrDuplicate(L"  iB");
          Units[1] = Prefixes[Index];
       } // if/else
-      SPrint(TheValue, 79, L"%d%s", (UINTN) SizeInIeee, Units);
+      SPrint(TheValue, 255, L"%ld%s", SizeInIeee, Units);
    } // if
    return TheValue;
 } // CHAR16 *SizeInSIUnits()
@@ -680,7 +681,7 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) {
    CHAR16                  *SISize, *TypeName;
 
    FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
-   if (FileSystemInfoPtr != NULL) {
+   if (FileSystemInfoPtr != NULL) { // we have filesystem information (size, label)....
        if ((FileSystemInfoPtr->VolumeLabel != NULL) && (StrLen(FileSystemInfoPtr->VolumeLabel) > 0)) {
           FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
        }
@@ -692,7 +693,7 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) {
           FoundName = NULL;
        } // if rEFInd HFS+ driver suspected
 
-       if (FoundName == NULL) { // filesystem has no name....
+       if (FoundName == NULL) { // filesystem has no name, so use fs type and size
           FoundName = AllocateZeroPool(sizeof(CHAR16) * 256);
           if (FoundName != NULL) {
              SISize = SizeInIEEEUnits(FileSystemInfoPtr->VolumeSize);
@@ -703,10 +704,10 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) {
 
        FreePool(FileSystemInfoPtr);
 
-   } else {
+   } else { // fs driver not returning info; fall back on our own information....
       FoundName = AllocateZeroPool(sizeof(CHAR16) * 256);
       if (FoundName != NULL) {
-         TypeName = FSTypeName(Volume->FSType); // NOTE: Don't free TypeName; fn returns constant
+         TypeName = FSTypeName(Volume->FSType); // NOTE: Don't free TypeName; function returns constant
          if (StrLen(TypeName) > 0)
             SPrint(FoundName, 255, L"%s volume", FSTypeName(Volume->FSType));
          else
@@ -726,7 +727,7 @@ static CHAR16 *GetVolumeName(IN REFIT_VOLUME *Volume) {
    return FoundName;
 } // static CHAR16 *GetVolumeName()
 
-VOID ScanVolume(IN OUT REFIT_VOLUME *Volume)
+VOID ScanVolume(REFIT_VOLUME *Volume)
 {
     EFI_STATUS              Status;
     EFI_DEVICE_PATH         *DevicePath, *NextDevicePath;
@@ -915,7 +916,7 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I
             }
         }
     }
-}
+} /* VOID ScanExtendedPartition() */
 
 VOID ScanVolumes(VOID)
 {
@@ -928,7 +929,7 @@ VOID ScanVolumes(VOID)
     MBR_PARTITION_INFO      *MbrTable;
     UINTN                   PartitionIndex;
     UINT8                   *SectorBuffer1, *SectorBuffer2;
-    UINTN                   SectorSum, i;
+    UINTN                   SectorSum, i, VolNumber = 0;
 
     MyFreePool(Volumes);
     Volumes = NULL;
@@ -948,6 +949,8 @@ VOID ScanVolumes(VOID)
         Volume = AllocateZeroPool(sizeof(REFIT_VOLUME));
         Volume->DeviceHandle = Handles[HandleIndex];
         ScanVolume(Volume);
+        if (Volume->IsReadable)
+           Volume->VolNumber = VolNumber++;
 
         AddListElement((VOID ***) &Volumes, &VolumesCount, Volume);
 
@@ -1030,7 +1033,7 @@ VOID ScanVolumes(VOID)
             MyFreePool(SectorBuffer2);
         }
 
-    }
+    } // for
 } /* VOID ScanVolumes() */
 
 static VOID UninitVolumes(VOID)
@@ -1375,8 +1378,8 @@ BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) {
 
 // Merges two strings, creating a new one and returning a pointer to it.
 // If AddChar != 0, the specified character is placed between the two original
-// strings (unless the first string is NULL). The original input string
-// *First is de-allocated and replaced by the new merged string.
+// strings (unless the first string is NULL or empty). The original input
+// string *First is de-allocated and replaced by the new merged string.
 // This is similar to StrCat, but safer and more flexible because
 // MergeStrings allocates memory that's the correct size for the
 // new merged string, so it can take a NULL *First and it cleans
@@ -1392,6 +1395,10 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
       Length2 = StrLen(Second);
    NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2));
    if (NewString != NULL) {
+      if ((*First != NULL) && (StrLen(*First) == 0)) {
+         MyFreePool(*First);
+         *First = NULL;
+      }
       NewString[0] = L'\0';
       if (*First != NULL) {
          StrCat(NewString, *First);
@@ -1515,6 +1522,39 @@ VOID FindVolumeAndFilename(IN EFI_DEVICE_PATH *loadpath, OUT REFIT_VOLUME **Devi
    MyFreePool(DeviceString);
 } // VOID FindVolumeAndFilename()
 
+// Splits a volume/filename string (e.g., "fs0:\EFI\BOOT") into separate
+// volume and filename components (e.g., "fs0" and "\EFI\BOOT"), returning
+// the filename component in the original *Path variable and the split-off
+// volume component in the *VolName variable.
+// Returns TRUE if both components are found, FALSE otherwise.
+BOOLEAN SplitVolumeAndFilename(IN OUT CHAR16 **Path, OUT CHAR16 **VolName) {
+   UINTN i = 0, Length;
+   CHAR16 *Filename;
+
+   if (*Path == NULL)
+      return FALSE;
+
+   if (*VolName != NULL) {
+      MyFreePool(*VolName);
+      *VolName = NULL;
+   }
+
+   Length = StrLen(*Path);
+   while ((i < Length) && ((*Path)[i] != L':')) {
+      i++;
+   } // while
+
+   if (i < Length) {
+      Filename = StrDuplicate((*Path) + i + 1);
+      (*Path)[i] = 0;
+      *VolName = *Path;
+      *Path = Filename;
+      return TRUE;
+   } else {
+      return FALSE;
+   }
+} // BOOLEAN SplitVolumeAndFilename()
+
 // Returns all the digits in the input string, including intervening
 // non-digit characters. For instance, if InString is "foo-3.3.4-7.img",
 // this function returns "3.3.4-7". If InString contains no digits,
@@ -1631,18 +1671,18 @@ BOOLEAN EjectMedia(VOID) {
 } // VOID EjectMedia()
 
 
-// // Return the GUID as a string, suitable for display to the user. Note that the calling
-// // function is responsible for freeing the allocated memory.
-// CHAR16 * GuidAsString(EFI_GUID *GuidData) {
-//    CHAR16 *TheString;
-// 
-//    TheString = AllocateZeroPool(42 * sizeof(CHAR16));
-//    if (TheString != 0) {
-//       SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-//               (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
-//               (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
-//               (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
-//               (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
-//    }
-//    return TheString;
-// } // GuidAsString(EFI_GUID *GuidData)
+// Return the GUID as a string, suitable for display to the user. Note that the calling
+// function is responsible for freeing the allocated memory.
+CHAR16 * GuidAsString(EFI_GUID *GuidData) {
+   CHAR16 *TheString;
+
+   TheString = AllocateZeroPool(42 * sizeof(CHAR16));
+   if (TheString != 0) {
+      SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+              (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
+              (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
+              (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
+              (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
+   }
+   return TheString;
+} // GuidAsString(EFI_GUID *GuidData)