// self recognition stuff
//
-// Converts forward slashes to backslashes and removes duplicate slashes.
+// Converts forward slashes to backslashes, removes duplicate slashes, and
+// removes slashes from both the start and end of the pathname.
// Necessary because some (buggy?) EFI implementations produce "\/" strings
-// in pathnames and because some user inputs can produce duplicate directory
-// separators
+// in pathnames, because some user inputs can produce duplicate directory
+// separators, and because we want consistent start and end slashes for
+// directory comparisons. A special case: If the PathName refers to root,
+// return "/", since some firmware implementations flake out if this
+// isn't present.
VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) {
CHAR16 *NewName;
- UINTN i, j = 0;
+ UINTN i, FinalChar = 0;
BOOLEAN LastWasSlash = FALSE;
- NewName = AllocateZeroPool(sizeof(CHAR16) * (StrLen(PathName) + 1));
+ NewName = AllocateZeroPool(sizeof(CHAR16) * (StrLen(PathName) + 2));
if (NewName != NULL) {
for (i = 0; i < StrLen(PathName); i++) {
if ((PathName[i] == L'/') || (PathName[i] == L'\\')) {
- if (!LastWasSlash)
- NewName[j++] = L'\\';
+ if ((!LastWasSlash) && (FinalChar != 0))
+ NewName[FinalChar++] = L'\\';
LastWasSlash = TRUE;
} else {
- NewName[j++] = PathName[i];
+ NewName[FinalChar++] = PathName[i];
LastWasSlash = FALSE;
} // if/else
} // for
- NewName[j] = 0;
+ 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);
{
EFI_STATUS Status;
CHAR16 *DevicePathAsString;
- UINTN i;
SelfImageHandle = ImageHandle;
Status = refit_call3_wrapper(BS->HandleProtocol, SelfImageHandle, &LoadedImageProtocol, (VOID **) &SelfLoadedImage);
// find the current directory
DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath);
CleanUpPathNameSlashes(DevicePathAsString);
- if (DevicePathAsString != NULL) {
- for (i = StrLen(DevicePathAsString); (i > 0) && (DevicePathAsString[i] != '\\'); i--) ;
- DevicePathAsString[i] = 0;
- } else
- DevicePathAsString[0] = 0;
- SelfDirPath = StrDuplicate(DevicePathAsString);
+ if (SelfDirPath != NULL)
+ FreePool(SelfDirPath);
+ SelfDirPath = FindPath(DevicePathAsString);
FreePool(DevicePathAsString);
return FinishInitRefitLib();
{
ReinitVolumes();
- // Below two lines were in rEFIt, but seem to cause problems on
- // most systems. OTOH, my Mac Mini produces (apparently harmless)
- // errors about "(re)opening our installation volume" (see the
- // next function) when returning from programs when these two lines
- // are removed. On the gripping hand, the Mac SOMETIMES crashes
- // when launching a second program even with these lines removed.
- // TODO: Figure out cause of above weirdness and fix it more
- // reliably!
- /* if (SelfVolume != NULL && SelfVolume->RootDir != NULL)
- SelfRootDir = SelfVolume->RootDir; */
+ if ((ST->Hdr.Revision >> 16) == 1) {
+ // Below two lines were in rEFIt, but seem to cause system crashes or
+ // reboots when launching OSes after returning from programs on most
+ // systems. OTOH, my Mac Mini produces errors about "(re)opening our
+ // installation volume" (see the next function) when returning from
+ // programs when these two lines are removed, and it often crashes
+ // when returning from a program or when launching a second program
+ // with these lines removed. Therefore, the preceding if() statement
+ // executes these lines only on EFIs with a major version number of 1
+ // (which Macs have) and not with 2 (which UEFI PCs have). My selection
+ // of hardware on which to test is limited, though, so this may be the
+ // wrong test, or there may be a better way to fix this problem.
+ // TODO: Figure out cause of above weirdness and fix it more
+ // reliably!
+ if (SelfVolume != NULL && SelfVolume->RootDir != NULL)
+ SelfRootDir = SelfVolume->RootDir;
+ } // if
return FinishInitRefitLib();
}
VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount)
{
UINTN AllocateCount;
-
+
*ElementCount = InitialElementCount;
if (*ElementCount > 0) {
AllocateCount = (*ElementCount + 7) & ~7; // next multiple of 8
FreePool(FileSystemInfoPtr);
}
+ if (Volume->VolName == NULL) {
+ Volume->VolName = StrDuplicate(L"Unknown");
+ }
// TODO: if no official volume name is found or it is empty, use something else, e.g.:
// - name from bytes 3 to 10 of the boot sector
// - partition number
BOOLEAN DirIterNext(IN OUT REFIT_DIR_ITER *DirIter, IN UINTN FilterMode, IN CHAR16 *FilePattern OPTIONAL,
OUT EFI_FILE_INFO **DirEntry)
{
+ BOOLEAN KeepGoing = TRUE;
+ UINTN i;
+ CHAR16 *OnePattern;
+
if (DirIter->LastFileInfo != NULL) {
FreePool(DirIter->LastFileInfo);
DirIter->LastFileInfo = NULL;
if (EFI_ERROR(DirIter->LastStatus))
return FALSE; // stop iteration
- for (;;) {
+ do {
DirIter->LastStatus = DirNextEntry(DirIter->DirHandle, &(DirIter->LastFileInfo), FilterMode);
if (EFI_ERROR(DirIter->LastStatus))
return FALSE;
return FALSE;
if (FilePattern != NULL) {
if ((DirIter->LastFileInfo->Attribute & EFI_FILE_DIRECTORY))
- break;
- if (MetaiMatch(DirIter->LastFileInfo->FileName, FilePattern))
- break;
+ KeepGoing = FALSE;
+ i = 0;
+ while (KeepGoing && (OnePattern = FindCommaDelimited(FilePattern, i++)) != NULL) {
+ if (MetaiMatch(DirIter->LastFileInfo->FileName, OnePattern))
+ KeepGoing = FALSE;
+ } // while
// else continue loop
} else
break;
- }
+ } while (KeepGoing);
*DirEntry = DirIter->LastFileInfo;
return TRUE;
// 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.
+// 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;