blob: ada4825181bece64e7cc363c4198415cf48d71d0 [file] [log] [blame]
/** @file
Driver to implement English version of Unicode Collation Protocol.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
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;
}