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