]> code.delx.au - refind/blobdiff - refind/lib.c
TianoCore build support; new use_graphics_for refind.conf token
[refind] / refind / lib.c
index c7c5734b877a31bbfa81825bdbe65421b88ecf1f..85a1de2fbc6979494ec2aaec34234047826e59a1 100644 (file)
 #include "lib.h"
 #include "icns.h"
 #include "screen.h"
-#include "refit_call_wrapper.h"
+#include "../include/refit_call_wrapper.h"
+#include "../include/RemovableMedia.h"
+
+#ifdef __MAKEWITH_GNUEFI
+#define EfiReallocatePool ReallocatePool
+#else
+#define LibLocateHandle gBS->LocateHandleBuffer
+#define DevicePathProtocol gEfiDevicePathProtocolGuid
+#define BlockIoProtocol gEfiBlockIoProtocolGuid
+#define LibFileSystemInfo EfiLibFileSystemInfo
+#define LibOpenRoot EfiLibOpenRoot
+EFI_DEVICE_PATH EndDevicePath[] = {
+   {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}}
+};
+
+//#define EndDevicePath DevicePath
+#endif
 
 // variables
 
@@ -127,10 +143,13 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle)
 
     // find the current directory
     DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath);
+//    Print(L"DevicePathAsString is '%s'\n", DevicePathAsString);
     CleanUpPathNameSlashes(DevicePathAsString);
     if (SelfDirPath != NULL)
        FreePool(SelfDirPath);
     SelfDirPath = FindPath(DevicePathAsString);
+//    Print(L"SelfDirPath is '%s'\n", SelfDirPath);
+//    PauseForKey();
     FreePool(DevicePathAsString);
 
     return FinishInitRefitLib();
@@ -223,7 +242,7 @@ VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID
         if (*ElementCount == 0)
             *ListPtr = AllocatePool(sizeof(VOID *) * AllocateCount);
         else
-            *ListPtr = ReallocatePool(*ListPtr, sizeof(VOID *) * (*ElementCount), sizeof(VOID *) * AllocateCount);
+            *ListPtr = EfiReallocatePool(*ListPtr, sizeof(VOID *) * (*ElementCount), sizeof(VOID *) * AllocateCount);
     }
     (*ListPtr)[*ElementCount] = NewElement;
     (*ElementCount)++;
@@ -269,8 +288,7 @@ VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DE
     MaxPaths--;  // leave space for the terminating NULL pointer
 
     // get all LoadedImage handles
-    Status = LibLocateHandle(ByProtocol, &LoadedImageProtocol, NULL,
-                             &HandleCount, &Handles);
+    Status = LibLocateHandle(ByProtocol, &LoadedImageProtocol, NULL, &HandleCount, &Handles);
     if (CheckError(Status, L"while listing LoadedImage handles")) {
         if (HardcodedPathList) {
             for (HardcodedIndex = 0; HardcodedPathList[HardcodedIndex] && PathCount < MaxPaths; HardcodedIndex++)
@@ -366,13 +384,14 @@ static VOID ScanVolumeBootcode(IN OUT REFIT_VOLUME *Volume, OUT BOOLEAN *Bootabl
             Volume->OSIconName = L"grub,linux";
             Volume->OSName = L"Linux";
 
-        // GRUB in BIOS boot partition:
-        } else if (FindMem(SectorBuffer, 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;
+//         // Below doesn't produce a bootable entry, so commented out for the moment....
+//         // GRUB in BIOS boot partition:
+//         } else if (FindMem(SectorBuffer, 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 *)(SectorBuffer + 502)) == 0 &&
                     *((UINT32 *)(SectorBuffer + 506)) == 50000 &&
@@ -637,7 +656,7 @@ static VOID ScanVolume(IN OUT REFIT_VOLUME *Volume)
     if (FileExists(Volume->RootDir, VOLUME_ICON_NAME)) {
        Volume->VolIconImage = LoadIcns(Volume->RootDir, VOLUME_ICON_NAME, 128);
     }
-}
+} // ScanVolume()
 
 static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_INFO *MbrEntry)
 {
@@ -681,7 +700,9 @@ static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_I
                 Volume->DiskKind = WholeDiskVolume->DiskKind;
                 Volume->IsMbrPartition = TRUE;
                 Volume->MbrPartitionIndex = LogicalPartitionIndex++;
-                Volume->VolName = PoolPrint(L"Partition %d", Volume->MbrPartitionIndex + 1);
+                Volume->VolName = AllocateZeroPool(256 * sizeof(UINT16));
+                SPrint(Volume->VolName, 255, L"Partition %d", Volume->MbrPartitionIndex + 1);
+//                Volume->VolName = PoolPrint(L"Partition %d", Volume->MbrPartitionIndex + 1);
                 Volume->BlockIO = WholeDiskVolume->BlockIO;
                 Volume->BlockIOOffset = ExtCurrent + EMbrTable[i].StartLBA;
                 Volume->WholeDiskBlockIO = WholeDiskVolume->BlockIO;
@@ -720,8 +741,9 @@ VOID ScanVolumes(VOID)
     // get all filesystem handles
     Status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL, &HandleCount, &Handles);
     // was: &FileSystemProtocol
-    if (Status == EFI_NOT_FOUND)
+    if (Status == EFI_NOT_FOUND) {
         return;  // no filesystems. strange, but true...
+    }
     if (CheckError(Status, L"while listing all file systems"))
         return;
 
@@ -801,8 +823,10 @@ VOID ScanVolumes(VOID)
                 // now we're reasonably sure the association is correct...
                 Volume->IsMbrPartition = TRUE;
                 Volume->MbrPartitionIndex = PartitionIndex;
-                if (Volume->VolName == NULL)
-                    Volume->VolName = PoolPrint(L"Partition %d", PartitionIndex + 1);
+                if (Volume->VolName == NULL) {
+                    Volume->VolName = AllocateZeroPool(sizeof(CHAR16) * 256);
+                    SPrint(Volume->VolName, 255, L"Partition %d", PartitionIndex + 1);
+                }
                 break;
             }
 
@@ -923,7 +947,7 @@ EFI_STATUS DirNextEntry(IN EFI_FILE *Directory, IN OUT EFI_FILE_INFO **DirEntry,
                 Print(L"Reallocating buffer from %d to %d\n", LastBufferSize, BufferSize);
 #endif
             }
-            Buffer = ReallocatePool(Buffer, LastBufferSize, BufferSize);
+            Buffer = EfiReallocatePool(Buffer, LastBufferSize, BufferSize);
             LastBufferSize = BufferSize;
         }
         if (EFI_ERROR(Status)) {
@@ -967,6 +991,60 @@ VOID DirIterOpen(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath OPTIONAL, OUT REF
     DirIter->LastFileInfo = NULL;
 }
 
+#ifndef __MAKEWITH_GNUEFI
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
+
+static EFI_STATUS
+InitializeUnicodeCollationProtocol (VOID)
+{
+   EFI_STATUS  Status;
+
+   if (mUnicodeCollation != NULL) {
+      return EFI_SUCCESS;
+   }
+
+   //
+   // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
+   // instances first and then select one which support English language.
+   // Current implementation just pick the first instance.
+   //
+   Status = gBS->LocateProtocol (
+                          &gEfiUnicodeCollation2ProtocolGuid,
+                          NULL,
+                          (VOID **) &mUnicodeCollation
+                          );
+  if (EFI_ERROR(Status)) {
+    Status = gBS->LocateProtocol (
+                  &gEfiUnicodeCollationProtocolGuid,
+                  NULL,
+                  (VOID **) &mUnicodeCollation
+                  );
+
+  }
+   return Status;
+}
+
+static BOOLEAN
+MetaiMatch (IN CHAR16 *String, IN CHAR16 *Pattern)
+{
+   if (!mUnicodeCollation) {
+      InitializeUnicodeCollationProtocol();
+   }
+   if (mUnicodeCollation)
+      return mUnicodeCollation->MetaiMatch (mUnicodeCollation, String, Pattern);
+   return FALSE; // Shouldn't happen
+}
+
+static VOID StrLwr (IN OUT CHAR16 *Str) {
+   if (!mUnicodeCollation) {
+      InitializeUnicodeCollationProtocol();
+   }
+   if (mUnicodeCollation)
+      mUnicodeCollation->StrLwr (mUnicodeCollation, Str);
+}
+
+#endif
+
 BOOLEAN DirIterNext(IN OUT REFIT_DIR_ITER *DirIter, IN UINTN FilterMode, IN CHAR16 *FilePattern OPTIONAL,
                     OUT EFI_FILE_INFO **DirEntry)
 {
@@ -1198,7 +1276,8 @@ CHAR16 *FindLastDirName(IN CHAR16 *Path) {
 
 // Returns the directory portion of a pathname. For instance,
 // if FullPath is 'EFI\foo\bar.efi', this function returns the
-// string 'EFI\foo'.
+// string 'EFI\foo'. The calling function is responsible for
+// freeing the returned string's memory.
 CHAR16 *FindPath(IN CHAR16* FullPath) {
    UINTN i, LastBackslash = 0;
    CHAR16 *PathOnly;
@@ -1275,3 +1354,48 @@ CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) {
    } // if
    return (FoundString);
 } // CHAR16 *FindCommaDelimited()
+
+// Returns TRUE if SmallString is an element in the comma-delimited List,
+// FALSE otherwise. Performs comparison case-insensitively (except on
+// buggy EFIs with case-sensitive StriCmp() functions).
+BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List) {
+   UINTN     i = 0;
+   BOOLEAN   Found = FALSE;
+   CHAR16    *OneElement;
+
+   if (SmallString && List) {
+      while (!Found && (OneElement = FindCommaDelimited(List, i++))) {
+         if (StriCmp(OneElement, SmallString) == 0)
+            Found = TRUE;
+      } // while
+   } // if
+   return Found;
+} // BOOLEAN IsIn()
+
+static EFI_GUID AppleRemovableMediaGuid = APPLE_REMOVABLE_MEDIA_PROTOCOL_GUID;
+
+// Eject all removable media.
+// Returns TRUE if any media were ejected, FALSE otherwise.
+BOOLEAN EjectMedia(VOID) {
+   EFI_STATUS                      Status;
+   UINTN                           HandleIndex, HandleCount = 0, Ejected = 0;
+   EFI_HANDLE                      *Handles, Handle;
+   APPLE_REMOVABLE_MEDIA_PROTOCOL  *Ejectable;
+
+   Status = LibLocateHandle(ByProtocol, &AppleRemovableMediaGuid, NULL, &HandleCount, &Handles);
+   if (EFI_ERROR(Status) || HandleCount == 0)
+      return (FALSE); // probably not an Apple system
+
+   for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+      Handle = Handles[HandleIndex];
+      Status = refit_call3_wrapper(BS->HandleProtocol, Handle, &AppleRemovableMediaGuid, (VOID **) &Ejectable);
+      if (EFI_ERROR(Status))
+         continue;
+      Status = refit_call1_wrapper(Ejectable->Eject, Ejectable);
+      if (!EFI_ERROR(Status))
+         Ejected++;
+   }
+   FreePool(Handles);
+   return (Ejected > 0);
+} // VOID EjectMedia()
+