* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
- * Modifications copyright (c) 2012-2014 Roderick W. Smith
+ * Modifications copyright (c) 2012-2015 Roderick W. Smith
*
* Modifications distributed under the terms of the GNU General Public
* License (GPL) version 3 (GPLv3), a copy of which must be distributed
#include "../include/refit_call_wrapper.h"
#include "../include/RemovableMedia.h"
#include "gpt.h"
+#include "config.h"
#ifdef __MAKEWITH_GNUEFI
#define EfiReallocatePool ReallocatePool
#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
#define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs"
#define BTRFS_SIGNATURE "_BHRfS_M"
+#define NTFS_SIGNATURE "NTFS "
// variables
CHAR16 *retval = NULL;
switch (TypeCode) {
+ case FS_TYPE_WHOLEDISK:
+ retval = L" whole disk";
+ break;
case FS_TYPE_FAT:
retval = L" FAT";
break;
case FS_TYPE_ISO9660:
retval = L" ISO-9660";
break;
+ case FS_TYPE_NTFS:
+ retval = L" NTFS";
+ break;
default:
retval = L"";
break;
} // CHAR16 *FSTypeName()
// Identify the filesystem type and record the filesystem's UUID/serial number,
-// if possible. Expects a Buffer containing the first few (normally 4096) bytes
-// of the filesystem. Sets the filesystem type code in Volume->FSType and the
-// UUID/serial number in Volume->VolUuid. Note that the UUID value is recognized
-// differently for each filesystem, and is currently supported only for
-// ext2/3/4fs and ReiserFS. If the UUID can't be determined, it's set to 0. Also, the UUID
-// is just read directly into memory; it is *NOT* valid when displayed by
-// GuidAsString() or used in other GUID/UUID-manipulating functions. (As I
-// write, it's being used merely to detect partitions that are part of a
-// RAID 1 array.)
+// if possible. Expects a Buffer containing the first few (normally at least
+// 4096) bytes of the filesystem. Sets the filesystem type code in Volume->FSType
+// and the UUID/serial number in Volume->VolUuid. Note that the UUID value is
+// recognized differently for each filesystem, and is currently supported only
+// for NTFS, ext2/3/4fs, and ReiserFS (and for NTFS it's really a 64-bit serial
+// number not a UUID or GUID). If the UUID can't be determined, it's set to 0.
+// Also, the UUID is just read directly into memory; it is *NOT* valid when
+// displayed by GuidAsString() or used in other GUID/UUID-manipulating
+// functions. (As I write, it's being used merely to detect partitions that are
+// part of a RAID 1 array.)
static VOID SetFilesystemData(IN UINT8 *Buffer, IN UINTN BufferSize, IN OUT REFIT_VOLUME *Volume) {
UINT32 *Ext2Incompat, *Ext2Compat;
UINT16 *Magic16;
char *MagicString;
+ EFI_FILE *RootDir;
if ((Buffer != NULL) && (Volume != NULL)) {
SetMem(&(Volume->VolUuid), sizeof(EFI_GUID), 0);
Volume->FSType = FS_TYPE_UNKNOWN;
if (BufferSize >= 512) {
+
+ // Search for NTFS, FAT, and MBR/EBR.
+ // These all have 0xAA55 at the end of the first sector, but FAT and
+ // MBR/EBR are not easily distinguished. Thus, we first check to see
+ // if the "volume" is in fact a disk device; then look for NTFS
+ // "magic"; and then check to see if the volume can be mounted, thus
+ // relying on the EFI's built-in FAT driver to identify FAT.
Magic16 = (UINT16*) (Buffer + 510);
if (*Magic16 == FAT_MAGIC) {
- Volume->FSType = FS_TYPE_FAT;
+ MagicString = (char*) (Buffer + 3);
+ // Confusingly, "LogicalPartition" refers to the presence of a
+ // partition table, not an MBR logical partition.
+ if (Volume->BlockIO->Media->LogicalPartition) {
+ Volume->FSType = FS_TYPE_WHOLEDISK;
+ } else if (CompareMem(MagicString, NTFS_SIGNATURE, 8) == 0) {
+ Volume->FSType = FS_TYPE_NTFS;
+ CopyMem(&(Volume->VolUuid), Buffer + 0x48, sizeof(UINT64));
+ } else {
+ RootDir = LibOpenRoot(Volume->DeviceHandle);
+ if (RootDir != NULL)
+ Volume->FSType = FS_TYPE_FAT;
+ } // if/elseif/else
return;
} // if
- } // search for FAT magic
+ } // search for FAT and NTFS magic
if (BufferSize >= (1024 + 100)) {
Magic16 = (UINT16*) (Buffer + 1024 + 56);
return;
}
} // search for HFS+ magic
+
} // if (Buffer != NULL)
} // UINT32 SetFilesystemData()
Volume->BlockIOOffset, SAMPLE_SIZE, Buffer);
if (!EFI_ERROR(Status)) {
- SetFilesystemData(Buffer, SAMPLE_SIZE, Volume);
+// if (Volume->BlockIO->Media->LogicalPartition)
+// Print(L"Skipping; whole disk!\n");
+// else
+ SetFilesystemData(Buffer, SAMPLE_SIZE, Volume);
+// PauseForKey();
if ((*((UINT16 *)(Buffer + 510)) == 0xaa55 && Buffer[0] != 0) && (FindMem(Buffer, 512, "EXFAT", 5) == -1)) {
*Bootable = TRUE;
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"netbsd";
Volume->OSName = L"NetBSD";
+ // Windows NT/200x/XP
} else if (FindMem(Buffer, SECTOR_SIZE, "NTLDR", 5) >= 0) {
Volume->HasBootCode = TRUE;
Volume->OSIconName = L"win";
Volume->OSName = L"Windows";
+ // Windows Vista/7/8
} else if (FindMem(Buffer, SECTOR_SIZE, "BOOTMGR", 7) >= 0) {
Volume->HasBootCode = TRUE;
- Volume->OSIconName = L"winvista,win";
+ Volume->OSIconName = L"win8,win";
Volume->OSName = L"Windows";
} else if (FindMem(Buffer, 512, "CPUBOOT SYS", 11) >= 0 ||
}
// NOTE: If you add an operating system with a name that starts with 'W' or 'L', you
- // need to fix AddLegacyEntry in main.c.
+ // need to fix AddLegacyEntry in refind/legacy.c.
#if REFIT_DEBUG > 0
Print(L" Result of bootcode detection: %s %s (%s)\n",
// Set default volume badge icon based on /.VolumeBadge.{icns|png} file or disk kind
VOID SetVolumeBadgeIcon(REFIT_VOLUME *Volume)
{
+ if (GlobalConfig.HideUIFlags & HIDEUI_FLAG_BADGES)
+ return;
+
if (Volume->VolBadgeImage == NULL) {
Volume->VolBadgeImage = egLoadIconAnyType(Volume->RootDir, L"", L".VolumeBadge", GlobalConfig.IconSizes[ICON_SIZE_BADGE]);
}
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()
} // CHAR16 *SizeInIEEEUnits()
// 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 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
FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
}
- // 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 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)) {
return FoundName;
} // static CHAR16 *GetVolumeName()
-// Determine the unique GUID of the volume and store it.
+// Determine the unique GUID and name of the volume and store them.
static VOID SetPartGuidAndName(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *DevicePath) {
HARDDRIVE_DEVICE_PATH *HdDevicePath;
} // if
} // 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)
{
EFI_STATUS Status;
DevicePath = NextDevicePath;
} // while
- if (!Bootable) {
+ if (!Bootable) {
#if REFIT_DEBUG > 0
- if (Volume->HasBootCode)
- Print(L" Volume considered non-bootable, but boot code is present\n");
+ if (Volume->HasBootCode)
+ Print(L" Volume considered non-bootable, but boot code is present\n");
#endif
- Volume->HasBootCode = FALSE;
- }
+ Volume->HasBootCode = FALSE;
+ }
- // open the root directory of the volume
- Volume->RootDir = LibOpenRoot(Volume->DeviceHandle);
+ // open the root directory of the volume
+ Volume->RootDir = LibOpenRoot(Volume->DeviceHandle);
- // Set volume icon based on .VolumeBadge icon or disk kind
- SetVolumeBadgeIcon(Volume);
+ // Set volume icon based on .VolumeBadge icon or disk kind
+ SetVolumeBadgeIcon(Volume);
- Volume->VolName = GetVolumeName(Volume);
+ Volume->VolName = GetVolumeName(Volume);
- if (Volume->RootDir == NULL) {
- Volume->IsReadable = FALSE;
- return;
- } else {
- Volume->IsReadable = TRUE;
- }
+ if (Volume->RootDir == NULL) {
+ Volume->IsReadable = FALSE;
+ return;
+ } else {
+ Volume->IsReadable = TRUE;
+ if ((GlobalConfig.LegacyType == LEGACY_TYPE_MAC) && (Volume->FSType == FS_TYPE_NTFS) && Volume->HasBootCode) {
+ // VBR boot code found on NTFS, but volume is not actually bootable
+ // unless there are actual boot file, so check for them....
+ Volume->HasBootCode = HasWindowsBiosBootFiles(Volume);
+ }
+ } // if/else
- // get custom volume icons if present
- if (!Volume->VolIconImage)
- Volume->VolIconImage = egLoadIconAnyType(Volume->RootDir, L"", L".VolumeIcon", GlobalConfig.IconSizes[ICON_SIZE_BIG]);
+ // get custom volume icons if present
+ if (!Volume->VolIconImage) {
+ Volume->VolIconImage = egLoadIconAnyType(Volume->RootDir, L"", L".VolumeIcon", GlobalConfig.IconSizes[ICON_SIZE_BIG]);
+ }
} // ScanVolume()
static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_INFO *MbrEntry)