/** @file Driver to implement English version of Unicode Collation Protocol. Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "UnicodeCollationEng.h" CHAR8 mEngUpperMap[MAP_TABLE_SIZE]; CHAR8 mEngLowerMap[MAP_TABLE_SIZE]; CHAR8 mEngInfoMap[MAP_TABLE_SIZE]; CHAR8 mOtherChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '\\', '.', '_', '^', '$', '~', '!', '#', '%', '&', '-', '{', '}', '(', ')', '@', '`', '\'', '\0' }; EFI_HANDLE mHandle = NULL; // // EFI Unicode Collation Protocol supporting ISO 639-2 language code // GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_COLLATION_PROTOCOL UnicodeEng = { EngStriColl, EngMetaiMatch, EngStrLwr, EngStrUpr, EngFatToStr, EngStrToFat, "eng" }; // // EFI Unicode Collation2 Protocol supporting RFC 4646 language code // GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_COLLATION_PROTOCOL Unicode2Eng = { EngStriColl, EngMetaiMatch, EngStrLwr, EngStrUpr, EngFatToStr, EngStrToFat, "en" }; /** The user Entry Point for English module. This function initializes unicode character mapping and then installs Unicode Collation & Unicode Collation 2 Protocols based on the feature flags. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI InitializeUnicodeCollationEng ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINTN Index; UINTN Index2; // // Initialize mapping tables for the supported languages // for (Index = 0; Index < MAP_TABLE_SIZE; Index++) { mEngUpperMap[Index] = (CHAR8) Index; mEngLowerMap[Index] = (CHAR8) Index; mEngInfoMap[Index] = 0; if ((Index >= 'a' && Index <= 'z') || (Index >= 0xe0 && Index <= 0xf6) || (Index >= 0xf8 && Index <= 0xfe)) { Index2 = Index - 0x20; mEngUpperMap[Index] = (CHAR8) Index2; mEngLowerMap[Index2] = (CHAR8) Index; mEngInfoMap[Index] |= CHAR_FAT_VALID; mEngInfoMap[Index2] |= CHAR_FAT_VALID; } } for (Index = 0; mOtherChars[Index] != 0; Index++) { Index2 = mOtherChars[Index]; mEngInfoMap[Index2] |= CHAR_FAT_VALID; } if (FeaturePcdGet (PcdUnicodeCollation2Support)) { if (FeaturePcdGet (PcdUnicodeCollationSupport)) { Status = gBS->InstallMultipleProtocolInterfaces ( &mHandle, &gEfiUnicodeCollationProtocolGuid, &UnicodeEng, &gEfiUnicodeCollation2ProtocolGuid, &Unicode2Eng, NULL ); ASSERT_EFI_ERROR (Status); } else { Status = gBS->InstallMultipleProtocolInterfaces ( &mHandle, &gEfiUnicodeCollation2ProtocolGuid, &Unicode2Eng, NULL ); ASSERT_EFI_ERROR (Status); } } else { if (FeaturePcdGet (PcdUnicodeCollationSupport)) { Status = gBS->InstallMultipleProtocolInterfaces ( &mHandle, &gEfiUnicodeCollationProtocolGuid, &UnicodeEng, NULL ); ASSERT_EFI_ERROR (Status); } else { // // This module must support to produce at least one of Unicode Collation Protocol // and Unicode Collation 2 Protocol. // ASSERT (FALSE); Status = EFI_UNSUPPORTED; } } return Status; } /** Performs a case-insensitive comparison of two Null-terminated strings. @param This Protocol instance pointer. @param Str1 A pointer to a Null-terminated string. @param Str2 A pointer to a Null-terminated string. @retval 0 Str1 is equivalent to Str2 @retval > 0 Str1 is lexically greater than Str2 @retval < 0 Str1 is lexically less than Str2 **/ INTN EFIAPI EngStriColl ( IN EFI_UNICODE_COLLATION_PROTOCOL *This, IN CHAR16 *Str1, IN CHAR16 *Str2 ) { while (*Str1 != 0) { if (TO_UPPER (*Str1) != TO_UPPER (*Str2)) { break; } Str1 += 1; Str2 += 1; } return TO_UPPER (*Str1) - TO_UPPER (*Str2); } /** Converts all the characters in a Null-terminated string to lower case characters. @param This Protocol instance pointer. @param Str A pointer to a Null-terminated string. **/ VOID EFIAPI EngStrLwr ( IN EFI_UNICODE_COLLATION_PROTOCOL *This, IN OUT CHAR16 *Str ) { while (*Str != 0) { *Str = TO_LOWER (*Str); Str += 1; } } /** Converts all the characters in a Null-terminated string to upper case characters. @param This Protocol instance pointer. @param Str A pointer to a Null-terminated string. **/ VOID EFIAPI EngStrUpr ( IN EFI_UNICODE_COLLATION_PROTOCOL *This, IN OUT CHAR16 *Str ) { while (*Str != 0) { *Str = TO_UPPER (*Str); Str += 1; } } /** Performs a case-insensitive comparison of a Null-terminated pattern string and a Null-terminated string. @param This Protocol instance pointer. @param String A pointer to a Null-terminated string. @param Pattern A pointer to a Null-terminated pattern string. @retval TRUE Pattern was found in String. @retval FALSE Pattern was not found in String. **/ BOOLEAN EFIAPI EngMetaiMatch ( IN EFI_UNICODE_COLLATION_PROTOCOL *This, IN CHAR16 *String, IN CHAR16 *Pattern ) { CHAR16 CharC; CHAR16 CharP; CHAR16 Index3; for (;;) { CharP = *Pattern; Pattern += 1; switch (CharP) { case 0: // // End of pattern. If end of string, TRUE match // if (*String != 0) { return FALSE; } else { return TRUE; } case '*': // // Match zero or more chars // while (*String != 0) { if (EngMetaiMatch (This, String, Pattern)) { return TRUE; } String += 1; } return EngMetaiMatch (This, String, Pattern); case '?': // // Match any one char // if (*String == 0) { return FALSE; } String += 1; break; case '[': // // Match char set // CharC = *String; if (CharC == 0) { // // syntax problem // return FALSE; } Index3 = 0; CharP = *Pattern++; while (CharP != 0) { if (CharP == ']') { return FALSE; } if (CharP == '-') { // // if range of chars, get high range // CharP = *Pattern; if (CharP == 0 || CharP == ']') { // // syntax problem // return FALSE; } if (TO_UPPER (CharC) >= TO_UPPER (Index3) && TO_UPPER (CharC) <= TO_UPPER (CharP)) { // // if in range, it's a match // break; } } Index3 = CharP; if (TO_UPPER (CharC) == TO_UPPER (CharP)) { // // if char matches // break; } CharP = *Pattern++; } // // skip to end of match char set // while ((CharP != 0) && (CharP != ']')) { CharP = *Pattern; Pattern += 1; } String += 1; break; default: CharC = *String; if (TO_UPPER (CharC) != TO_UPPER (CharP)) { return FALSE; } String += 1; break; } } } /** Converts an 8.3 FAT file name in an OEM character set to a Null-terminated string. @param This Protocol instance pointer. @param FatSize The size of the string Fat in bytes. @param Fat A pointer to a Null-terminated string that contains an 8.3 file name using an 8-bit OEM character set. @param String A pointer to a Null-terminated string. The string must be preallocated to hold FatSize characters. **/ VOID EFIAPI EngFatToStr ( IN EFI_UNICODE_COLLATION_PROTOCOL *This, IN UINTN FatSize, IN CHAR8 *Fat, OUT CHAR16 *String ) { // // No DBCS issues, just expand and add null terminate to end of string // while ((*Fat != 0) && (FatSize != 0)) { *String = *Fat; String += 1; Fat += 1; FatSize -= 1; } *String = 0; } /** Converts a Null-terminated string to legal characters in a FAT filename using an OEM character set. @param This Protocol instance pointer. @param String A pointer to a Null-terminated string. The string must be preallocated to hold FatSize characters. @param FatSize The size of the string Fat in bytes. @param Fat A pointer to a Null-terminated string that contains an 8.3 file name using an OEM character set. @retval TRUE Fat is a Long File Name @retval FALSE Fat is an 8.3 file name **/ BOOLEAN EFIAPI EngStrToFat ( IN EFI_UNICODE_COLLATION_PROTOCOL *This, IN CHAR16 *String, IN UINTN FatSize, OUT CHAR8 *Fat ) { BOOLEAN SpecialCharExist; SpecialCharExist = FALSE; while ((*String != 0) && (FatSize != 0)) { // // Skip '.' or ' ' when making a fat name // if (*String != '.' && *String != ' ') { // // If this is a valid fat char, move it. // Otherwise, move a '_' and flag the fact that the name needs a long file name. // if (*String < MAP_TABLE_SIZE && ((mEngInfoMap[*String] & CHAR_FAT_VALID) != 0)) { *Fat = mEngUpperMap[*String]; } else { *Fat = '_'; SpecialCharExist = TRUE; } Fat += 1; FatSize -= 1; } String += 1; } // // Do not terminate that fat string // return SpecialCharExist; }