1 /** @file
2   Driver to implement English version of Unicode Collation Protocol.
3 
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 
16 #include "UnicodeCollationEng.h"
17 
18 CHAR8 mEngUpperMap[MAP_TABLE_SIZE];
19 CHAR8 mEngLowerMap[MAP_TABLE_SIZE];
20 CHAR8 mEngInfoMap[MAP_TABLE_SIZE];
21 
22 CHAR8 mOtherChars[] = {
23   '0',
24   '1',
25   '2',
26   '3',
27   '4',
28   '5',
29   '6',
30   '7',
31   '8',
32   '9',
33   '\\',
34   '.',
35   '_',
36   '^',
37   '$',
38   '~',
39   '!',
40   '#',
41   '%',
42   '&',
43   '-',
44   '{',
45   '}',
46   '(',
47   ')',
48   '@',
49   '`',
50   '\'',
51   '\0'
52 };
53 
54 EFI_HANDLE  mHandle = NULL;
55 
56 //
57 // EFI Unicode Collation Protocol supporting ISO 639-2 language code
58 //
59 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_COLLATION_PROTOCOL  UnicodeEng = {
60   EngStriColl,
61   EngMetaiMatch,
62   EngStrLwr,
63   EngStrUpr,
64   EngFatToStr,
65   EngStrToFat,
66   "eng"
67 };
68 
69 //
70 // EFI Unicode Collation2 Protocol supporting RFC 4646 language code
71 //
72 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_COLLATION_PROTOCOL  Unicode2Eng = {
73   EngStriColl,
74   EngMetaiMatch,
75   EngStrLwr,
76   EngStrUpr,
77   EngFatToStr,
78   EngStrToFat,
79   "en"
80 };
81 
82 /**
83   The user Entry Point for English module.
84 
85   This function initializes unicode character mapping and then installs Unicode
86   Collation & Unicode Collation 2 Protocols based on the feature flags.
87 
88   @param  ImageHandle    The firmware allocated handle for the EFI image.
89   @param  SystemTable    A pointer to the EFI System Table.
90 
91   @retval EFI_SUCCESS    The entry point is executed successfully.
92   @retval other          Some error occurs when executing this entry point.
93 
94 **/
95 EFI_STATUS
96 EFIAPI
InitializeUnicodeCollationEng(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)97 InitializeUnicodeCollationEng (
98   IN EFI_HANDLE       ImageHandle,
99   IN EFI_SYSTEM_TABLE *SystemTable
100   )
101 {
102   EFI_STATUS  Status;
103   UINTN       Index;
104   UINTN       Index2;
105 
106   //
107   // Initialize mapping tables for the supported languages
108   //
109   for (Index = 0; Index < MAP_TABLE_SIZE; Index++) {
110     mEngUpperMap[Index] = (CHAR8) Index;
111     mEngLowerMap[Index] = (CHAR8) Index;
112     mEngInfoMap[Index]  = 0;
113 
114     if ((Index >= 'a' && Index <= 'z') || (Index >= 0xe0 && Index <= 0xf6) || (Index >= 0xf8 && Index <= 0xfe)) {
115 
116       Index2                = Index - 0x20;
117       mEngUpperMap[Index]   = (CHAR8) Index2;
118       mEngLowerMap[Index2]  = (CHAR8) Index;
119 
120       mEngInfoMap[Index] |= CHAR_FAT_VALID;
121       mEngInfoMap[Index2] |= CHAR_FAT_VALID;
122     }
123   }
124 
125   for (Index = 0; mOtherChars[Index] != 0; Index++) {
126     Index2 = mOtherChars[Index];
127     mEngInfoMap[Index2] |= CHAR_FAT_VALID;
128   }
129 
130   if (FeaturePcdGet (PcdUnicodeCollation2Support)) {
131     if (FeaturePcdGet (PcdUnicodeCollationSupport)) {
132       Status = gBS->InstallMultipleProtocolInterfaces (
133                       &mHandle,
134                       &gEfiUnicodeCollationProtocolGuid,
135                       &UnicodeEng,
136                       &gEfiUnicodeCollation2ProtocolGuid,
137                       &Unicode2Eng,
138                       NULL
139                       );
140       ASSERT_EFI_ERROR (Status);
141     } else {
142       Status = gBS->InstallMultipleProtocolInterfaces (
143                       &mHandle,
144                       &gEfiUnicodeCollation2ProtocolGuid,
145                       &Unicode2Eng,
146                       NULL
147                       );
148       ASSERT_EFI_ERROR (Status);
149     }
150   } else {
151     if (FeaturePcdGet (PcdUnicodeCollationSupport)) {
152       Status = gBS->InstallMultipleProtocolInterfaces (
153                       &mHandle,
154                       &gEfiUnicodeCollationProtocolGuid,
155                       &UnicodeEng,
156                       NULL
157                       );
158       ASSERT_EFI_ERROR (Status);
159     } else {
160       //
161       // This module must support to produce at least one of Unicode Collation Protocol
162       // and Unicode Collation 2 Protocol.
163       //
164       ASSERT (FALSE);
165       Status = EFI_UNSUPPORTED;
166     }
167   }
168 
169   return Status;
170 }
171 
172 
173 /**
174   Performs a case-insensitive comparison of two Null-terminated strings.
175 
176   @param  This Protocol instance pointer.
177   @param  Str1 A pointer to a Null-terminated string.
178   @param  Str2 A pointer to a Null-terminated string.
179 
180   @retval 0   Str1 is equivalent to Str2
181   @retval > 0 Str1 is lexically greater than Str2
182   @retval < 0 Str1 is lexically less than Str2
183 
184 **/
185 INTN
186 EFIAPI
EngStriColl(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN CHAR16 * Str1,IN CHAR16 * Str2)187 EngStriColl (
188   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
189   IN CHAR16                           *Str1,
190   IN CHAR16                           *Str2
191   )
192 {
193   while (*Str1 != 0) {
194     if (TO_UPPER (*Str1) != TO_UPPER (*Str2)) {
195       break;
196     }
197 
198     Str1 += 1;
199     Str2 += 1;
200   }
201 
202   return TO_UPPER (*Str1) - TO_UPPER (*Str2);
203 }
204 
205 
206 /**
207   Converts all the characters in a Null-terminated string to
208   lower case characters.
209 
210   @param  This   Protocol instance pointer.
211   @param  Str    A pointer to a Null-terminated string.
212 
213 **/
214 VOID
215 EFIAPI
EngStrLwr(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN OUT CHAR16 * Str)216 EngStrLwr (
217   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
218   IN OUT CHAR16                       *Str
219   )
220 {
221   while (*Str != 0) {
222     *Str = TO_LOWER (*Str);
223     Str += 1;
224   }
225 }
226 
227 
228 /**
229   Converts all the characters in a Null-terminated string to upper
230   case characters.
231 
232   @param  This   Protocol instance pointer.
233   @param  Str    A pointer to a Null-terminated string.
234 
235 **/
236 VOID
237 EFIAPI
EngStrUpr(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN OUT CHAR16 * Str)238 EngStrUpr (
239   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
240   IN OUT CHAR16                       *Str
241   )
242 {
243   while (*Str != 0) {
244     *Str = TO_UPPER (*Str);
245     Str += 1;
246   }
247 }
248 
249 /**
250   Performs a case-insensitive comparison of a Null-terminated
251   pattern string and a Null-terminated string.
252 
253   @param  This    Protocol instance pointer.
254   @param  String  A pointer to a Null-terminated string.
255   @param  Pattern A pointer to a Null-terminated pattern string.
256 
257   @retval TRUE    Pattern was found in String.
258   @retval FALSE   Pattern was not found in String.
259 
260 **/
261 BOOLEAN
262 EFIAPI
EngMetaiMatch(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN CHAR16 * String,IN CHAR16 * Pattern)263 EngMetaiMatch (
264   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
265   IN CHAR16                           *String,
266   IN CHAR16                           *Pattern
267   )
268 {
269   CHAR16  CharC;
270   CHAR16  CharP;
271   CHAR16  Index3;
272 
273   for (;;) {
274     CharP = *Pattern;
275     Pattern += 1;
276 
277     switch (CharP) {
278     case 0:
279       //
280       // End of pattern.  If end of string, TRUE match
281       //
282       if (*String != 0) {
283         return FALSE;
284       } else {
285         return TRUE;
286       }
287 
288     case '*':
289       //
290       // Match zero or more chars
291       //
292       while (*String != 0) {
293         if (EngMetaiMatch (This, String, Pattern)) {
294           return TRUE;
295         }
296 
297         String += 1;
298       }
299 
300       return EngMetaiMatch (This, String, Pattern);
301 
302     case '?':
303       //
304       // Match any one char
305       //
306       if (*String == 0) {
307         return FALSE;
308       }
309 
310       String += 1;
311       break;
312 
313     case '[':
314       //
315       // Match char set
316       //
317       CharC = *String;
318       if (CharC == 0) {
319         //
320         // syntax problem
321         //
322         return FALSE;
323       }
324 
325       Index3  = 0;
326       CharP   = *Pattern++;
327       while (CharP != 0) {
328         if (CharP == ']') {
329           return FALSE;
330         }
331 
332         if (CharP == '-') {
333           //
334           // if range of chars, get high range
335           //
336           CharP = *Pattern;
337           if (CharP == 0 || CharP == ']') {
338             //
339             // syntax problem
340             //
341             return FALSE;
342           }
343 
344           if (TO_UPPER (CharC) >= TO_UPPER (Index3) && TO_UPPER (CharC) <= TO_UPPER (CharP)) {
345             //
346             // if in range, it's a match
347             //
348             break;
349           }
350         }
351 
352         Index3 = CharP;
353         if (TO_UPPER (CharC) == TO_UPPER (CharP)) {
354           //
355           // if char matches
356           //
357           break;
358         }
359 
360         CharP = *Pattern++;
361       }
362       //
363       // skip to end of match char set
364       //
365       while ((CharP != 0) && (CharP != ']')) {
366         CharP = *Pattern;
367         Pattern += 1;
368       }
369 
370       String += 1;
371       break;
372 
373     default:
374       CharC = *String;
375       if (TO_UPPER (CharC) != TO_UPPER (CharP)) {
376         return FALSE;
377       }
378 
379       String += 1;
380       break;
381     }
382   }
383 }
384 
385 
386 /**
387   Converts an 8.3 FAT file name in an OEM character set to a Null-terminated string.
388 
389   @param  This    Protocol instance pointer.
390   @param  FatSize The size of the string Fat in bytes.
391   @param  Fat     A pointer to a Null-terminated string that contains an 8.3 file
392                   name using an 8-bit OEM character set.
393   @param  String  A pointer to a Null-terminated string. The string must
394                   be preallocated to hold FatSize characters.
395 
396 **/
397 VOID
398 EFIAPI
EngFatToStr(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN UINTN FatSize,IN CHAR8 * Fat,OUT CHAR16 * String)399 EngFatToStr (
400   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
401   IN UINTN                            FatSize,
402   IN CHAR8                            *Fat,
403   OUT CHAR16                          *String
404   )
405 {
406   //
407   // No DBCS issues, just expand and add null terminate to end of string
408   //
409   while ((*Fat != 0) && (FatSize != 0)) {
410     *String = *Fat;
411     String += 1;
412     Fat += 1;
413     FatSize -= 1;
414   }
415 
416   *String = 0;
417 }
418 
419 
420 /**
421   Converts a Null-terminated string to legal characters in a FAT
422   filename using an OEM character set.
423 
424   @param  This    Protocol instance pointer.
425   @param  String  A pointer to a Null-terminated string. The string must
426                   be preallocated to hold FatSize characters.
427   @param  FatSize The size of the string Fat in bytes.
428   @param  Fat     A pointer to a Null-terminated string that contains an 8.3 file
429                   name using an OEM character set.
430 
431   @retval TRUE    Fat is a Long File Name
432   @retval FALSE   Fat is an 8.3 file name
433 
434 **/
435 BOOLEAN
436 EFIAPI
EngStrToFat(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN CHAR16 * String,IN UINTN FatSize,OUT CHAR8 * Fat)437 EngStrToFat (
438   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
439   IN CHAR16                           *String,
440   IN UINTN                            FatSize,
441   OUT CHAR8                           *Fat
442   )
443 {
444   BOOLEAN SpecialCharExist;
445 
446   SpecialCharExist = FALSE;
447   while ((*String != 0) && (FatSize != 0)) {
448     //
449     // Skip '.' or ' ' when making a fat name
450     //
451     if (*String != '.' && *String != ' ') {
452       //
453       // If this is a valid fat char, move it.
454       // Otherwise, move a '_' and flag the fact that the name needs a long file name.
455       //
456       if (*String < MAP_TABLE_SIZE && ((mEngInfoMap[*String] & CHAR_FAT_VALID) != 0)) {
457         *Fat = mEngUpperMap[*String];
458       } else {
459         *Fat              = '_';
460         SpecialCharExist  = TRUE;
461       }
462 
463       Fat += 1;
464       FatSize -= 1;
465     }
466 
467     String += 1;
468   }
469   //
470   // Do not terminate that fat string
471   //
472   return SpecialCharExist;
473 }
474