* 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
- * with this source code or binaries made from it.
+ * License (GPL) version 3 (GPLv3), or (at your option) any later version.
*
*/
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
#include "global.h"
#include "lib.h"
#include "../include/RemovableMedia.h"
#include "gpt.h"
#include "config.h"
-#include "../EfiLib/LegacyBios.h"
+#include "mystrings.h"
#ifdef __MAKEWITH_GNUEFI
#define EfiReallocatePool ReallocatePool
EFI_DEVICE_PATH EndDevicePath[] = {
{END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}}
};
-
-//#define EndDevicePath DevicePath
#endif
// "Magic" signatures for various filesystems
// and identify its boot loader, and hence probable BIOS-mode OS installation
#define SAMPLE_SIZE 69632 /* 68 KiB -- ReiserFS superblock begins at 64 KiB */
-
-// functions
-
-static EFI_STATUS FinishInitRefitLib(VOID);
-
-static VOID UninitVolumes(VOID);
-
//
-// self recognition stuff
+// Pathname manipulations
//
// Converts forward slashes to backslashes, removes duplicate slashes, and
// return "/", since some firmware implementations flake out if this
// isn't present.
VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) {
- CHAR16 *NewName;
- UINTN i, Length, FinalChar = 0;
- BOOLEAN LastWasSlash = FALSE;
-
- Length = StrLen(PathName);
- NewName = AllocateZeroPool(sizeof(CHAR16) * (Length + 2));
- if (NewName != NULL) {
- for (i = 0; i < StrLen(PathName); i++) {
- if ((PathName[i] == L'/') || (PathName[i] == L'\\')) {
- if ((!LastWasSlash) && (FinalChar != 0))
- NewName[FinalChar++] = L'\\';
- LastWasSlash = TRUE;
- } else {
- NewName[FinalChar++] = PathName[i];
- LastWasSlash = FALSE;
- } // if/else
- } // for
- NewName[FinalChar] = 0;
- if ((FinalChar > 0) && (NewName[FinalChar - 1] == L'\\'))
- NewName[--FinalChar] = 0;
- if (FinalChar == 0) {
- NewName[0] = L'\\';
- NewName[1] = 0;
- }
- // Copy the transformed name back....
- StrCpy(PathName, NewName);
- FreePool(NewName);
- } // if allocation OK
+ CHAR16 *NewName;
+ UINTN i, Length, FinalChar = 0;
+ BOOLEAN LastWasSlash = FALSE;
+
+ Length = StrLen(PathName);
+ NewName = AllocateZeroPool(sizeof(CHAR16) * (Length + 2));
+ if (NewName != NULL) {
+ for (i = 0; i < Length; i++) {
+ if ((PathName[i] == L'/') || (PathName[i] == L'\\')) {
+ if ((!LastWasSlash) && (FinalChar != 0))
+ NewName[FinalChar++] = L'\\';
+ LastWasSlash = TRUE;
+ } else {
+ NewName[FinalChar++] = PathName[i];
+ LastWasSlash = FALSE;
+ } // if/else
+ } // for
+ NewName[FinalChar] = 0;
+ if ((FinalChar > 0) && (NewName[FinalChar - 1] == L'\\'))
+ NewName[--FinalChar] = 0;
+ if (FinalChar == 0) {
+ NewName[0] = L'\\';
+ NewName[1] = 0;
+ }
+ // Copy the transformed name back....
+ StrCpy(PathName, NewName);
+ FreePool(NewName);
+ } // if allocation OK
} // CleanUpPathNameSlashes()
// Splits an EFI device path into device and filename components. For instance, if InString is
// If InString contains no ")" character, this function leaves the original input string
// unmodified and also returns that string. If InString is NULL, this function returns NULL.
static CHAR16* SplitDeviceString(IN OUT CHAR16 *InString) {
- INTN i;
- CHAR16 *FileName = NULL;
- BOOLEAN Found = FALSE;
-
- if (InString != NULL) {
- i = StrLen(InString) - 1;
- while ((i >= 0) && (!Found)) {
- if (InString[i] == L')') {
- Found = TRUE;
- FileName = StrDuplicate(&InString[i + 1]);
- CleanUpPathNameSlashes(FileName);
- InString[i + 1] = '\0';
- } // if
- i--;
- } // while
- if (FileName == NULL)
- FileName = StrDuplicate(InString);
- } // if
- return FileName;
+ INTN i;
+ CHAR16 *FileName = NULL;
+ BOOLEAN Found = FALSE;
+
+ if (InString != NULL) {
+ i = StrLen(InString) - 1;
+ while ((i >= 0) && (!Found)) {
+ if (InString[i] == L')') {
+ Found = TRUE;
+ FileName = StrDuplicate(&InString[i + 1]);
+ CleanUpPathNameSlashes(FileName);
+ InString[i + 1] = '\0';
+ } // if
+ i--;
+ } // while
+ if (FileName == NULL)
+ FileName = StrDuplicate(InString);
+ } // if
+ return FileName;
} // static CHAR16* SplitDeviceString()
+//
+// Library initialization and de-initialization
+//
+
+static EFI_STATUS FinishInitRefitLib(VOID)
+{
+ EFI_STATUS Status;
+
+ if (SelfRootDir == NULL) {
+ SelfRootDir = LibOpenRoot(SelfLoadedImage->DeviceHandle);
+ if (SelfRootDir == NULL) {
+ CheckError(EFI_LOAD_ERROR, L"while (re)opening our installation volume");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Status = refit_call5_wrapper(SelfRootDir->Open, SelfRootDir, &SelfDir, SelfDirPath, EFI_FILE_MODE_READ, 0);
+ if (CheckFatalError(Status, L"while opening our installation directory"))
+ return EFI_LOAD_ERROR;
+
+ return EFI_SUCCESS;
+}
+
EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle)
{
EFI_STATUS Status;
// find the current directory
DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath);
+ GlobalConfig.SelfDevicePath = FileDevicePath(SelfLoadedImage->DeviceHandle, DevicePathAsString);
CleanUpPathNameSlashes(DevicePathAsString);
MyFreePool(SelfDirPath);
Temp = FindPath(DevicePathAsString);
return FinishInitRefitLib();
}
+static VOID UninitVolumes(VOID)
+{
+ REFIT_VOLUME *Volume;
+ UINTN VolumeIndex;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+
+ if (Volume->RootDir != NULL) {
+ refit_call1_wrapper(Volume->RootDir->Close, Volume->RootDir);
+ Volume->RootDir = NULL;
+ }
+
+ Volume->DeviceHandle = NULL;
+ Volume->BlockIO = NULL;
+ Volume->WholeDiskBlockIO = NULL;
+ }
+} /* VOID UninitVolumes() */
+
+VOID ReinitVolumes(VOID)
+{
+ EFI_STATUS Status;
+ REFIT_VOLUME *Volume;
+ UINTN VolumeIndex;
+ EFI_DEVICE_PATH *RemainingDevicePath;
+ EFI_HANDLE DeviceHandle, WholeDiskHandle;
+
+ for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
+ Volume = Volumes[VolumeIndex];
+
+ if (Volume->DevicePath != NULL) {
+ // get the handle for that path
+ RemainingDevicePath = Volume->DevicePath;
+ Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &DeviceHandle);
+
+ if (!EFI_ERROR(Status)) {
+ Volume->DeviceHandle = DeviceHandle;
+
+ // get the root directory
+ Volume->RootDir = LibOpenRoot(Volume->DeviceHandle);
+
+ } else
+ CheckError(Status, L"from LocateDevicePath");
+ }
+
+ if (Volume->WholeDiskDevicePath != NULL) {
+ // get the handle for that path
+ RemainingDevicePath = Volume->WholeDiskDevicePath;
+ Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &WholeDiskHandle);
+
+ if (!EFI_ERROR(Status)) {
+ // get the BlockIO protocol
+ Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol,
+ (VOID **) &Volume->WholeDiskBlockIO);
+ if (EFI_ERROR(Status)) {
+ Volume->WholeDiskBlockIO = NULL;
+ CheckError(Status, L"from HandleProtocol");
+ }
+ } else
+ CheckError(Status, L"from LocateDevicePath");
+ }
+ }
+} /* VOID ReinitVolumes(VOID) */
+
// called before running external programs to close open file handles
VOID UninitRefitLib(VOID)
{
refit_call1_wrapper(SelfRootDir->Close, SelfRootDir);
SelfRootDir = NULL;
}
-}
+} /* VOID UninitRefitLib() */
// called after running external programs to re-open file handles
EFI_STATUS ReinitRefitLib(VOID)
return FinishInitRefitLib();
}
-static EFI_STATUS FinishInitRefitLib(VOID)
-{
- EFI_STATUS Status;
-
- if (SelfRootDir == NULL) {
- SelfRootDir = LibOpenRoot(SelfLoadedImage->DeviceHandle);
- if (SelfRootDir == NULL) {
- CheckError(EFI_LOAD_ERROR, L"while (re)opening our installation volume");
- return EFI_LOAD_ERROR;
- }
- }
-
- Status = refit_call5_wrapper(SelfRootDir->Open, SelfRootDir, &SelfDir, SelfDirPath, EFI_FILE_MODE_READ, 0);
- if (CheckFatalError(Status, L"while opening our installation directory"))
- return EFI_LOAD_ERROR;
-
- return EFI_SUCCESS;
-}
-
//
// EFI variable read and write functions
//
}
} // VOID FreeList()
-//
-// firmware device path discovery
-//
-
-static UINT8 LegacyLoaderMediaPathData[] = {
- 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B,
- 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B,
- 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00,
-};
-static EFI_DEVICE_PATH *LegacyLoaderMediaPath = (EFI_DEVICE_PATH *)LegacyLoaderMediaPathData;
-
-VOID ExtractLegacyLoaderPaths(EFI_DEVICE_PATH **PathList, UINTN MaxPaths, EFI_DEVICE_PATH **HardcodedPathList)
-{
- EFI_STATUS Status;
- UINTN HandleCount = 0;
- UINTN HandleIndex, HardcodedIndex;
- EFI_HANDLE *Handles;
- EFI_HANDLE Handle;
- UINTN PathCount = 0;
- UINTN PathIndex;
- EFI_LOADED_IMAGE *LoadedImage;
- EFI_DEVICE_PATH *DevicePath;
- BOOLEAN Seen;
-
- MaxPaths--; // leave space for the terminating NULL pointer
-
- // get all LoadedImage 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++)
- PathList[PathCount++] = HardcodedPathList[HardcodedIndex];
- }
- PathList[PathCount] = NULL;
- return;
- }
- for (HandleIndex = 0; HandleIndex < HandleCount && PathCount < MaxPaths; HandleIndex++) {
- Handle = Handles[HandleIndex];
-
- Status = refit_call3_wrapper(BS->HandleProtocol, Handle, &LoadedImageProtocol, (VOID **) &LoadedImage);
- if (EFI_ERROR(Status))
- continue; // This can only happen if the firmware scewed up, ignore it.
-
- Status = refit_call3_wrapper(BS->HandleProtocol, LoadedImage->DeviceHandle, &DevicePathProtocol, (VOID **) &DevicePath);
- if (EFI_ERROR(Status))
- continue; // This happens, ignore it.
-
- // Only grab memory range nodes
- if (DevicePathType(DevicePath) != HARDWARE_DEVICE_PATH || DevicePathSubType(DevicePath) != HW_MEMMAP_DP)
- continue;
-
- // Check if we have this device path in the list already
- // WARNING: This assumes the first node in the device path is unique!
- Seen = FALSE;
- for (PathIndex = 0; PathIndex < PathCount; PathIndex++) {
- if (DevicePathNodeLength(DevicePath) != DevicePathNodeLength(PathList[PathIndex]))
- continue;
- if (CompareMem(DevicePath, PathList[PathIndex], DevicePathNodeLength(DevicePath)) == 0) {
- Seen = TRUE;
- break;
- }
- }
- if (Seen)
- continue;
-
- PathList[PathCount++] = AppendDevicePath(DevicePath, LegacyLoaderMediaPath);
- }
- MyFreePool(Handles);
-
- if (HardcodedPathList) {
- for (HardcodedIndex = 0; HardcodedPathList[HardcodedIndex] && PathCount < MaxPaths; HardcodedIndex++)
- PathList[PathCount++] = HardcodedPathList[HardcodedIndex];
- }
- PathList[PathCount] = NULL;
-}
-
//
// volume functions
//
Volume->FSType = FS_TYPE_ISO9660;
return;
}
-
} // if ((Buffer != NULL) && (Volume != NULL))
-
} // UINT32 SetFilesystemData()
static VOID ScanVolumeBootcode(REFIT_VOLUME *Volume, BOOLEAN *Bootable)
// 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;
+ 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
// 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;
+ EFI_FILE_SYSTEM_INFO *FileSystemInfoPtr = NULL;
+ CHAR16 *FoundName = NULL;
+ CHAR16 *SISize, *TypeName;
- if (Volume->RootDir != NULL) {
- FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
- }
+ if (Volume->RootDir != NULL) {
+ FileSystemInfoPtr = LibFileSystemInfo(Volume->RootDir);
+ }
- if ((FileSystemInfoPtr != NULL) && (FileSystemInfoPtr->VolumeLabel != NULL) &&
- (StrLen(FileSystemInfoPtr->VolumeLabel) > 0)) {
- FoundName = StrDuplicate(FileSystemInfoPtr->VolumeLabel);
- }
+ 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
+ // 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)")
+ // 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;
+ // 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;
+ HARDDRIVE_DEVICE_PATH *HdDevicePath;
+ GPT_ENTRY *PartInfo;
- if ((Volume == NULL) || (DevicePath == NULL))
- return;
+ 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)) {
- GlobalConfig.DiscoveredRoot = Volume;
- Print(L"Found match!\n");
- PauseForKey();
- } // if (GUIDs match)
- } // if (PartInfo exists)
- } // if (GPT disk)
- } // if (disk device)
+ 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,
// 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;
+ 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;
+ 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)
NextExtCurrent = ExtBase + EMbrTable[i].StartLBA;
break;
} else {
-
// found a logical partition
Volume = AllocateZeroPool(sizeof(REFIT_VOLUME));
Volume->DiskKind = WholeDiskVolume->DiskKind;
ScanVolumeBootcode(Volume, &Bootable);
if (!Bootable)
Volume->HasBootCode = FALSE;
-
SetVolumeBadgeIcon(Volume);
-
AddListElement((VOID ***) &Volumes, &VolumesCount, Volume);
-
- }
- }
- }
+ } // if/else
+ } // for
+ } // for
} /* VOID ScanExtendedPartition() */
VOID ScanVolumes(VOID)
} // for
} /* VOID ScanVolumes() */
-static VOID UninitVolumes(VOID)
-{
- REFIT_VOLUME *Volume;
- UINTN VolumeIndex;
-
- for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
- Volume = Volumes[VolumeIndex];
-
- if (Volume->RootDir != NULL) {
- refit_call1_wrapper(Volume->RootDir->Close, Volume->RootDir);
- Volume->RootDir = NULL;
- }
-
- Volume->DeviceHandle = NULL;
- Volume->BlockIO = NULL;
- Volume->WholeDiskBlockIO = NULL;
- }
-}
-
-VOID ReinitVolumes(VOID)
-{
- EFI_STATUS Status;
- REFIT_VOLUME *Volume;
- UINTN VolumeIndex;
- EFI_DEVICE_PATH *RemainingDevicePath;
- EFI_HANDLE DeviceHandle, WholeDiskHandle;
-
- for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) {
- Volume = Volumes[VolumeIndex];
-
- if (Volume->DevicePath != NULL) {
- // get the handle for that path
- RemainingDevicePath = Volume->DevicePath;
- Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &DeviceHandle);
-
- if (!EFI_ERROR(Status)) {
- Volume->DeviceHandle = DeviceHandle;
-
- // get the root directory
- Volume->RootDir = LibOpenRoot(Volume->DeviceHandle);
-
- } else
- CheckError(Status, L"from LocateDevicePath");
- }
-
- if (Volume->WholeDiskDevicePath != NULL) {
- // get the handle for that path
- RemainingDevicePath = Volume->WholeDiskDevicePath;
- Status = refit_call3_wrapper(BS->LocateDevicePath, &BlockIoProtocol, &RemainingDevicePath, &WholeDiskHandle);
-
- if (!EFI_ERROR(Status)) {
- // get the BlockIO protocol
- Status = refit_call3_wrapper(BS->HandleProtocol, WholeDiskHandle, &BlockIoProtocol,
- (VOID **) &Volume->WholeDiskBlockIO);
- if (EFI_ERROR(Status)) {
- Volume->WholeDiskBlockIO = NULL;
- CheckError(Status, L"from HandleProtocol");
- }
- } else
- CheckError(Status, L"from LocateDevicePath");
- }
- }
-}
-
//
// file and dir functions
//
BOOLEAN FileExists(IN EFI_FILE *BaseDir, IN CHAR16 *RelativePath)
{
- 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 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)
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,
// Remove the .efi extension from FileName -- for instance, if FileName is
// "fred.efi", returns "fred". If the filename contains no .efi extension,
// returns a copy of the original input.
-CHAR16 * StripEfiExtension(CHAR16 *FileName) {
- UINTN Length;
- CHAR16 *Copy = NULL;
-
- if ((FileName != NULL) && ((Copy = StrDuplicate(FileName)) != NULL)) {
- Length = StrLen(Copy);
- // Note: Do StriCmp() twice to work around Gigabyte Hybrid EFI case-sensitivity bug....
- if ((Length >= 4) && ((StriCmp(&Copy[Length - 4], L".efi") == 0) || (StriCmp(&Copy[Length - 4], L".EFI") == 0))) {
- Copy[Length - 4] = 0;
- } // if
- } // if
- return Copy;
+CHAR16 * StripEfiExtension(IN CHAR16 *FileName) {
+ UINTN Length;
+ CHAR16 *Copy = NULL;
+
+ if ((FileName != NULL) && ((Copy = StrDuplicate(FileName)) != NULL)) {
+ Length = StrLen(Copy);
+ if ((Length >= 4) && MyStriCmp(&Copy[Length - 4], L".efi")) {
+ Copy[Length - 4] = 0;
+ } // if
+ } // if
+ return Copy;
} // CHAR16 * StripExtension()
//
return -1;
}
-// Performs a case-insensitive search of BigStr for SmallStr.
-// Returns TRUE if found, FALSE if not.
-BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) {
- CHAR16 *SmallCopy, *BigCopy;
- BOOLEAN Found = FALSE;
- UINTN StartPoint = 0, NumCompares = 0, SmallLen = 0;
-
- if ((SmallStr != NULL) && (BigStr != NULL) && (StrLen(BigStr) >= StrLen(SmallStr))) {
- SmallCopy = StrDuplicate(SmallStr);
- BigCopy = StrDuplicate(BigStr);
- StrLwr(SmallCopy);
- StrLwr(BigCopy);
- SmallLen = StrLen(SmallCopy);
- NumCompares = StrLen(BigCopy) - SmallLen + 1;
- while ((!Found) && (StartPoint < NumCompares)) {
- Found = (StrnCmp(SmallCopy, &BigCopy[StartPoint++], SmallLen) == 0);
- } // while
- MyFreePool(SmallCopy);
- MyFreePool(BigCopy);
- } // if
-
- 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
-// string *First is de-allocated and replaced by the new merged string.
-// This is similar to StrCat, but safer and more flexible because
-// MergeStrings allocates memory that's the correct size for the
-// new merged string, so it can take a NULL *First and it cleans
-// up the old memory. It should *NOT* be used with a constant
-// *First, though....
-VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
- UINTN Length1 = 0, Length2 = 0;
- CHAR16* NewString;
-
- if (*First != NULL)
- Length1 = StrLen(*First);
- if (Second != NULL)
- Length2 = StrLen(Second);
- NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2));
- if (NewString != NULL) {
- if ((*First != NULL) && (StrLen(*First) == 0)) {
- MyFreePool(*First);
- *First = NULL;
- }
- NewString[0] = L'\0';
- if (*First != NULL) {
- StrCat(NewString, *First);
- if (AddChar) {
- NewString[Length1] = AddChar;
- NewString[Length1 + 1] = '\0';
- } // if (AddChar)
- } // if (*First != NULL)
- if (Second != NULL)
- StrCat(NewString, Second);
- MyFreePool(*First);
- *First = NewString;
- } else {
- Print(L"Error! Unable to allocate memory in MergeStrings()!\n");
- } // if/else
-} // static CHAR16* MergeStrings()
-
// Takes an input pathname (*Path) and returns the part of the filename from
// the final dot onwards, converted to lowercase. If the filename includes
// no dots, or if the input is NULL, returns an empty (but allocated) string.
// The calling function is responsible for freeing the memory associated with
// the return value.
CHAR16 *FindExtension(IN CHAR16 *Path) {
- CHAR16 *Extension;
- BOOLEAN Found = FALSE, FoundSlash = FALSE;
- INTN i;
-
- Extension = AllocateZeroPool(sizeof(CHAR16));
- if (Path) {
- i = StrLen(Path);
- while ((!Found) && (!FoundSlash) && (i >= 0)) {
- if (Path[i] == L'.')
- Found = TRUE;
- else if ((Path[i] == L'/') || (Path[i] == L'\\'))
- FoundSlash = TRUE;
- if (!Found)
- i--;
- } // while
- if (Found) {
- MergeStrings(&Extension, &Path[i], 0);
- StrLwr(Extension);
- } // if (Found)
- } // if
- return (Extension);
-} // CHAR16 *FindExtension
+ CHAR16 *Extension;
+ BOOLEAN Found = FALSE, FoundSlash = FALSE;
+ INTN i;
+
+ Extension = AllocateZeroPool(sizeof(CHAR16));
+ if (Path) {
+ i = StrLen(Path);
+ while ((!Found) && (!FoundSlash) && (i >= 0)) {
+ if (Path[i] == L'.')
+ Found = TRUE;
+ else if ((Path[i] == L'/') || (Path[i] == L'\\'))
+ FoundSlash = TRUE;
+ if (!Found)
+ i--;
+ } // while
+ if (Found) {
+ MergeStrings(&Extension, &Path[i], 0);
+ ToLower(Extension);
+ } // if (Found)
+ } // if
+ return (Extension);
+} // CHAR16 *FindExtension()
// Takes an input pathname (*Path) and locates the final directory component
// of that name. For instance, if the input path is 'EFI\foo\bar.efi', this
// function returns the string 'foo'.
// Assumes the pathname is separated with backslashes.
CHAR16 *FindLastDirName(IN CHAR16 *Path) {
- UINTN i, StartOfElement = 0, EndOfElement = 0, PathLength, CopyLength;
- CHAR16 *Found = NULL;
-
- if (Path == NULL)
- return NULL;
-
- PathLength = StrLen(Path);
- // Find start & end of target element
- for (i = 0; i < PathLength; i++) {
- if (Path[i] == '\\') {
- StartOfElement = EndOfElement;
- EndOfElement = i;
- } // if
- } // for
- // Extract the target element
- if (EndOfElement > 0) {
- while ((StartOfElement < PathLength) && (Path[StartOfElement] == '\\')) {
- StartOfElement++;
- } // while
- EndOfElement--;
- if (EndOfElement >= StartOfElement) {
- CopyLength = EndOfElement - StartOfElement + 1;
- Found = StrDuplicate(&Path[StartOfElement]);
- if (Found != NULL)
- Found[CopyLength] = 0;
- } // if (EndOfElement >= StartOfElement)
- } // if (EndOfElement > 0)
- return (Found);
-} // CHAR16 *FindLastDirName
+ UINTN i, StartOfElement = 0, EndOfElement = 0, PathLength, CopyLength;
+ CHAR16 *Found = NULL;
+
+ if (Path == NULL)
+ return NULL;
+
+ PathLength = StrLen(Path);
+ // Find start & end of target element
+ for (i = 0; i < PathLength; i++) {
+ if (Path[i] == '\\') {
+ StartOfElement = EndOfElement;
+ EndOfElement = i;
+ } // if
+ } // for
+ // Extract the target element
+ if (EndOfElement > 0) {
+ while ((StartOfElement < PathLength) && (Path[StartOfElement] == '\\')) {
+ StartOfElement++;
+ } // while
+ EndOfElement--;
+ if (EndOfElement >= StartOfElement) {
+ CopyLength = EndOfElement - StartOfElement + 1;
+ Found = StrDuplicate(&Path[StartOfElement]);
+ if (Found != NULL)
+ Found[CopyLength] = 0;
+ } // if (EndOfElement >= StartOfElement)
+ } // if (EndOfElement > 0)
+ return (Found);
+} // CHAR16 *FindLastDirName()
// Returns the directory portion of a pathname. For instance,
// if FullPath is 'EFI\foo\bar.efi', this function returns the
return (PathOnly);
}
-/*++
- *
- * Routine Description:
- *
- * Find a substring.
- *
- * Arguments:
- *
- * String - Null-terminated string to search.
- * StrCharSet - Null-terminated string to search for.
- *
- * Returns:
- * The address of the first occurrence of the matching substring if successful, or NULL otherwise.
- * --*/
-CHAR16* MyStrStr (CHAR16 *String, CHAR16 *StrCharSet)
-{
- CHAR16 *Src;
- CHAR16 *Sub;
-
- if ((String == NULL) || (StrCharSet == NULL))
- return NULL;
-
- Src = String;
- Sub = StrCharSet;
-
- while ((*String != L'\0') && (*StrCharSet != L'\0')) {
- if (*String++ != *StrCharSet) {
- String = ++Src;
- StrCharSet = Sub;
- } else {
- StrCharSet++;
- }
- }
- if (*StrCharSet == L'\0') {
- return Src;
- } else {
- return NULL;
- }
-} // CHAR16 *MyStrStr()
-
-// Restrict TheString to at most Limit characters.
-// Does this in two ways:
-// - Locates stretches of two or more spaces and compresses
-// them down to one space.
-// - Truncates TheString
-// Returns TRUE if changes were made, FALSE otherwise
-BOOLEAN LimitStringLength(CHAR16 *TheString, UINTN Limit) {
- CHAR16 *SubString, *TempString;
- UINTN i;
- BOOLEAN HasChanged = FALSE;
-
- // SubString will be NULL or point WITHIN TheString
- SubString = MyStrStr(TheString, L" ");
- while (SubString != NULL) {
- i = 0;
- while (SubString[i] == L' ')
- i++;
- if (i >= StrLen(SubString)) {
- SubString[0] = '\0';
- HasChanged = TRUE;
- } else {
- TempString = StrDuplicate(&SubString[i]);
- if (TempString != NULL) {
- StrCpy(&SubString[1], TempString);
- MyFreePool(TempString);
- HasChanged = TRUE;
- } else {
- // memory allocation problem; abort to avoid potentially infinite loop!
- break;
- } // if/else
- } // if/else
- SubString = MyStrStr(TheString, L" ");
- } // while
-
- // If the string is still too long, truncate it....
- if (StrLen(TheString) > Limit) {
- TheString[Limit] = '\0';
- HasChanged = TRUE;
- } // if
-
- return HasChanged;
-} // BOOLEAN LimitStringLength()
-
// Takes an input loadpath, splits it into disk and filename components, finds a matching
// DeviceVolume, and returns that and the filename (*loader).
VOID FindVolumeAndFilename(IN EFI_DEVICE_PATH *loadpath, OUT REFIT_VOLUME **DeviceVolume, OUT CHAR16 **loader) {
- CHAR16 *DeviceString, *VolumeDeviceString, *Temp;
- UINTN i = 0;
- BOOLEAN Found = FALSE;
-
- MyFreePool(*loader);
- MyFreePool(*DeviceVolume);
- *DeviceVolume = NULL;
- DeviceString = DevicePathToStr(loadpath);
- *loader = SplitDeviceString(DeviceString);
-
- while ((i < VolumesCount) && (!Found)) {
- VolumeDeviceString = DevicePathToStr(Volumes[i]->DevicePath);
- Temp = SplitDeviceString(VolumeDeviceString);
- if (StriCmp(DeviceString, VolumeDeviceString) == 0) {
- Found = TRUE;
- *DeviceVolume = Volumes[i];
- }
- MyFreePool(Temp);
- MyFreePool(VolumeDeviceString);
- i++;
- } // while
+ CHAR16 *DeviceString, *VolumeDeviceString, *Temp;
+ UINTN i = 0;
+ BOOLEAN Found = FALSE;
+
+ MyFreePool(*loader);
+ MyFreePool(*DeviceVolume);
+ *DeviceVolume = NULL;
+ DeviceString = DevicePathToStr(loadpath);
+ *loader = SplitDeviceString(DeviceString);
+
+ while ((i < VolumesCount) && (!Found)) {
+ VolumeDeviceString = DevicePathToStr(Volumes[i]->DevicePath);
+ Temp = SplitDeviceString(VolumeDeviceString);
+ if (MyStriCmp(DeviceString, VolumeDeviceString)) {
+ Found = TRUE;
+ *DeviceVolume = Volumes[i];
+ }
+ MyFreePool(Temp);
+ MyFreePool(VolumeDeviceString);
+ i++;
+ } // while
- MyFreePool(DeviceString);
+ MyFreePool(DeviceString);
} // VOID FindVolumeAndFilename()
// Splits a volume/filename string (e.g., "fs0:\EFI\BOOT") into separate
// volume component in the *VolName variable.
// Returns TRUE if both components are found, FALSE otherwise.
BOOLEAN SplitVolumeAndFilename(IN OUT CHAR16 **Path, OUT CHAR16 **VolName) {
- UINTN i = 0, Length;
- CHAR16 *Filename;
+ UINTN i = 0, Length;
+ CHAR16 *Filename;
- if (*Path == NULL)
- return FALSE;
+ if (*Path == NULL)
+ return FALSE;
- if (*VolName != NULL) {
- MyFreePool(*VolName);
- *VolName = NULL;
- }
+ if (*VolName != NULL) {
+ MyFreePool(*VolName);
+ *VolName = NULL;
+ }
- Length = StrLen(*Path);
- while ((i < Length) && ((*Path)[i] != L':')) {
- i++;
- } // while
-
- if (i < Length) {
- Filename = StrDuplicate((*Path) + i + 1);
- (*Path)[i] = 0;
- *VolName = *Path;
- *Path = Filename;
- return TRUE;
- } else {
- return FALSE;
- }
-} // BOOLEAN SplitVolumeAndFilename()
+ Length = StrLen(*Path);
+ while ((i < Length) && ((*Path)[i] != L':')) {
+ i++;
+ } // while
-// Returns all the digits in the input string, including intervening
-// non-digit characters. For instance, if InString is "foo-3.3.4-7.img",
-// this function returns "3.3.4-7". If InString contains no digits,
-// the return value is NULL.
-CHAR16 *FindNumbers(IN CHAR16 *InString) {
- UINTN i, StartOfElement, EndOfElement = 0, InLength, CopyLength;
- CHAR16 *Found = NULL;
-
- if (InString == NULL)
- return NULL;
-
- InLength = StartOfElement = StrLen(InString);
- // Find start & end of target element
- for (i = 0; i < InLength; i++) {
- if ((InString[i] >= '0') && (InString[i] <= '9')) {
- if (StartOfElement > i)
- StartOfElement = i;
- if (EndOfElement < i)
- EndOfElement = i;
- } // if
- } // for
- // Extract the target element
- if (EndOfElement > 0) {
- if (EndOfElement >= StartOfElement) {
- CopyLength = EndOfElement - StartOfElement + 1;
- Found = StrDuplicate(&InString[StartOfElement]);
- if (Found != NULL)
- Found[CopyLength] = 0;
- } // if (EndOfElement >= StartOfElement)
- } // if (EndOfElement > 0)
- return (Found);
-} // CHAR16 *FindNumbers()
-
-// Find the #Index element (numbered from 0) in a comma-delimited string
-// of elements.
-// Returns the found element, or NULL if Index is out of range or InString
-// is NULL. Note that the calling function is responsible for freeing the
-// memory associated with the returned string pointer.
-CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) {
- UINTN StartPos = 0, CurPos = 0;
- BOOLEAN Found = FALSE;
- CHAR16 *FoundString = NULL;
-
- if (InString != NULL) {
- // After while() loop, StartPos marks start of item #Index
- while ((Index > 0) && (CurPos < StrLen(InString))) {
- if (InString[CurPos] == L',') {
- Index--;
- StartPos = CurPos + 1;
- } // if
- CurPos++;
- } // while
- // After while() loop, CurPos is one past the end of the element
- while ((CurPos < StrLen(InString)) && (!Found)) {
- if (InString[CurPos] == L',')
- Found = TRUE;
- else
- CurPos++;
- } // while
- if (Index == 0)
- FoundString = StrDuplicate(&InString[StartPos]);
- if (FoundString != NULL)
- FoundString[CurPos - StartPos] = 0;
- } // if
- return (FoundString);
-} // CHAR16 *FindCommaDelimited()
-
-// Return the position of SmallString within BigString, or -1 if
-// not found.
-INTN FindSubString(IN CHAR16 *SmallString, IN CHAR16 *BigString) {
- INTN Position = -1;
- UINTN i = 0, SmallSize, BigSize;
- BOOLEAN Found = FALSE;
-
- if ((SmallString == NULL) || (BigString == NULL))
- return -1;
-
- SmallSize = StrLen(SmallString);
- BigSize = StrLen(BigString);
- if ((SmallSize > BigSize) || (SmallSize == 0) || (BigSize == 0))
- return -1;
-
- while ((i <= (BigSize - SmallSize) && !Found)) {
- if (CompareMem(BigString + i, SmallString, SmallSize) == 0) {
- Found = TRUE;
- Position = i;
- } // if
- i++;
- } // while()
- return Position;
-} // INTN FindSubString()
+ if (i < Length) {
+ Filename = StrDuplicate((*Path) + i + 1);
+ (*Path)[i] = 0;
+ *VolName = *Path;
+ *Path = Filename;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+} // BOOLEAN SplitVolumeAndFilename()
// Take an input path name, which may include a volume specification and/or
// a path, and return separate volume, path, and file names. For instance,
// the returned pointer is NULL. The calling function is responsible for
// freeing the allocated memory.
VOID SplitPathName(CHAR16 *InPath, CHAR16 **VolName, CHAR16 **Path, CHAR16 **Filename) {
- CHAR16 *Temp = NULL;
-
- MyFreePool(*VolName);
- MyFreePool(*Path);
- MyFreePool(*Filename);
- *VolName = *Path = *Filename = NULL;
- Temp = StrDuplicate(InPath);
- SplitVolumeAndFilename(&Temp, VolName); // VolName is NULL or has volume; Temp has rest of path
- CleanUpPathNameSlashes(Temp);
- *Path = FindPath(Temp); // *Path has path (may be 0-length); Temp unchanged.
- *Filename = StrDuplicate(Temp + StrLen(*Path));
- CleanUpPathNameSlashes(*Filename);
- if (StrLen(*Path) == 0) {
- MyFreePool(*Path);
- *Path = NULL;
- }
- if (StrLen(*Filename) == 0) {
- MyFreePool(*Filename);
- *Filename = NULL;
- }
- MyFreePool(Temp);
-} // VOID SplitPathName
-
-// 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()
-
-// Returns TRUE if any element of List can be found as a substring of
-// BigString, FALSE otherwise. Performs comparisons case-insensitively.
-BOOLEAN IsInSubstring(IN CHAR16 *BigString, IN CHAR16 *List) {
- UINTN i = 0, ElementLength;
- BOOLEAN Found = FALSE;
- CHAR16 *OneElement;
-
- if (BigString && List) {
- while (!Found && (OneElement = FindCommaDelimited(List, i++))) {
- ElementLength = StrLen(OneElement);
- if ((ElementLength <= StrLen(BigString)) && (StriSubCmp(OneElement, BigString)))
- Found = TRUE;
- } // while
- } // if
- return Found;
-} // BOOLEAN IsSubstringIn()
+ CHAR16 *Temp = NULL;
+
+ MyFreePool(*VolName);
+ MyFreePool(*Path);
+ MyFreePool(*Filename);
+ *VolName = *Path = *Filename = NULL;
+ Temp = StrDuplicate(InPath);
+ SplitVolumeAndFilename(&Temp, VolName); // VolName is NULL or has volume; Temp has rest of path
+ CleanUpPathNameSlashes(Temp);
+ *Path = FindPath(Temp); // *Path has path (may be 0-length); Temp unchanged.
+ *Filename = StrDuplicate(Temp + StrLen(*Path));
+ CleanUpPathNameSlashes(*Filename);
+ if (StrLen(*Path) == 0) {
+ MyFreePool(*Path);
+ *Path = NULL;
+ }
+ if (StrLen(*Filename) == 0) {
+ MyFreePool(*Filename);
+ *Filename = NULL;
+ }
+ MyFreePool(Temp);
+} // VOID SplitPathName()
// Returns TRUE if specified Volume, Directory, and Filename correspond to an
// element in the comma-delimited List, FALSE otherwise. Note that Directory and
// Filename must *NOT* include a volume or path specification (that's part of
// the Volume variable), but the List elements may. Performs comparison
-// case-insensitively (except on buggy EFIs with case-sensitive StriCmp()
-// functions).
+// case-insensitively.
BOOLEAN FilenameIn(REFIT_VOLUME *Volume, CHAR16 *Directory, CHAR16 *Filename, CHAR16 *List) {
- UINTN i = 0;
- BOOLEAN Found = FALSE;
- CHAR16 *OneElement;
- CHAR16 *TargetVolName = NULL, *TargetPath = NULL, *TargetFilename = NULL;
-
- if (Filename && List) {
- while (!Found && (OneElement = FindCommaDelimited(List, i++))) {
- Found = TRUE;
- SplitPathName(OneElement, &TargetVolName, &TargetPath, &TargetFilename);
- VolumeNumberToName(Volume, &TargetVolName);
- if (((TargetVolName != NULL) && ((Volume == NULL) || (StriCmp(TargetVolName, Volume->VolName) != 0))) ||
- ((TargetPath != NULL) && (StriCmp(TargetPath, Directory) != 0)) ||
- ((TargetFilename != NULL) && (StriCmp(TargetFilename, Filename) != 0))) {
- Found = FALSE;
- } // if
- MyFreePool(OneElement);
- } // while
- } // if
+ UINTN i = 0;
+ BOOLEAN Found = FALSE;
+ CHAR16 *OneElement;
+ CHAR16 *TargetVolName = NULL, *TargetPath = NULL, *TargetFilename = NULL;
- MyFreePool(TargetVolName);
- MyFreePool(TargetPath);
- MyFreePool(TargetFilename);
- return Found;
+ if (Filename && List) {
+ while (!Found && (OneElement = FindCommaDelimited(List, i++))) {
+ Found = TRUE;
+ SplitPathName(OneElement, &TargetVolName, &TargetPath, &TargetFilename);
+ VolumeNumberToName(Volume, &TargetVolName);
+ if (((TargetVolName != NULL) && ((Volume == NULL) || (!MyStriCmp(TargetVolName, Volume->VolName)))) ||
+ ((TargetPath != NULL) && (!MyStriCmp(TargetPath, Directory))) ||
+ ((TargetFilename != NULL) && (!MyStriCmp(TargetFilename, Filename)))) {
+ Found = FALSE;
+ } // if
+ MyFreePool(OneElement);
+ } // while
+ } // if
+
+ MyFreePool(TargetVolName);
+ MyFreePool(TargetPath);
+ MyFreePool(TargetFilename);
+ return Found;
} // BOOLEAN FilenameIn()
// If *VolName is of the form "fs#", where "#" is a number, and if Volume points
// Implement FreePool the way it should have been done to begin with, so that
// it doesn't throw an ASSERT message if fed a NULL pointer....
VOID MyFreePool(IN VOID *Pointer) {
- if (Pointer != NULL)
- FreePool(Pointer);
+ if (Pointer != NULL)
+ FreePool(Pointer);
}
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++;
- }
- MyFreePool(Handles);
- return (Ejected > 0);
-} // VOID EjectMedia()
-
-// Converts consecutive characters in the input string into a
-// number, interpreting the string as a hexadecimal number, starting
-// at the specified position and continuing for the specified number
-// of characters or until the end of the string, whichever is first.
-// NumChars must be between 1 and 16. Ignores invalid characters.
-UINT64 StrToHex(CHAR16 *Input, UINTN Pos, UINTN NumChars) {
- UINT64 retval = 0x00;
- UINTN NumDone = 0;
- CHAR16 a;
-
- if ((Input == NULL) || (StrLen(Input) < Pos) || (NumChars == 0) || (NumChars > 16)) {
- return 0;
- }
+ EFI_STATUS Status;
+ UINTN HandleIndex, HandleCount = 0, Ejected = 0;
+ EFI_HANDLE *Handles, Handle;
+ APPLE_REMOVABLE_MEDIA_PROTOCOL *Ejectable;
- while ((StrLen(Input) >= Pos) && (NumDone < NumChars)) {
- a = Input[Pos];
- if ((a >= '0') && (a <= '9')) {
- retval *= 0x10;
- retval += (a - '0');
- NumDone++;
- }
- if ((a >= 'a') && (a <= 'f')) {
- retval *= 0x10;
- retval += (a - 'a' + 0x0a);
- NumDone++;
- }
- if ((a >= 'A') && (a <= 'F')) {
- retval *= 0x10;
- retval += (a - 'A' + 0x0a);
- NumDone++;
- }
- Pos++;
- } // while()
- return retval;
-} // StrToHex()
-
-// Returns TRUE if UnknownString can be interpreted as a GUID, FALSE otherwise.
-// Note that the input string must have no extraneous spaces and must be
-// conventionally formatted as a 36-character GUID, complete with dashes in
-// appropriate places.
-BOOLEAN IsGuid(CHAR16 *UnknownString) {
- UINTN Length, i;
- BOOLEAN retval = TRUE;
- CHAR16 a;
-
- if (UnknownString == NULL)
- return FALSE;
-
- Length = StrLen(UnknownString);
- if (Length != 36)
- return FALSE;
-
- for (i = 0; i < Length; i++) {
- a = UnknownString[i];
- if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
- if (a != '-')
- retval = FALSE;
- } else if (((a < 'a') || (a > 'f')) && ((a < 'A') || (a > 'F')) && ((a < '0') && (a > '9'))) {
- retval = FALSE;
- } // if/else if
- } // for
- return retval;
-} // BOOLEAN IsGuid()
-
-// Return the GUID as a string, suitable for display to the user. Note that the calling
-// function is responsible for freeing the allocated memory.
-CHAR16 * GuidAsString(EFI_GUID *GuidData) {
- CHAR16 *TheString;
-
- TheString = AllocateZeroPool(42 * sizeof(CHAR16));
- if (TheString != 0) {
- SPrint (TheString, 82, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- (UINTN)GuidData->Data1, (UINTN)GuidData->Data2, (UINTN)GuidData->Data3,
- (UINTN)GuidData->Data4[0], (UINTN)GuidData->Data4[1], (UINTN)GuidData->Data4[2],
- (UINTN)GuidData->Data4[3], (UINTN)GuidData->Data4[4], (UINTN)GuidData->Data4[5],
- (UINTN)GuidData->Data4[6], (UINTN)GuidData->Data4[7]);
- }
- return TheString;
-} // GuidAsString(EFI_GUID *GuidData)
-
-EFI_GUID StringAsGuid(CHAR16 * InString) {
- EFI_GUID Guid = NULL_GUID_VALUE;
+ Status = LibLocateHandle(ByProtocol, &AppleRemovableMediaGuid, NULL, &HandleCount, &Handles);
+ if (EFI_ERROR(Status) || HandleCount == 0)
+ return (FALSE); // probably not an Apple system
- if (!IsGuid(InString)) {
- return Guid;
- }
-
- Guid.Data1 = (UINT32) StrToHex(InString, 0, 8);
- Guid.Data2 = (UINT16) StrToHex(InString, 9, 4);
- Guid.Data3 = (UINT16) StrToHex(InString, 14, 4);
- Guid.Data4[0] = (UINT8) StrToHex(InString, 19, 2);
- Guid.Data4[1] = (UINT8) StrToHex(InString, 21, 2);
- Guid.Data4[2] = (UINT8) StrToHex(InString, 23, 2);
- Guid.Data4[3] = (UINT8) StrToHex(InString, 26, 2);
- Guid.Data4[4] = (UINT8) StrToHex(InString, 28, 2);
- Guid.Data4[5] = (UINT8) StrToHex(InString, 30, 2);
- Guid.Data4[6] = (UINT8) StrToHex(InString, 32, 2);
- Guid.Data4[7] = (UINT8) StrToHex(InString, 34, 2);
-
- return Guid;
-} // EFI_GUID StringAsGuid()
+ 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++;
+ }
+ MyFreePool(Handles);
+ return (Ejected > 0);
+} // VOID EjectMedia()
// Returns TRUE if the two GUIDs are equal, FALSE otherwise
BOOLEAN GuidsAreEqual(EFI_GUID *Guid1, EFI_GUID *Guid2) {
- return (CompareMem(Guid1, Guid2, 16) == 0);
+ return (CompareMem(Guid1, Guid2, 16) == 0);
} // BOOLEAN GuidsAreEqual()
+// Erase linked-list of UINT32 values....
+VOID EraseUint32List(UINT32_LIST **TheList) {
+ UINT32_LIST *NextItem;
+
+ while (*TheList) {
+ NextItem = (*TheList)->Next;
+ FreePool(*TheList);
+ *TheList = NextItem;
+ } // while
+} // EraseUin32List()