+// 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) {
+ UINT64 SizeInIeee;
+ UINTN Index = 0, NumPrefixes;
+ CHAR16 *Units, *Prefixes = L" KMGTPEZ";
+ CHAR16 *TheValue;
+
+ TheValue = AllocateZeroPool(sizeof(CHAR16) * 256);
+ if (TheValue != NULL) {
+ NumPrefixes = StrLen(Prefixes);
+ SizeInIeee = SizeInBytes;
+ while ((SizeInIeee > 1024) && (Index < (NumPrefixes - 1))) {
+ Index++;
+ SizeInIeee /= 1024;
+ } // while
+ if (Prefixes[Index] == ' ') {
+ Units = StrDuplicate(L"-byte");
+ } else {
+ Units = StrDuplicate(L" iB");
+ Units[1] = Prefixes[Index];
+ } // if/else
+ SPrint(TheValue, 255, L"%ld%s", SizeInIeee, Units);
+ } // if
+ return TheValue;
+} // CHAR16 *SizeInSIUnits()
+
+// Return a name for the volume. Ideally this should be the label for the
+// filesystem it contains, but this function falls back to describing the
+// filesystem by size (200 MiB, etc.) and/or type (ext2, HFS+, etc.), if
+// 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) {
+ EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr;
+ CHAR16 *FoundName = NULL;
+ CHAR16 *SISize, *TypeName;
+
+ FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
+ if (FileSystemInfoPtr != NULL) { // we have filesystem information (size, label)....
+ if ((FileSystemInfoPtr->VolumeLabel != NULL) && (StrLen(FileSystemInfoPtr->VolumeLabel) > 0)) {
+ FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
+ }
+
+ // Special case: 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
+ FoundName = AllocateZeroPool(sizeof(CHAR16) * 256);
+ if (FoundName != NULL) {
+ SISize = SizeInIEEEUnits(FileSystemInfoPtr->VolumeSize);
+ SPrint(FoundName, 255, L"%s%s volume", SISize, FSTypeName(Volume->FSType));
+ MyFreePool(SISize);
+ } // if allocated memory OK
+ } // if (FoundName == NULL)
+
+ FreePool(FileSystemInfoPtr);
+
+ } 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; function returns constant
+ if (StrLen(TypeName) > 0)
+ SPrint(FoundName, 255, L"%s volume", FSTypeName(Volume->FSType));
+ else
+ SPrint(FoundName, 255, L"unknown volume");
+ } // if allocated memory OK
+ } // if
+
+ // TODO: Above could be improved/extended, in case filesystem name is not found,
+ // such as:
+ // - use partition label
+ // - use or add disk/partition number (e.g., "(hd0,2)")
+
+ // Desperate fallback name....
+ if (FoundName == NULL) {
+ FoundName = StrDuplicate(L"unknown volume");
+ }
+ return FoundName;
+} // static CHAR16 *GetVolumeName()
+
+VOID ScanVolume(REFIT_VOLUME *Volume)