X-Git-Url: https://code.delx.au/refind/blobdiff_plain/7f97f502da6c482383f038970e788e1d005d391b..480ba418c97ece5557ac0efc5dc189ff19fb8b8f:/refind/lib.c diff --git a/refind/lib.c b/refind/lib.c index 3a75cdf..9c7d1f6 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -63,6 +63,7 @@ #include "../include/RemovableMedia.h" #include "gpt.h" #include "config.h" +#include "mystrings.h" #ifdef __MAKEWITH_GNUEFI #define EfiReallocatePool ReallocatePool @@ -997,9 +998,6 @@ VOID ScanVolume(REFIT_VOLUME *Volume) // open the root directory of the volume Volume->RootDir = LibOpenRoot(Volume->DeviceHandle); - // Set volume icon based on .VolumeBadge icon or disk kind - SetVolumeBadgeIcon(Volume); - Volume->VolName = GetVolumeName(Volume); if (Volume->RootDir == NULL) { @@ -1014,10 +1012,6 @@ VOID ScanVolume(REFIT_VOLUME *Volume) } } // if/else - // get custom volume icons if present - if (!Volume->VolIconImage) { - Volume->VolIconImage = egLoadIconAnyType(Volume->RootDir, L"", L".VolumeIcon", GlobalConfig.IconSizes[ICON_SIZE_BIG]); - } } // ScanVolume() static VOID ScanExtendedPartition(REFIT_VOLUME *WholeDiskVolume, MBR_PARTITION_INFO *MbrEntry) @@ -1211,6 +1205,23 @@ VOID ScanVolumes(VOID) } // for } /* VOID ScanVolumes() */ +VOID SetVolumeIcons(VOID) { + UINTN VolumeIndex; + REFIT_VOLUME *Volume; + + for (VolumeIndex = 0; VolumeIndex < VolumesCount; VolumeIndex++) { + Volume = Volumes[VolumeIndex]; + // Set volume icon based on .VolumeBadge icon or disk kind + SetVolumeBadgeIcon(Volume); + if (Volumes[VolumeIndex]->DiskKind == DISK_KIND_INTERNAL) { + // get custom volume icons if present + if (!Volume->VolIconImage) { + Volume->VolIconImage = egLoadIconAnyType(Volume->RootDir, L"", L".VolumeIcon", GlobalConfig.IconSizes[ICON_SIZE_BIG]); + } + } + } // for +} // VOID SetVolumeIcons() + // // file and dir functions // @@ -1461,130 +1472,6 @@ INTN FindMem(IN VOID *Buffer, IN UINTN BufferLength, IN VOID *SearchString, IN U return -1; } -BOOLEAN StriSubCmp(IN CHAR16 *SmallStr, IN CHAR16 *BigStr) { - BOOLEAN Found = 0, Terminate = 0; - UINTN BigIndex = 0, SmallIndex = 0, BigStart = 0; - - 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; - - 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) && (Length1 == 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 -} // 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 // no dots, or if the input is NULL, returns an empty (but allocated) string. @@ -1669,89 +1556,6 @@ CHAR16 *FindPath(IN CHAR16* FullPath) { 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 (IN CHAR16 *String, IN 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) { @@ -1813,74 +1617,6 @@ BOOLEAN SplitVolumeAndFilename(IN OUT CHAR16 **Path, OUT CHAR16 **VolName) { } } // BOOLEAN SplitVolumeAndFilename() -// 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, CopyLength; - CHAR16 *Found = NULL; - - if (InString == NULL) - return NULL; - - StartOfElement = StrLen(InString); - // Find start & end of target element - for (i = 0; InString[i] != L'\0'; i++) { - if ((InString[i] >= L'0') && (InString[i] <= L'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, InLength; - BOOLEAN Found = FALSE; - CHAR16 *FoundString = NULL; - - if (InString != NULL) { - InLength = StrLen(InString); - // After while() loop, StartPos marks start of item #Index - while ((Index > 0) && (CurPos < InLength)) { - 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 < InLength) && (!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() - // 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, // "BIGVOL:\EFI\ubuntu\grubx64.efi" will return a VolName of "BIGVOL", a Path @@ -1909,40 +1645,7 @@ VOID SplitPathName(CHAR16 *InPath, CHAR16 **VolName, CHAR16 **Path, CHAR16 **Fil *Filename = NULL; } MyFreePool(Temp); -} // VOID SplitPathName - -// Returns TRUE if SmallString is an element in the comma-delimited List, -// FALSE otherwise. Performs comparison case-insensitively. -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 (MyStriCmp(OneElement, SmallString)) - 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() +} // 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 @@ -2031,128 +1734,6 @@ BOOLEAN EjectMedia(VOID) { return (Ejected > 0); } // VOID EjectMedia() -// Returns TRUE if *Input contains nothing but valid hexadecimal characters, -// FALSE otherwise. Note that a leading "0x" is NOT acceptable in the input! -BOOLEAN IsValidHex(CHAR16 *Input) { - BOOLEAN IsHex = TRUE; - UINTN i = 0; - - while ((Input[i] != L'\0') && IsHex) { - if (!(((Input[i] >= L'0') && (Input[i] <= L'9')) || - ((Input[i] >= L'A') && (Input[i] <= L'F')) || - ((Input[i] >= L'a') && (Input[i] <= L'f')))) { - IsHex = FALSE; - } - i++; - } // while - return IsHex; -} // BOOLEAN IsValidHex() - -// 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, InputLength; - CHAR16 a; - - if ((Input == NULL) || (NumChars == 0) || (NumChars > 16)) { - return 0; - } - - InputLength = StrLen(Input); - while ((Pos <= InputLength) && (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 != L'-') - retval = FALSE; - } else if (((a < L'a') || (a > L'f')) && - ((a < L'A') || (a > L'F')) && - ((a < L'0') && (a > L'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; - - 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() - // Returns TRUE if the two GUIDs are equal, FALSE otherwise BOOLEAN GuidsAreEqual(EFI_GUID *Guid1, EFI_GUID *Guid2) { return (CompareMem(Guid1, Guid2, 16) == 0);