1 /** @file
2   Unicode Collation Support component that hides the trivial difference of Unicode Collation
3   and Unicode collation 2 Protocol.
4 
5   Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "Fat.h"
11 
12 EFI_UNICODE_COLLATION_PROTOCOL  *mUnicodeCollationInterface = NULL;
13 
14 /**
15   Worker function to initialize Unicode Collation support.
16 
17   It tries to locate Unicode Collation (2) protocol and matches it with current
18   platform language code.
19 
20   @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
21   @param  ProtocolGuid         The pointer to Unicode Collation (2) protocol GUID.
22   @param  VariableName         The name of the RFC 4646 or ISO 639-2 language variable.
23   @param  DefaultLanguage      The default language in case the RFC 4646 or ISO 639-2 language is absent.
24 
25   @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
26   @retval Others               The Unicode Collation (2) protocol has not been located.
27 
28 **/
29 EFI_STATUS
InitializeUnicodeCollationSupportWorker(IN EFI_HANDLE AgentHandle,IN EFI_GUID * ProtocolGuid,IN CONST CHAR16 * VariableName,IN CONST CHAR8 * DefaultLanguage)30 InitializeUnicodeCollationSupportWorker (
31   IN EFI_HANDLE         AgentHandle,
32   IN EFI_GUID           *ProtocolGuid,
33   IN CONST CHAR16       *VariableName,
34   IN CONST CHAR8        *DefaultLanguage
35   )
36 {
37   EFI_STATUS                      ReturnStatus;
38   EFI_STATUS                      Status;
39   UINTN                           NumHandles;
40   UINTN                           Index;
41   EFI_HANDLE                      *Handles;
42   EFI_UNICODE_COLLATION_PROTOCOL  *Uci;
43   BOOLEAN                         Iso639Language;
44   CHAR8                           *Language;
45   CHAR8                           *BestLanguage;
46 
47   Status = gBS->LocateHandleBuffer (
48                   ByProtocol,
49                   ProtocolGuid,
50                   NULL,
51                   &NumHandles,
52                   &Handles
53                   );
54   if (EFI_ERROR (Status)) {
55     return Status;
56   }
57 
58   Iso639Language = (BOOLEAN) (ProtocolGuid == &gEfiUnicodeCollationProtocolGuid);
59   GetEfiGlobalVariable2 (VariableName, (VOID**) &Language, NULL);
60 
61   ReturnStatus = EFI_UNSUPPORTED;
62   for (Index = 0; Index < NumHandles; Index++) {
63     //
64     // Open Unicode Collation Protocol
65     //
66     Status = gBS->OpenProtocol (
67                     Handles[Index],
68                     ProtocolGuid,
69                     (VOID **) &Uci,
70                     AgentHandle,
71                     NULL,
72                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
73                     );
74     if (EFI_ERROR (Status)) {
75       continue;
76     }
77 
78     //
79     // Find the best matching matching language from the supported languages
80     // of Unicode Collation (2) protocol.
81     //
82     BestLanguage = GetBestLanguage (
83                      Uci->SupportedLanguages,
84                      Iso639Language,
85                      (Language == NULL) ? "" : Language,
86                      DefaultLanguage,
87                      NULL
88                      );
89     if (BestLanguage != NULL) {
90       FreePool (BestLanguage);
91       mUnicodeCollationInterface = Uci;
92       ReturnStatus = EFI_SUCCESS;
93       break;
94     }
95   }
96 
97   if (Language != NULL) {
98     FreePool (Language);
99   }
100 
101   FreePool (Handles);
102 
103   return ReturnStatus;
104 }
105 
106 /**
107   Initialize Unicode Collation support.
108 
109   It tries to locate Unicode Collation 2 protocol and matches it with current
110   platform language code. If for any reason the first attempt fails, it then tries to
111   use Unicode Collation Protocol.
112 
113   @param  AgentHandle          The handle used to open Unicode Collation (2) protocol.
114 
115   @retval EFI_SUCCESS          The Unicode Collation (2) protocol has been successfully located.
116   @retval Others               The Unicode Collation (2) protocol has not been located.
117 
118 **/
119 EFI_STATUS
InitializeUnicodeCollationSupport(IN EFI_HANDLE AgentHandle)120 InitializeUnicodeCollationSupport (
121   IN EFI_HANDLE    AgentHandle
122   )
123 {
124 
125   EFI_STATUS       Status;
126 
127   Status = EFI_UNSUPPORTED;
128 
129   //
130   // First try to use RFC 4646 Unicode Collation 2 Protocol.
131   //
132   Status = InitializeUnicodeCollationSupportWorker (
133              AgentHandle,
134              &gEfiUnicodeCollation2ProtocolGuid,
135              L"PlatformLang",
136              (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang)
137              );
138   //
139   // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back
140   // on the ISO 639-2 Unicode Collation Protocol.
141   //
142   if (EFI_ERROR (Status)) {
143     Status = InitializeUnicodeCollationSupportWorker (
144                AgentHandle,
145                &gEfiUnicodeCollationProtocolGuid,
146                L"Lang",
147                (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang)
148                );
149   }
150 
151   return Status;
152 }
153 
154 
155 /**
156   Performs a case-insensitive comparison of two Null-terminated Unicode strings.
157 
158   @param  S1                   A pointer to a Null-terminated Unicode string.
159   @param  S2                   A pointer to a Null-terminated Unicode string.
160 
161   @retval 0                    S1 is equivalent to S2.
162   @retval >0                   S1 is lexically greater than S2.
163   @retval <0                   S1 is lexically less than S2.
164 **/
165 INTN
FatStriCmp(IN CHAR16 * S1,IN CHAR16 * S2)166 FatStriCmp (
167   IN CHAR16       *S1,
168   IN CHAR16       *S2
169   )
170 {
171   ASSERT (StrSize (S1) != 0);
172   ASSERT (StrSize (S2) != 0);
173   ASSERT (mUnicodeCollationInterface != NULL);
174 
175   return mUnicodeCollationInterface->StriColl (
176                                        mUnicodeCollationInterface,
177                                        S1,
178                                        S2
179                                        );
180 }
181 
182 
183 /**
184   Uppercase a string.
185 
186   @param  String                   The string which will be upper-cased.
187 
188 
189 **/
190 VOID
FatStrUpr(IN OUT CHAR16 * String)191 FatStrUpr (
192   IN OUT CHAR16   *String
193   )
194 {
195   ASSERT (StrSize (String) != 0);
196   ASSERT (mUnicodeCollationInterface != NULL);
197 
198   mUnicodeCollationInterface->StrUpr (mUnicodeCollationInterface, String);
199 }
200 
201 
202 /**
203   Lowercase a string
204 
205   @param  String                   The string which will be lower-cased.
206 
207 
208 **/
209 VOID
FatStrLwr(IN OUT CHAR16 * String)210 FatStrLwr (
211   IN OUT CHAR16   *String
212   )
213 {
214   ASSERT (StrSize (String) != 0);
215   ASSERT (mUnicodeCollationInterface != NULL);
216 
217   mUnicodeCollationInterface->StrLwr (mUnicodeCollationInterface, String);
218 }
219 
220 
221 /**
222   Convert FAT string to unicode string.
223 
224   @param  FatSize               The size of FAT string.
225   @param  Fat                   The FAT string.
226   @param  String                The unicode string.
227 
228   @return None.
229 
230 **/
231 VOID
FatFatToStr(IN UINTN FatSize,IN CHAR8 * Fat,OUT CHAR16 * String)232 FatFatToStr (
233   IN  UINTN                            FatSize,
234   IN  CHAR8                            *Fat,
235   OUT CHAR16                           *String
236   )
237 {
238   ASSERT (Fat != NULL);
239   ASSERT (String != NULL);
240   ASSERT (((UINTN) String & 0x01) == 0);
241   ASSERT (mUnicodeCollationInterface != NULL);
242 
243   mUnicodeCollationInterface->FatToStr (mUnicodeCollationInterface, FatSize, Fat, String);
244 }
245 
246 
247 /**
248   Convert unicode string to Fat string.
249 
250   @param  String                The unicode string.
251   @param  FatSize               The size of the FAT string.
252   @param  Fat                   The FAT string.
253 
254   @retval TRUE                  Convert successfully.
255   @retval FALSE                 Convert error.
256 
257 **/
258 BOOLEAN
FatStrToFat(IN CHAR16 * String,IN UINTN FatSize,OUT CHAR8 * Fat)259 FatStrToFat (
260   IN  CHAR16                          *String,
261   IN  UINTN                           FatSize,
262   OUT CHAR8                           *Fat
263   )
264 {
265   ASSERT (Fat != NULL);
266   ASSERT (StrSize (String) != 0);
267   ASSERT (mUnicodeCollationInterface != NULL);
268 
269   return mUnicodeCollationInterface->StrToFat (
270                                        mUnicodeCollationInterface,
271                                        String,
272                                        FatSize,
273                                        Fat
274                                        );
275 }
276