X-Git-Url: https://code.delx.au/refind/blobdiff_plain/f92a7032373fc63e9d8946574d4fb42464d1c916..add96ff8057d0c03026395992d9ecde081c8dca7:/refind/lib.c diff --git a/refind/lib.c b/refind/lib.c index 7d2a573..15132ad 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -193,6 +193,7 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle) // find the current directory DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath); + GlobalConfig.SelfDevicePath = FileDevicePath(SelfLoadedImage->DeviceHandle, DevicePathAsString); CleanUpPathNameSlashes(DevicePathAsString); MyFreePool(SelfDirPath); Temp = FindPath(DevicePathAsString); @@ -310,25 +311,12 @@ EFI_STATUS EfivarSetRaw(EFI_GUID *vendor, CHAR16 *name, CHAR8 *buf, UINTN size, // list functions // -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 - *ListPtr = AllocatePool(sizeof(VOID *) * AllocateCount); - } else { - *ListPtr = NULL; - } -} - VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement) { UINTN AllocateCount; - if ((*ElementCount & 7) == 0) { - AllocateCount = *ElementCount + 8; + if ((*ElementCount & 15) == 0) { + AllocateCount = *ElementCount + 16; if (*ElementCount == 0) *ListPtr = AllocatePool(sizeof(VOID *) * AllocateCount); else @@ -351,82 +339,6 @@ VOID FreeList(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount) } } // 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 // @@ -866,25 +778,25 @@ static VOID SetPartGuidAndName(REFIT_VOLUME *Volume, EFI_DEVICE_PATH_PROTOCOL *D 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, @@ -1336,7 +1248,6 @@ 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; @@ -1438,14 +1349,6 @@ MetaiMatch (IN CHAR16 *String, IN CHAR16 *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, @@ -1531,8 +1434,7 @@ CHAR16 * StripEfiExtension(CHAR16 *FileName) { 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))) { + if ((Length >= 4) && MyStriCmp(&Copy[Length - 4], L".efi")) { Copy[Length - 4] = 0; } // if } // if @@ -1558,31 +1460,50 @@ INTN FindMem(IN VOID *Buffer, IN UINTN BufferLength, IN VOID *SearchString, IN U 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 + BOOLEAN Found = 0, Terminate = 0; + UINTN BigIndex = 0, SmallIndex = 0, BigStart = 0; - return (Found); + if (SmallStr && BigStr) { + while (!Terminate) { + if (BigStr[BigIndex] == '\0') { + Terminate = 1; + } + if (SmallStr[SmallIndex] == '\0') { + Found = 1; + Terminate = 1; + } + if ((SmallStr[SmallIndex] & ~0x20) == (BigStr[BigIndex] & ~0x20)) { + SmallIndex++; + BigIndex++; + } else { + SmallIndex = 0; + BigStart++; + BigIndex = BigStart; + } + } // while + } // if + return Found; } // BOOLEAN StriSubCmp() +// Performs a case-insensitive string comparison. This function is necesary +// because some EFIs have buggy StriCmp() functions that actually perform +// case-sensitive comparisons. +// Returns TRUE if strings are identical, FALSE otherwise. +BOOLEAN MyStriCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString) { + if (FirstString && SecondString) { + while ((*FirstString != L'\0') && ((*FirstString & ~0x20) == (*SecondString & ~0x20))) { + FirstString++; + SecondString++; + } + return (*FirstString == *SecondString); + } else { + return FALSE; + } +} // BOOLEAN MyStriCmp() + // Convert input string to all-lowercase. +// DO NOT USE the standard StrLwr() function, since it's broken on some EFIs! VOID ToLower(CHAR16 * MyString) { UINTN i = 0; @@ -1614,7 +1535,7 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) { Length2 = StrLen(Second); NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2)); if (NewString != NULL) { - if ((*First != NULL) && (StrLen(*First) == 0)) { + if ((*First != NULL) && (Length1 == 0)) { MyFreePool(*First); *First = NULL; } @@ -1633,7 +1554,35 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) { } else { Print(L"Error! Unable to allocate memory in MergeStrings()!\n"); } // if/else -} // static CHAR16* MergeStrings() +} // VOID MergeStrings() + +// Similar to MergeStrings, but breaks the input string into word chunks and +// merges each word separately. Words are defined as string fragments separated +// by ' ', '_', or '-'. +VOID MergeWords(CHAR16 **MergeTo, CHAR16 *SourceString, CHAR16 AddChar) { + CHAR16 *Temp, *Word, *p; + BOOLEAN LineFinished = FALSE; + + if (SourceString) { + Temp = Word = p = StrDuplicate(SourceString); + if (Temp) { + while (!LineFinished) { + if ((*p == L' ') || (*p == L'_') || (*p == L'-') || (*p == L'\0')) { + if (*p == L'\0') + LineFinished = TRUE; + *p = L'\0'; + if (*Word != L'\0') + MergeStrings(MergeTo, Word, AddChar); + Word = p + 1; + } // if + p++; + } // while + MyFreePool(Temp); + } else { + Print(L"Error! Unable to allocate memory in MergeWords()!\n"); + } // if/else + } // if +} // VOID MergeWords() // Takes an input pathname (*Path) and returns the part of the filename from // the final dot onwards, converted to lowercase. If the filename includes @@ -1658,7 +1607,7 @@ CHAR16 *FindExtension(IN CHAR16 *Path) { } // while if (Found) { MergeStrings(&Extension, &Path[i], 0); - StrLwr(Extension); + ToLower(Extension); } // if (Found) } // if return (Extension); @@ -1818,7 +1767,7 @@ VOID FindVolumeAndFilename(IN EFI_DEVICE_PATH *loadpath, OUT REFIT_VOLUME **Devi while ((i < VolumesCount) && (!Found)) { VolumeDeviceString = DevicePathToStr(Volumes[i]->DevicePath); Temp = SplitDeviceString(VolumeDeviceString); - if (StriCmp(DeviceString, VolumeDeviceString) == 0) { + if (MyStriCmp(DeviceString, VolumeDeviceString)) { Found = TRUE; *DeviceVolume = Volumes[i]; } @@ -1986,8 +1935,7 @@ VOID SplitPathName(CHAR16 *InPath, CHAR16 **VolName, CHAR16 **Path, CHAR16 **Fil } // 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). +// FALSE otherwise. Performs comparison case-insensitively. BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List) { UINTN i = 0; BOOLEAN Found = FALSE; @@ -1995,7 +1943,7 @@ BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List) { if (SmallString && List) { while (!Found && (OneElement = FindCommaDelimited(List, i++))) { - if (StriCmp(OneElement, SmallString) == 0) + if (MyStriCmp(OneElement, SmallString)) Found = TRUE; } // while } // if @@ -2023,8 +1971,7 @@ BOOLEAN IsInSubstring(IN CHAR16 *BigString, IN CHAR16 *List) { // 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; @@ -2036,9 +1983,9 @@ BOOLEAN FilenameIn(REFIT_VOLUME *Volume, CHAR16 *Directory, CHAR16 *Filename, CH 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))) { + if (((TargetVolName != NULL) && ((Volume == NULL) || (!MyStriCmp(TargetVolName, Volume->VolName)))) || + ((TargetPath != NULL) && (!MyStriCmp(TargetPath, Directory))) || + ((TargetFilename != NULL) && (!MyStriCmp(TargetFilename, Filename)))) { Found = FALSE; } // if MyFreePool(OneElement);