]> code.delx.au - refind/blobdiff - refind/lib.c
New FreeBSD GPT BIOS-mode boot loader detection code. Also,
[refind] / refind / lib.c
index 08550e26b2964f6d0df1cdd5d16d59ec18171267..19e140a414259fe3f57a9ad5cd67dd8745fb8440 100644 (file)
@@ -436,6 +436,9 @@ static CHAR16 *FSTypeName(IN UINT32 TypeCode) {
    CHAR16 *retval = NULL;
 
    switch (TypeCode) {
+      case FS_TYPE_WHOLEDISK:
+         retval = L" whole disk";
+         break;
       case FS_TYPE_FAT:
          retval = L" FAT";
          break;
@@ -485,26 +488,35 @@ static VOID SetFilesystemData(IN UINT8 *Buffer, IN UINTN BufferSize, IN OUT REFI
    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) {
             MagicString = (char*) (Buffer + 3);
-            if (CompareMem(MagicString, NTFS_SIGNATURE, 8) == 0) {
+            // 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 {
-               // NOTE: This misidentifies a whole disk as a FAT partition
-               // because FAT and MBR share the same 0xaa55 "magic" and
-               // no other distinguishing data. Later code, in ScanVolume(),
-               // resets to FS_TYPE_UNKNOWN if the "filesystem" can't be
-               // read.
-               Volume->FSType = FS_TYPE_FAT;
-            }
+               RootDir = LibOpenRoot(Volume->DeviceHandle);
+               if (RootDir != NULL)
+                  Volume->FSType = FS_TYPE_FAT;
+            } // if/elseif/else
             return;
          } // if
       } // search for FAT and NTFS magic
@@ -581,7 +593,11 @@ static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
                                  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;
@@ -618,6 +634,15 @@ static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
             Volume->OSIconName = L"freebsd";
             Volume->OSName = L"FreeBSD";
 
+        // If more differentiation needed, also search for
+        // "Invalid partition table" &/or "Missing boot loader".
+        } else if ((*((UINT16 *)(Buffer + 510)) == 0xaa55) &&
+                   (FindMem(Buffer, SECTOR_SIZE, "Boot loader too large", 21) >= 0) &&
+                   (FindMem(Buffer, SECTOR_SIZE, "I/O error loading boot loader", 29) >= 0))  {
+            Volume->HasBootCode = TRUE;
+            Volume->OSIconName = L"freebsd";
+            Volume->OSName = L"FreeBSD";
+
         } else if (FindMem(Buffer, 512, "!Loading", 8) >= 0 ||
                    FindMem(Buffer, SECTOR_SIZE, "/cdboot\0/CDBOOT\0", 16) >= 0) {
             Volume->HasBootCode = TRUE;
@@ -630,14 +655,16 @@ static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
             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 ||
@@ -769,7 +796,7 @@ static CHAR16 *SizeInIEEEUnits(UINT64 SizeInBytes) {
 } // 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
@@ -788,13 +815,6 @@ static CHAR16 *GetVolumeName(REFIT_VOLUME *Volume) {
       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)) {
@@ -835,7 +855,7 @@ static CHAR16 *GetVolumeName(REFIT_VOLUME *Volume) {
    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;
 
@@ -851,16 +871,17 @@ static VOID SetPartGuidAndName(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *D
    } // if
 } // VOID SetPartGuid()
 
-// Return TRUE if NTFS boot files are found, FALSE otherwise.
-// Assumes Volume is already mounted.
+// 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 XP boot files
-                    FileExists(Volume->RootDir, L"ntdetect.com") &&
-                    FileExists(Volume->RootDir, L"boot.ini")) ||
-                   FileExists(Volume->RootDir, L"Windows");           // Windows 7 ID (imperfect; TODO: Improve)
+      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()
@@ -986,18 +1007,20 @@ VOID ScanVolume(REFIT_VOLUME *Volume)
 
    if (Volume->RootDir == NULL) {
       Volume->IsReadable = FALSE;
-      if (Volume->FSType != FS_TYPE_NTFS)
-          Volume->FSType = FS_TYPE_UNKNOWN;
       return;
    } else {
       Volume->IsReadable = TRUE;
-      if ((Volume->FSType == FS_TYPE_NTFS) && Volume->HasBootCode)
+      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]);
+   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)