]> code.delx.au - refind/blobdiff - refind/lib.c
Added feature to detect the root (/) Linux filesystem based on
[refind] / refind / lib.c
index 19e140a414259fe3f57a9ad5cd67dd8745fb8440..7d2a573f755a86cb8fc1370c42e71935449818ef 100644 (file)
@@ -50,6 +50,7 @@
 #include "../include/RemovableMedia.h"
 #include "gpt.h"
 #include "config.h"
+#include "../EfiLib/LegacyBios.h"
 
 #ifdef __MAKEWITH_GNUEFI
 #define EfiReallocatePool ReallocatePool
@@ -75,6 +76,7 @@ EFI_DEVICE_PATH EndDevicePath[] = {
 #define REISER2FS_SUPER_MAGIC_STRING     "ReIsEr2Fs"
 #define REISER2FS_JR_SUPER_MAGIC_STRING  "ReIsEr3Fs"
 #define BTRFS_SIGNATURE                  "_BHRfS_M"
+#define XFS_SIGNATURE                    "XFSB"
 #define NTFS_SIGNATURE                   "NTFS    "
 
 // variables
@@ -460,6 +462,9 @@ static CHAR16 *FSTypeName(IN UINT32 TypeCode) {
       case FS_TYPE_BTRFS:
          retval = L" Btrfs";
          break;
+      case FS_TYPE_XFS:
+         retval = L" XFS";
+         break;
       case FS_TYPE_ISO9660:
          retval = L" ISO-9660";
          break;
@@ -494,33 +499,6 @@ static VOID SetFilesystemData(IN UINT8 *Buffer, IN UINTN BufferSize, IN OUT REFI
       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);
-            // 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 and NTFS magic
-
       if (BufferSize >= (1024 + 100)) {
          Magic16 = (UINT16*) (Buffer + 1024 + 56);
          if (*Magic16 == EXT2_SUPER_MAGIC) { // ext2/3/4
@@ -557,6 +535,14 @@ static VOID SetFilesystemData(IN UINT8 *Buffer, IN UINTN BufferSize, IN OUT REFI
          } // if
       } // search for Btrfs magic
 
+      if (BufferSize >= 512) {
+         MagicString = (char*) Buffer;
+         if (CompareMem(MagicString, XFS_SIGNATURE, 4) == 0) {
+            Volume->FSType = FS_TYPE_XFS;
+            return;
+         }
+      } // search for XFS magic
+
       if (BufferSize >= (1024 + 2)) {
          Magic16 = (UINT16*) (Buffer + 1024);
          if ((*Magic16 == HFSPLUS_MAGIC1) || (*Magic16 == HFSPLUS_MAGIC2)) {
@@ -565,7 +551,39 @@ static VOID SetFilesystemData(IN UINT8 *Buffer, IN UINTN BufferSize, IN OUT REFI
          }
       } // search for HFS+ magic
 
-   } // if (Buffer != NULL)
+      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 look for NTFS
+         // "magic"; then check to see if the volume can be mounted, thus
+         // relying on the EFI's built-in FAT driver to identify FAT; and then
+         // check to see if the "volume" is in fact a whole-disk device.
+         Magic16 = (UINT16*) (Buffer + 510);
+         if (*Magic16 == FAT_MAGIC) {
+            MagicString = (char*) (Buffer + 3);
+            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;
+               } else if (!Volume->BlockIO->Media->LogicalPartition) {
+                  Volume->FSType = FS_TYPE_WHOLEDISK;
+               } // if/elseif/else
+            } // if/else
+            return;
+         } // if
+      } // search for FAT and NTFS magic
+
+      // If no other filesystem is identified and block size is right, assume
+      // it's ISO-9660....
+      if (Volume->BlockIO->Media->BlockSize == 2048) {
+          Volume->FSType = FS_TYPE_ISO9660;
+          return;
+      }
+
+   } // if ((Buffer != NULL) && (Volume != NULL))
 
 } // UINT32 SetFilesystemData()
 
@@ -592,12 +610,9 @@ static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
                                  Volume->BlockIO, Volume->BlockIO->Media->MediaId,
                                  Volume->BlockIOOffset, SAMPLE_SIZE, Buffer);
     if (!EFI_ERROR(Status)) {
-
-//         if (Volume->BlockIO->Media->LogicalPartition)
-//            Print(L"Skipping; whole disk!\n");
-//         else
-           SetFilesystemData(Buffer, SAMPLE_SIZE, Volume);
-//        PauseForKey();
+        SetFilesystemData(Buffer, SAMPLE_SIZE, Volume);
+    }
+    if ((Status == EFI_SUCCESS) && (GlobalConfig.LegacyType == LEGACY_TYPE_MAC)) {
         if ((*((UINT16 *)(Buffer + 510)) == 0xaa55 && Buffer[0] != 0) && (FindMem(Buffer, 512, "EXFAT", 5) == -1)) {
             *Bootable = TRUE;
             Volume->HasBootCode = TRUE;
@@ -617,15 +632,6 @@ static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
             Volume->OSIconName = L"grub,linux";
             Volume->OSName = L"Linux";
 
-//         // Below doesn't produce a bootable entry, so commented out for the moment....
-//         // GRUB in BIOS boot partition:
-//         } else if (FindMem(Buffer, 512, "Geom\0Read\0 Error", 16) >= 0) {
-//             Volume->HasBootCode = TRUE;
-//             Volume->OSIconName = L"grub,linux";
-//             Volume->OSName = L"Linux";
-//             Volume->VolName = L"BIOS Boot Partition";
-//             *Bootable = TRUE;
-
         } else if ((*((UINT32 *)(Buffer + 502)) == 0 &&
                     *((UINT32 *)(Buffer + 506)) == 50000 &&
                     *((UINT16 *)(Buffer + 510)) == 0xaa55) ||
@@ -855,20 +861,30 @@ static CHAR16 *GetVolumeName(REFIT_VOLUME *Volume) {
    return FoundName;
 } // static CHAR16 *GetVolumeName()
 
-// Determine the unique GUID and name of the volume and store them.
+// 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)
+   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);
-         Volume->PartName = PartNameFromGuid(&(Volume->PartGuid));
-      } // if
-   } // if
+         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)) {
+                GlobalConfig.DiscoveredRoot = Volume;
+                Print(L"Found match!\n");
+                PauseForKey();
+             } // if (GUIDs match)
+         } // if (PartInfo exists)
+      } // if (GPT disk)
+   } // if (disk device)
 } // VOID SetPartGuid()
 
 // Return TRUE if NTFS boot files are found or if Volume is unreadable,
@@ -1288,15 +1304,17 @@ VOID ReinitVolumes(VOID)
 
 BOOLEAN FileExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath)
 {
-    EFI_STATUS         Status;
-    EFI_FILE_HANDLE    TestFile;
-
-    Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &TestFile, RelativePath, EFI_FILE_MODE_READ, 0);
-    if (Status == EFI_SUCCESS) {
-        refit_call1_wrapper(TestFile->Close, TestFile);
-        return TRUE;
-    }
-    return FALSE;
+   EFI_STATUS         Status;
+   EFI_FILE_HANDLE    TestFile;
+
+   if (BaseDir != NULL) {
+      Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &TestFile, RelativePath, EFI_FILE_MODE_READ, 0);
+      if (Status == EFI_SUCCESS) {
+         refit_call1_wrapper(TestFile->Close, TestFile);
+         return TRUE;
+      }
+   }
+   return FALSE;
 }
 
 EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry, IN UINTN FilterMode)
@@ -1318,6 +1336,7 @@ EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry,
         LastBufferSize = BufferSize = 256;
         Buffer = AllocatePool(BufferSize);
         for (IterCount = 0; ; IterCount++) {
+            Print(L"In DirNextEntry(), about to call Directory->Read()\n");
             Status = refit_call3_wrapper(Directory->Read, Directory, &BufferSize, Buffer);
             if (Status != EFI_BUFFER_TOO_SMALL || IterCount >= 4)
                 break;
@@ -1563,6 +1582,19 @@ BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) {
    return (Found);
 } // BOOLEAN StriSubCmp()
 
+// Convert input string to all-lowercase.
+VOID ToLower(CHAR16 * MyString) {
+    UINTN i = 0;
+
+    if (MyString) {
+        while (MyString[i] != L'\0') {
+            if ((MyString[i] >= L'A') && (MyString[i] <= L'Z'))
+                MyString[i] = MyString[i] - L'A' + L'a';
+            i++;
+        } // while
+    } // if
+} // VOID ToLower()
+
 // 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 or empty). The original input
@@ -2180,5 +2212,5 @@ EFI_GUID StringAsGuid(CHAR16 * InString) {
 // Returns TRUE if the two GUIDs are equal, FALSE otherwise
 BOOLEAN GuidsAreEqual(EFI_GUID *Guid1, EFI_GUID *Guid2) {
    return (CompareMem(Guid1, Guid2, 16) == 0);
-} // BOOLEAN CompareGuids()
+} // BOOLEAN GuidsAreEqual()