1 /** @file
2 Module produce UC2 on top of UC.
3 
4 UEFI 2.1 specification supersedes Inte's EFI Specification 1.10.
5 EFI_UNICODE_COLLATION_PROTOCOL defined in Inte's EFI Specification 1.10 is replaced by
6 EFI_UNICODE_COLLATION_PROTOCOL in UEFI 2.1.
7 This module produces UC2 on top of UC. This module is used on platform when both of
8 these two conditions are true:
9 1) EFI 1.10 module producing UC present
10 2) And the rest of modules on the platform consume UC2
11 
12 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
13 This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution.  The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
17 
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 Module Name:
21 
22 **/
23 
24 #include <PiDxe.h>
25 #include <Protocol/UnicodeCollation.h>
26 #include <Library/BaseLib.h>
27 #include <Library/DebugLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Library/UefiDriverEntryPoint.h>
30 #include <Library/UefiLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/HiiLib.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/LanguageLib.h>
35 
36 /**
37   Performs a case-insensitive comparison of two Null-terminated strings.
38 
39   @param  This Protocol instance pointer.
40   @param  Str1 A pointer to a Null-terminated string.
41   @param  Str2 A pointer to a Null-terminated string.
42 
43   @retval 0   Str1 is equivalent to Str2
44   @retval > 0 Str1 is lexically greater than Str2
45   @retval < 0 Str1 is lexically less than Str2
46 
47 **/
48 INTN
49 EFIAPI
50 StriColl (
51   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
52   IN CHAR16                           *Str1,
53   IN CHAR16                           *Str2
54   );
55 
56 /**
57   Converts all the characters in a Null-terminated string to
58   lower case characters.
59 
60   @param  This   Protocol instance pointer.
61   @param  Str    A pointer to a Null-terminated string.
62 
63 **/
64 VOID
65 EFIAPI
66 StrLwr (
67   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
68   IN OUT CHAR16                       *Str
69   );
70 
71 /**
72   Converts all the characters in a Null-terminated string to upper
73   case characters.
74 
75   @param  This   Protocol instance pointer.
76   @param  Str    A pointer to a Null-terminated string.
77 
78 **/
79 VOID
80 EFIAPI
81 StrUpr (
82   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
83   IN OUT CHAR16                       *Str
84   );
85 
86 /**
87   Performs a case-insensitive comparison of a Null-terminated
88   pattern string and a Null-terminated string.
89 
90   @param  This    Protocol instance pointer.
91   @param  String  A pointer to a Null-terminated string.
92   @param  Pattern A pointer to a Null-terminated pattern string.
93 
94   @retval TRUE    Pattern was found in String.
95   @retval FALSE   Pattern was not found in String.
96 
97 **/
98 BOOLEAN
99 EFIAPI
100 MetaiMatch (
101   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
102   IN CHAR16                           *String,
103   IN CHAR16                           *Pattern
104   );
105 
106 /**
107   Converts an 8.3 FAT file name in an OEM character set to a Null-terminated string.
108 
109   @param  This    Protocol instance pointer.
110   @param  FatSize The size of the string Fat in bytes.
111   @param  Fat     A pointer to a Null-terminated string that contains an 8.3 file
112                   name using an OEM character set.
113   @param  String  A pointer to a Null-terminated string. The string must
114                   be preallocated to hold FatSize characters.
115 
116 **/
117 VOID
118 EFIAPI
119 FatToStr (
120   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
121   IN UINTN                            FatSize,
122   IN CHAR8                            *Fat,
123   OUT CHAR16                          *String
124   );
125 
126 /**
127   Converts a Null-terminated string to legal characters in a FAT
128   filename using an OEM character set.
129 
130   @param  This    Protocol instance pointer.
131   @param  String  A pointer to a Null-terminated string. The string must
132                   be preallocated to hold FatSize characters.
133   @param  FatSize The size of the string Fat in bytes.
134   @param  Fat     A pointer to a Null-terminated string that contains an 8.3 file
135                   name using an OEM character set.
136 
137   @retval TRUE    Fat is a Long File Name
138   @retval FALSE   Fat is an 8.3 file name
139 
140 **/
141 BOOLEAN
142 EFIAPI
143 StrToFat (
144   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
145   IN CHAR16                           *String,
146   IN UINTN                            FatSize,
147   OUT CHAR8                           *Fat
148   );
149 
150 #define UC2_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('_', 'U', 'C', '2')
151 
152 typedef struct {
153   UINT32                          Signature;
154   EFI_UNICODE_COLLATION_PROTOCOL  Uc2;
155   EFI_UNICODE_COLLATION_PROTOCOL *Uc;
156 } UC2_PRIVATE_DATA;
157 
158 #define UC2_PRIVATE_DATA_FROM_THIS(a) CR (a, UC2_PRIVATE_DATA, Uc2, UC2_PRIVATE_DATA_SIGNATURE)
159 
160 //
161 // Firmware Volume Protocol template
162 //
163 EFI_EVENT  mUc2Registration;
164 
165 UC2_PRIVATE_DATA gUC2PrivateDataTemplate = {
166   UC2_PRIVATE_DATA_SIGNATURE,
167   {
168     StriColl,
169     MetaiMatch,
170     StrLwr,
171     StrUpr,
172     FatToStr,
173     StrToFat,
174     NULL
175   },
176   NULL
177 };
178 
179 //
180 // Module globals
181 //
182 /**
183   This notification function is invoked when an instance of the
184   EFI_UNICODE_COLLATION_PROTOCOL is produced. It installs another instance of the
185   EFI_UNICODE_COLLATION_PROTOCOL2 on the same handle.
186 
187   @param  Event                 The event that occured
188   @param  Context               Context of event. Not used in this nofication function.
189 
190 **/
191 VOID
192 EFIAPI
UcNotificationEvent(IN EFI_EVENT Event,IN VOID * Context)193 UcNotificationEvent (
194   IN  EFI_EVENT       Event,
195   IN  VOID            *Context
196   )
197 {
198   EFI_STATUS                     Status;
199   UINTN                          BufferSize;
200   EFI_HANDLE                     Handle;
201   UC2_PRIVATE_DATA               *Private;
202   EFI_UNICODE_COLLATION_PROTOCOL *Uc2;
203 
204   while (TRUE) {
205     BufferSize = sizeof (Handle);
206     Status = gBS->LocateHandle (
207                     ByRegisterNotify,
208                     &gEfiUnicodeCollationProtocolGuid,
209                     mUc2Registration,
210                     &BufferSize,
211                     &Handle
212                     );
213     if (EFI_ERROR (Status)) {
214       //
215       // Exit Path of While Loop....
216       //
217       break;
218     }
219 
220     //
221     // Skip this handle if the Firmware Volume Protocol is already installed
222     //
223     Status = gBS->HandleProtocol (
224                     Handle,
225                     &gEfiUnicodeCollation2ProtocolGuid,
226                     (VOID **)&Uc2
227                     );
228     if (!EFI_ERROR (Status)) {
229       continue;
230     }
231 
232     //
233     // Allocate private data structure
234     //
235     Private = AllocateCopyPool (sizeof (UC2_PRIVATE_DATA), &gUC2PrivateDataTemplate);
236     if (Private == NULL) {
237       continue;
238     }
239 
240     //
241     // Retrieve the UC Protocol
242     //
243     Status = gBS->HandleProtocol (
244                     Handle,
245                     &gEfiUnicodeCollationProtocolGuid,
246                     (VOID **)&Private->Uc
247                     );
248     ASSERT_EFI_ERROR (Status);
249 
250     //
251     // Fill in rest of private data structure
252     //
253     Private->Uc2.SupportedLanguages = ConvertLanguagesIso639ToRfc4646 (Private->Uc->SupportedLanguages);
254     if (Private->Uc2.SupportedLanguages != NULL) {
255 
256       //
257       // Install UC2 Protocol onto same handle
258       //
259       Status = gBS->InstallMultipleProtocolInterfaces (
260                       &Handle,
261                       &gEfiUnicodeCollation2ProtocolGuid,
262                       &Private->Uc2,
263                       NULL
264                       );
265       ASSERT_EFI_ERROR (Status);
266     }
267   }
268 }
269 
270 
271 /**
272   The user Entry Point for DXE driver. The user code starts with this function
273   as the real entry point for the image goes into a library that calls this
274   function.
275 
276   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
277   @param[in] SystemTable    A pointer to the EFI System Table.
278 
279   @retval EFI_SUCCESS       The entry point is executed successfully.
280   @retval other             Some error occurs when executing this entry point.
281 
282 **/
283 EFI_STATUS
284 EFIAPI
InitializeUC2(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)285 InitializeUC2 (
286   IN EFI_HANDLE        ImageHandle,
287   IN EFI_SYSTEM_TABLE  *SystemTable
288   )
289 {
290   EfiCreateProtocolNotifyEvent (
291     &gEfiUnicodeCollationProtocolGuid,
292     TPL_CALLBACK,
293     UcNotificationEvent,
294     NULL,
295     &mUc2Registration
296     );
297   return EFI_SUCCESS;
298 }
299 
300 
301 /**
302   Performs a case-insensitive comparison of two Null-terminated strings.
303 
304   @param  This Protocol instance pointer.
305   @param  Str1 A pointer to a Null-terminated string.
306   @param  Str2 A pointer to a Null-terminated string.
307 
308   @retval 0   Str1 is equivalent to Str2
309   @retval > 0 Str1 is lexically greater than Str2
310   @retval < 0 Str1 is lexically less than Str2
311 
312 **/
313 INTN
314 EFIAPI
StriColl(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN CHAR16 * Str1,IN CHAR16 * Str2)315 StriColl (
316   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
317   IN CHAR16                           *Str1,
318   IN CHAR16                           *Str2
319   )
320 {
321   UC2_PRIVATE_DATA *Private;
322 
323   Private = UC2_PRIVATE_DATA_FROM_THIS (This);
324 
325   return Private->Uc->StriColl (Private->Uc, Str1, Str2);
326 }
327 
328 
329 /**
330   Converts all the characters in a Null-terminated string to
331   lower case characters.
332 
333   @param  This   Protocol instance pointer.
334   @param  Str    A pointer to a Null-terminated string.
335 
336 **/
337 VOID
338 EFIAPI
StrLwr(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN OUT CHAR16 * Str)339 StrLwr (
340   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
341   IN OUT CHAR16                       *Str
342   )
343 {
344   UC2_PRIVATE_DATA *Private;
345 
346   Private = UC2_PRIVATE_DATA_FROM_THIS (This);
347 
348   Private->Uc->StrLwr (Private->Uc, Str);
349 }
350 
351 
352 /**
353   Converts all the characters in a Null-terminated string to upper
354   case characters.
355 
356   @param  This   Protocol instance pointer.
357   @param  Str    A pointer to a Null-terminated string.
358 
359 **/
360 VOID
361 EFIAPI
StrUpr(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN OUT CHAR16 * Str)362 StrUpr (
363   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
364   IN OUT CHAR16                       *Str
365   )
366 {
367   UC2_PRIVATE_DATA *Private;
368 
369   Private = UC2_PRIVATE_DATA_FROM_THIS (This);
370 
371   Private->Uc->StrUpr (Private->Uc, Str);
372 }
373 
374 /**
375   Performs a case-insensitive comparison of a Null-terminated
376   pattern string and a Null-terminated string.
377 
378   @param  This    Protocol instance pointer.
379   @param  String  A pointer to a Null-terminated string.
380   @param  Pattern A pointer to a Null-terminated pattern string.
381 
382   @retval TRUE    Pattern was found in String.
383   @retval FALSE   Pattern was not found in String.
384 
385 **/
386 BOOLEAN
387 EFIAPI
MetaiMatch(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN CHAR16 * String,IN CHAR16 * Pattern)388 MetaiMatch (
389   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
390   IN CHAR16                           *String,
391   IN CHAR16                           *Pattern
392   )
393 {
394   UC2_PRIVATE_DATA *Private;
395 
396   Private = UC2_PRIVATE_DATA_FROM_THIS (This);
397 
398   return Private->Uc->MetaiMatch (Private->Uc, String, Pattern);
399 }
400 
401 
402 /**
403   Converts an 8.3 FAT file name in an OEM character set to a Null-terminated string.
404 
405   @param  This    Protocol instance pointer.
406   @param  FatSize The size of the string Fat in bytes.
407   @param  Fat     A pointer to a Null-terminated string that contains an 8.3 file
408                   name using an 8-bit OEM character set.
409   @param  String  A pointer to a Null-terminated string. The string must
410                   be preallocated to hold FatSize characters.
411 
412 **/
413 VOID
414 EFIAPI
FatToStr(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN UINTN FatSize,IN CHAR8 * Fat,OUT CHAR16 * String)415 FatToStr (
416   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
417   IN UINTN                            FatSize,
418   IN CHAR8                            *Fat,
419   OUT CHAR16                          *String
420   )
421 {
422   UC2_PRIVATE_DATA *Private;
423 
424   Private = UC2_PRIVATE_DATA_FROM_THIS (This);
425 
426   Private->Uc->FatToStr (Private->Uc, FatSize, Fat, String);
427 }
428 
429 
430 /**
431   Converts a Null-terminated string to legal characters in a FAT
432   filename using an OEM character set.
433 
434   @param  This    Protocol instance pointer.
435   @param  String  A pointer to a Null-terminated string. The string must
436                   be preallocated to hold FatSize characters.
437   @param  FatSize The size of the string Fat in bytes.
438   @param  Fat     A pointer to a Null-terminated string that contains an 8.3 file
439                   name using an OEM character set.
440 
441   @retval TRUE    Fat is a Long File Name
442   @retval FALSE   Fat is an 8.3 file name
443 
444 **/
445 BOOLEAN
446 EFIAPI
StrToFat(IN EFI_UNICODE_COLLATION_PROTOCOL * This,IN CHAR16 * String,IN UINTN FatSize,OUT CHAR8 * Fat)447 StrToFat (
448   IN EFI_UNICODE_COLLATION_PROTOCOL   *This,
449   IN CHAR16                           *String,
450   IN UINTN                            FatSize,
451   OUT CHAR8                           *Fat
452   )
453 {
454   UC2_PRIVATE_DATA *Private;
455 
456   Private = UC2_PRIVATE_DATA_FROM_THIS (This);
457 
458   return Private->Uc->StrToFat (Private->Uc, String, FatSize, Fat);
459 }
460 
461