1 /*++
2
3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 EfiDriverLib.c
15
16 Abstract:
17
18 Light weight lib to support EFI drivers.
19
20 --*/
21
22 #include "Tiano.h"
23 #include "EfiDriverLib.h"
24 #include EFI_ARCH_PROTOCOL_DEFINITION (StatusCode)
25
26 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
27
28 VOID
29 EFIAPI
30 OnStatusCodeInstall (
31 IN EFI_EVENT Event,
32 IN VOID *Context
33 );
34
35 #endif
36
37 //
38 // Global Interface for Debug Mask Protocol
39 //
40 EFI_DEBUG_MASK_PROTOCOL *gDebugMaskInterface = NULL;
41
42 EFI_STATUS
EfiInitializeDriverLib(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)43 EfiInitializeDriverLib (
44 IN EFI_HANDLE ImageHandle,
45 IN EFI_SYSTEM_TABLE *SystemTable
46 )
47 /*++
48
49 Routine Description:
50
51 Intialize Driver Lib if it has not yet been initialized.
52
53 Arguments:
54
55 ImageHandle - Standard EFI Image entry parameter
56
57 SystemTable - Standard EFI Image entry parameter
58
59 Returns:
60
61 EFI_STATUS always returns EFI_SUCCESS
62
63 --*/
64 {
65 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
66 VOID *Registration;
67 #endif
68
69 gST = SystemTable;
70
71 ASSERT (gST != NULL);
72
73 gBS = gST->BootServices;
74 gRT = gST->RuntimeServices;
75
76 ASSERT (gBS != NULL);
77 ASSERT (gRT != NULL);
78
79 //
80 // Get driver debug mask protocol interface
81 //
82 #ifdef EFI_DEBUG
83 gBS->HandleProtocol (
84 ImageHandle,
85 &gEfiDebugMaskProtocolGuid,
86 (VOID *) &gDebugMaskInterface
87 );
88 #endif
89
90 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
91 //
92 // Register EFI_STATUS_CODE_PROTOCOL notify function
93 //
94 EfiLibCreateProtocolNotifyEvent (
95 &gEfiStatusCodeRuntimeProtocolGuid,
96 EFI_TPL_CALLBACK,
97 OnStatusCodeInstall,
98 NULL,
99 &Registration
100 );
101
102 #endif
103
104 //
105 // Should be at EFI_D_INFO, but lets us know things are running
106 //
107 DEBUG ((EFI_D_INFO, "EfiInitializeDriverLib: Started\n"));
108
109 return EFI_SUCCESS;
110 }
111
112 STATIC
113 BOOLEAN
IsIso639LanguageCode(IN CHAR8 * Languages)114 IsIso639LanguageCode (
115 IN CHAR8 *Languages
116 )
117 /*++
118
119 Routine Description:
120
121 Tests whether a language code has format of ISO639-2.
122
123 Arguments:
124
125 Languages - The language code to be tested.
126
127 Returns:
128
129 TRUE - Language code format is ISO 639-2.
130 FALSE - Language code format is not ISO 639-2.
131
132 --*/
133 {
134 UINTN Index;
135
136 //
137 // Find out format of Languages
138 //
139 for (Index = 0; Languages[Index] != 0 && Languages[Index] != ';' && Languages[Index] != '-'; Index++);
140 if (Languages[Index] != 0) {
141 //
142 // RFC4646 language code
143 //
144 return FALSE;
145 }
146
147 //
148 // No ';' and '-', it's either ISO639-2 code (list) or single RFC4646 code
149 //
150 if (Index == 2) {
151 //
152 // Single RFC4646 language code without country code, e.g. "en"
153 //
154 return FALSE;
155 }
156
157 //
158 // Languages in format of ISO639-2
159 //
160 return TRUE;
161 }
162
163 BOOLEAN
EfiLibCompareLanguage(IN CHAR8 * Language1,IN CHAR8 * Language2)164 EfiLibCompareLanguage (
165 IN CHAR8 *Language1,
166 IN CHAR8 *Language2
167 )
168 /*++
169
170 Routine Description:
171
172 Compare the first language instance of two language codes, either could be a
173 single language code or a language code list. This function assume Language1
174 and Language2 has the same language code format, i.e. either ISO639-2 or RFC4646.
175
176 Arguments:
177
178 Language1 - The first language code to be tested.
179 Language2 - The second language code to be tested.
180
181 Returns:
182
183 TRUE - Language code match.
184 FALSE - Language code mismatch.
185
186 --*/
187 {
188 UINTN Index;
189
190 //
191 // Compare first two bytes of language tag
192 //
193 if ((Language1[0] != Language2[0]) || (Language1[1] != Language2[1])) {
194 return FALSE;
195 }
196
197 if (IsIso639LanguageCode (Language1)) {
198 //
199 // ISO639-2 language code, compare the third byte of language tag
200 //
201 return (BOOLEAN) ((Language1[2] == Language2[2]) ? TRUE : FALSE);
202 }
203
204 //
205 // RFC4646 language code
206 //
207 for (Index = 0; Language1[Index] != 0 && Language1[Index] != ';'; Index++);
208 if ((EfiAsciiStrnCmp (Language1, Language2, Index) == 0) && (Language2[Index] == 0 || Language2[Index] == ';')) {
209 return TRUE;
210 }
211
212 return FALSE;
213 }
214
215 STATIC
216 CHAR8 *
NextSupportedLanguage(IN CHAR8 * Languages)217 NextSupportedLanguage (
218 IN CHAR8 *Languages
219 )
220 /*++
221
222 Routine Description:
223
224 Step to next language code of a language code list.
225
226 Arguments:
227
228 Languages - The language code list to traverse.
229
230 Returns:
231
232 Pointer to next language code or NULL terminator if it's the last one.
233
234 --*/
235 {
236 UINTN Index;
237
238 if (IsIso639LanguageCode (Languages)) {
239 //
240 // ISO639-2 language code
241 //
242 return (Languages + 3);
243 }
244
245 //
246 // Search in RFC4646 language code list
247 //
248 for (Index = 0; Languages[Index] != 0 && Languages[Index] != ';'; Index++);
249 if (Languages[Index] == ';') {
250 Index++;
251 }
252 return (Languages + Index);
253 }
254
255 EFI_STATUS
EfiLibLookupUnicodeString(IN CHAR8 * Language,IN CHAR8 * SupportedLanguages,IN EFI_UNICODE_STRING_TABLE * UnicodeStringTable,OUT CHAR16 ** UnicodeString)256 EfiLibLookupUnicodeString (
257 IN CHAR8 *Language,
258 IN CHAR8 *SupportedLanguages,
259 IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable,
260 OUT CHAR16 **UnicodeString
261 )
262 /*++
263
264 Routine Description:
265
266 Translate a unicode string to a specified language if supported.
267
268 Arguments:
269
270 Language - The name of language to translate to
271 SupportedLanguages - Supported languages set
272 UnicodeStringTable - Pointer of one item in translation dictionary
273 UnicodeString - The translated string
274
275 Returns:
276
277 EFI_INVALID_PARAMETER - Invalid parameter
278 EFI_UNSUPPORTED - System not supported this language or this string translation
279 EFI_SUCCESS - String successfully translated
280
281 --*/
282 {
283 //
284 // Make sure the parameters are valid
285 //
286 if (Language == NULL || UnicodeString == NULL) {
287 return EFI_INVALID_PARAMETER;
288 }
289
290 //
291 // If there are no supported languages, or the Unicode String Table is empty, then the
292 // Unicode String specified by Language is not supported by this Unicode String Table
293 //
294 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
295 return EFI_UNSUPPORTED;
296 }
297
298 //
299 // Make sure Language is in the set of Supported Languages
300 //
301 while (*SupportedLanguages != 0) {
302 if (EfiLibCompareLanguage (Language, SupportedLanguages)) {
303
304 //
305 // Search the Unicode String Table for the matching Language specifier
306 //
307 while (UnicodeStringTable->Language != NULL) {
308 if (EfiLibCompareLanguage (Language, UnicodeStringTable->Language)) {
309
310 //
311 // A matching string was found, so return it
312 //
313 *UnicodeString = UnicodeStringTable->UnicodeString;
314 return EFI_SUCCESS;
315 }
316
317 UnicodeStringTable++;
318 }
319
320 return EFI_UNSUPPORTED;
321 }
322
323 SupportedLanguages = NextSupportedLanguage (SupportedLanguages);
324 }
325
326 return EFI_UNSUPPORTED;
327 }
328
329 EFI_STATUS
EfiLibAddUnicodeString(IN CHAR8 * Language,IN CHAR8 * SupportedLanguages,IN OUT EFI_UNICODE_STRING_TABLE ** UnicodeStringTable,IN CHAR16 * UnicodeString)330 EfiLibAddUnicodeString (
331 IN CHAR8 *Language,
332 IN CHAR8 *SupportedLanguages,
333 IN OUT EFI_UNICODE_STRING_TABLE **UnicodeStringTable,
334 IN CHAR16 *UnicodeString
335 )
336 /*++
337
338 Routine Description:
339
340 Add an translation to the dictionary if this language if supported.
341
342 Arguments:
343
344 Language - The name of language to translate to
345 SupportedLanguages - Supported languages set
346 UnicodeStringTable - Translation dictionary
347 UnicodeString - The corresponding string for the language to be translated to
348
349 Returns:
350
351 EFI_INVALID_PARAMETER - Invalid parameter
352 EFI_UNSUPPORTED - System not supported this language
353 EFI_ALREADY_STARTED - Already has a translation item of this language
354 EFI_OUT_OF_RESOURCES - No enough buffer to be allocated
355 EFI_SUCCESS - String successfully translated
356
357 --*/
358 {
359 UINTN NumberOfEntries;
360 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;
361 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;
362 UINTN UnicodeStringLength;
363
364 //
365 // Make sure the parameter are valid
366 //
367 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {
368 return EFI_INVALID_PARAMETER;
369 }
370
371 //
372 // If there are no supported languages, then a Unicode String can not be added
373 //
374 if (SupportedLanguages == NULL) {
375 return EFI_UNSUPPORTED;
376 }
377
378 //
379 // If the Unicode String is empty, then a Unicode String can not be added
380 //
381 if (UnicodeString[0] == 0) {
382 return EFI_INVALID_PARAMETER;
383 }
384
385 //
386 // Make sure Language is a member of SupportedLanguages
387 //
388 while (*SupportedLanguages != 0) {
389 if (EfiLibCompareLanguage (Language, SupportedLanguages)) {
390
391 //
392 // Determine the size of the Unicode String Table by looking for a NULL Language entry
393 //
394 NumberOfEntries = 0;
395 if (*UnicodeStringTable != NULL) {
396 OldUnicodeStringTable = *UnicodeStringTable;
397 while (OldUnicodeStringTable->Language != NULL) {
398 if (EfiLibCompareLanguage (Language, OldUnicodeStringTable->Language)) {
399 return EFI_ALREADY_STARTED;
400 }
401
402 OldUnicodeStringTable++;
403 NumberOfEntries++;
404 }
405 }
406
407 //
408 // Allocate space for a new Unicode String Table. It must hold the current number of
409 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
410 // marker
411 //
412 NewUnicodeStringTable = EfiLibAllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));
413 if (NewUnicodeStringTable == NULL) {
414 return EFI_OUT_OF_RESOURCES;
415 }
416
417 //
418 // If the current Unicode String Table contains any entries, then copy them to the
419 // newly allocated Unicode String Table.
420 //
421 if (*UnicodeStringTable != NULL) {
422 EfiCopyMem (
423 NewUnicodeStringTable,
424 *UnicodeStringTable,
425 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)
426 );
427 }
428
429 //
430 // Allocate space for a copy of the Language specifier
431 //
432 NewUnicodeStringTable[NumberOfEntries].Language = EfiLibAllocateCopyPool (EfiAsciiStrSize (Language), Language);
433 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {
434 gBS->FreePool (NewUnicodeStringTable);
435 return EFI_OUT_OF_RESOURCES;
436 }
437
438 //
439 // Compute the length of the Unicode String
440 //
441 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++)
442 ;
443
444 //
445 // Allocate space for a copy of the Unicode String
446 //
447 NewUnicodeStringTable[NumberOfEntries].UnicodeString = EfiLibAllocateCopyPool (
448 (UnicodeStringLength + 1) * sizeof (CHAR16),
449 UnicodeString
450 );
451 if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {
452 gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);
453 gBS->FreePool (NewUnicodeStringTable);
454 return EFI_OUT_OF_RESOURCES;
455 }
456
457 //
458 // Mark the end of the Unicode String Table
459 //
460 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;
461 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;
462
463 //
464 // Free the old Unicode String Table
465 //
466 if (*UnicodeStringTable != NULL) {
467 gBS->FreePool (*UnicodeStringTable);
468 }
469
470 //
471 // Point UnicodeStringTable at the newly allocated Unicode String Table
472 //
473 *UnicodeStringTable = NewUnicodeStringTable;
474
475 return EFI_SUCCESS;
476 }
477
478 SupportedLanguages = NextSupportedLanguage (SupportedLanguages);
479 }
480
481 return EFI_UNSUPPORTED;
482 }
483
484 EFI_STATUS
EfiLibFreeUnicodeStringTable(IN OUT EFI_UNICODE_STRING_TABLE * UnicodeStringTable)485 EfiLibFreeUnicodeStringTable (
486 IN OUT EFI_UNICODE_STRING_TABLE *UnicodeStringTable
487 )
488 /*++
489
490 Routine Description:
491
492 Free a string table.
493
494 Arguments:
495
496 UnicodeStringTable - The string table to be freed.
497
498 Returns:
499
500 EFI_SUCCESS - The table successfully freed.
501
502 --*/
503 {
504 UINTN Index;
505
506 //
507 // If the Unicode String Table is NULL, then it is already freed
508 //
509 if (UnicodeStringTable == NULL) {
510 return EFI_SUCCESS;
511 }
512
513 //
514 // Loop through the Unicode String Table until we reach the end of table marker
515 //
516 for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) {
517
518 //
519 // Free the Language string from the Unicode String Table
520 //
521 gBS->FreePool (UnicodeStringTable[Index].Language);
522
523 //
524 // Free the Unicode String from the Unicode String Table
525 //
526 if (UnicodeStringTable[Index].UnicodeString != NULL) {
527 gBS->FreePool (UnicodeStringTable[Index].UnicodeString);
528 }
529 }
530
531 //
532 // Free the Unicode String Table itself
533 //
534 gBS->FreePool (UnicodeStringTable);
535
536 return EFI_SUCCESS;
537 }
538