+ if (Volume->VolBadgeImage == NULL) {
+ Volume->VolBadgeImage = egLoadIconAnyType(Volume->RootDir, L"", L".VolumeBadge", GlobalConfig.IconSizes[ICON_SIZE_BADGE]);
+ }
+
+ if (Volume->VolBadgeImage == NULL) {
+ switch (Volume->DiskKind) {
+ case DISK_KIND_INTERNAL:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_INTERNAL);
+ break;
+ case DISK_KIND_EXTERNAL:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_EXTERNAL);
+ break;
+ case DISK_KIND_OPTICAL:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_OPTICAL);
+ break;
+ case DISK_KIND_NET:
+ Volume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_NET);
+ break;
+ } // switch()
+ }
+} // VOID SetVolumeBadgeIcon()
+
+// 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 *SizeInIEEEUnits()
+
+// Return a name for the volume. Ideally this should be the label for the
+// filesystem or volume, 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(REFIT_VOLUME *Volume) {
+ EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr = NULL;
+ CHAR16 *FoundName = NULL;
+ CHAR16 *SISize, *TypeName;
+
+ if (Volume->RootDir != NULL) {
+ FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
+ }
+
+ if ((FileSystemInfoPtr != NULL) && (FileSystemInfoPtr->VolumeLabel != NULL) &&
+ (StrLen(FileSystemInfoPtr->VolumeLabel) > 0)) {
+ FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
+ }
+
+ // 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) && (FileSystemInfoPtr != NULL)) {
+ 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)
+
+ MyFreePool(FileSystemInfoPtr);
+
+ if (FoundName == NULL) {
+ 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", TypeName);
+ 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 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()
+
+// Determine the unique GUID, type code GUID, and name of the volume and store them.
+static VOID SetPartGuidAndName(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *DevicePath) {
+ HARDDRIVE_DEVICE_PATH *HdDevicePath;
+ GPT_ENTRY *PartInfo;
+
+ if ((Volume == NULL) || (DevicePath == NULL))
+ return;
+
+ if ((DevicePath->Type == MEDIA_DEVICE_PATH) && (DevicePath->SubType == MEDIA_HARDDRIVE_DP)) {
+ HdDevicePath = (HARDDRIVE_DEVICE_PATH*) DevicePath;
+ if (HdDevicePath->SignatureType == SIGNATURE_TYPE_GUID) {
+ Volume->PartGuid = *((EFI_GUID*) HdDevicePath->Signature);
+ PartInfo = FindPartWithGuid(&(Volume->PartGuid));
+ if (PartInfo) {
+ Volume->PartName = StrDuplicate(PartInfo->name);
+ CopyMem(&(Volume->PartTypeGuid), PartInfo->type_guid, sizeof(EFI_GUID));
+ if (GuidsAreEqual(&(Volume->PartTypeGuid), &gFreedesktopRootGuid) &&
+ ((PartInfo->attributes & GPT_NO_AUTOMOUNT) == 0)) {
+ GlobalConfig.DiscoveredRoot = Volume;
+ } // if (GUIDs match && automounting OK)
+ Volume->IsMarkedReadOnly = ((PartInfo->attributes & GPT_READ_ONLY) > 0);
+ } // if (PartInfo exists)
+ } // if (GPT disk)
+ } // if (disk device)
+} // VOID SetPartGuid()
+
+// Return TRUE if NTFS boot files are found or if Volume is unreadable,
+// FALSE otherwise. The idea is to weed out non-boot NTFS volumes from
+// BIOS/legacy boot list on Macs. We can't assume NTFS will be readable,
+// so return TRUE if it's unreadable; but if it IS readable, return
+// TRUE only if Windows boot files are found.
+static BOOLEAN HasWindowsBiosBootFiles(REFIT_VOLUME *Volume) {
+ BOOLEAN FilesFound = TRUE;
+
+ if (Volume->RootDir != NULL) {
+ FilesFound = FileExists(Volume->RootDir, L"NTLDR") || // Windows NT/200x/XP boot file
+ FileExists(Volume->RootDir, L"bootmgr"); // Windows Vista/7/8 boot file
+ } // if
+ return FilesFound;
+} // static VOID HasWindowsBiosBootFiles()
+
+VOID ScanVolume(REFIT_VOLUME *Volume)