]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/UefiLib/UefiLib.c
Removed MdePkg usage of ModuleName: in file headers
[mirror_edk2.git] / MdePkg / Library / UefiLib / UefiLib.c
CommitLineData
e386b444 1/** @file\r
2 Mde UEFI library functions.\r
3\r
4 Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
e386b444 13**/\r
14\r
15//\r
16// Include common header file for this module.\r
17//\r
f734a10a 18#include "UefiLibInternal.h"\r
e386b444 19\r
20/**\r
21 Compare whether two names of languages are identical.\r
22\r
23 @param Language1 Name of language 1.\r
24 @param Language2 Name of language 2.\r
25\r
26 @retval TRUE Language 1 and language 2 are the same.\r
27 @retval FALSE Language 1 and language 2 are not the same.\r
28\r
29**/\r
30STATIC\r
31BOOLEAN\r
32CompareIso639LanguageCode (\r
33 IN CONST CHAR8 *Language1,\r
34 IN CONST CHAR8 *Language2\r
35 )\r
36{\r
37 UINT32 Name1;\r
38 UINT32 Name2;\r
39\r
40 Name1 = ReadUnaligned24 ((CONST UINT32 *) Language1);\r
41 Name2 = ReadUnaligned24 ((CONST UINT32 *) Language2);\r
42\r
43 return (BOOLEAN) (Name1 == Name2);\r
44}\r
45\r
46/**\r
47 This function searches the list of configuration tables stored in the EFI System\r
48 Table for a table with a GUID that matches TableGuid. If a match is found,\r
49 then a pointer to the configuration table is returned in Table, and EFI_SUCCESS\r
50 is returned. If a matching GUID is not found, then EFI_NOT_FOUND is returned.\r
51\r
52 @param TableGuid Pointer to table's GUID type..\r
53 @param Table Pointer to the table associated with TableGuid in the EFI System Table.\r
54\r
55 @retval EFI_SUCCESS A configuration table matching TableGuid was found.\r
56 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.\r
57\r
58**/\r
59EFI_STATUS\r
60EFIAPI\r
61EfiGetSystemConfigurationTable (\r
62 IN EFI_GUID *TableGuid,\r
63 OUT VOID **Table\r
64 )\r
65{\r
66 EFI_SYSTEM_TABLE *SystemTable;\r
67 UINTN Index;\r
68\r
69 ASSERT (TableGuid != NULL);\r
70 ASSERT (Table != NULL);\r
71\r
72 SystemTable = gST;\r
73 *Table = NULL;\r
74 for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {\r
75 if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) {\r
76 *Table = SystemTable->ConfigurationTable[Index].VendorTable;\r
77 return EFI_SUCCESS;\r
78 }\r
79 }\r
80\r
81 return EFI_NOT_FOUND;\r
82}\r
83\r
84/**\r
85 This function causes the notification function to be executed for every protocol\r
86 of type ProtocolGuid instance that exists in the system when this function is\r
87 invoked. In addition, every time a protocol of type ProtocolGuid instance is\r
88 installed or reinstalled, the notification function is also executed.\r
89\r
90 @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.\r
91 @param NotifyTpl Supplies the task priority level of the event notifications.\r
92 @param NotifyFunction Supplies the function to notify when the event is signaled.\r
93 @param NotifyContext The context parameter to pass to NotifyFunction.\r
94 @param Registration A pointer to a memory location to receive the registration value.\r
95\r
96 @return The notification event that was created.\r
97\r
98**/\r
99EFI_EVENT\r
100EFIAPI\r
101EfiCreateProtocolNotifyEvent(\r
102 IN EFI_GUID *ProtocolGuid,\r
103 IN EFI_TPL NotifyTpl,\r
104 IN EFI_EVENT_NOTIFY NotifyFunction,\r
105 IN VOID *NotifyContext, OPTIONAL\r
106 OUT VOID **Registration\r
107 )\r
108{\r
109 EFI_STATUS Status;\r
110 EFI_EVENT Event;\r
111\r
112 //\r
113 // Create the event\r
114 //\r
115\r
116 Status = gBS->CreateEvent (\r
117 EVT_NOTIFY_SIGNAL,\r
118 NotifyTpl,\r
119 NotifyFunction,\r
120 NotifyContext,\r
121 &Event\r
122 );\r
123 ASSERT_EFI_ERROR (Status);\r
124\r
125 //\r
126 // Register for protocol notifactions on this event\r
127 //\r
128\r
129 Status = gBS->RegisterProtocolNotify (\r
130 ProtocolGuid,\r
131 Event,\r
132 Registration\r
133 );\r
134\r
135 ASSERT_EFI_ERROR (Status);\r
136\r
137 //\r
138 // Kick the event so we will perform an initial pass of\r
139 // current installed drivers\r
140 //\r
141\r
142 gBS->SignalEvent (Event);\r
143 return Event;\r
144}\r
145\r
146/**\r
147 This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.\r
148 This event is signaled with EfiNamedEventSignal(). This provide the ability for\r
149 one or more listeners on the same event named by the GUID specified by Name.\r
150\r
151 @param Name Supplies GUID name of the event.\r
152 @param NotifyTpl Supplies the task priority level of the event notifications.\r
153 @param NotifyFunction Supplies the function to notify when the event is signaled.\r
154 @param NotifyContext The context parameter to pass to NotifyFunction.\r
155 @param Registration A pointer to a memory location to receive the registration value.\r
156\r
157 @retval EFI_SUCCESS A named event was created.\r
158 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.\r
159\r
160**/\r
161EFI_STATUS\r
162EFIAPI\r
163EfiNamedEventListen (\r
164 IN CONST EFI_GUID *Name,\r
165 IN EFI_TPL NotifyTpl,\r
166 IN EFI_EVENT_NOTIFY NotifyFunction,\r
167 IN CONST VOID *NotifyContext, OPTIONAL\r
168 OUT VOID *Registration OPTIONAL\r
169 )\r
170{\r
171 EFI_STATUS Status;\r
172 EFI_EVENT Event;\r
173 VOID *RegistrationLocal;\r
174\r
175 //\r
176 // Create event\r
177 //\r
178 Status = gBS->CreateEvent (\r
179 EVT_NOTIFY_SIGNAL,\r
180 NotifyTpl,\r
181 NotifyFunction,\r
182 (VOID *) NotifyContext,\r
183 &Event\r
184 );\r
185 ASSERT_EFI_ERROR (Status);\r
186\r
187 //\r
188 // The Registration is not optional to RegisterProtocolNotify().\r
189 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.\r
190 //\r
191 if (Registration != NULL) {\r
192 RegistrationLocal = Registration;\r
193 } else {\r
194 RegistrationLocal = &RegistrationLocal;\r
195 }\r
196\r
197 //\r
198 // Register for an installation of protocol interface\r
199 //\r
200\r
201 Status = gBS->RegisterProtocolNotify (\r
202 (EFI_GUID *) Name,\r
203 Event,\r
204 RegistrationLocal\r
205 );\r
206 ASSERT_EFI_ERROR (Status);\r
207\r
208 return EFI_SUCCESS;\r
209}\r
210\r
211/**\r
212 This function signals the named event specified by Name. The named event must\r
213 have been created with EfiNamedEventListen().\r
214\r
215 @param Name Supplies GUID name of the event.\r
216\r
217 @retval EFI_SUCCESS A named event was signaled.\r
218 @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event.\r
219\r
220**/\r
221EFI_STATUS\r
222EFIAPI\r
223EfiNamedEventSignal (\r
224 IN CONST EFI_GUID *Name\r
225 )\r
226{\r
227 EFI_STATUS Status;\r
228 EFI_HANDLE Handle;\r
229\r
230 Handle = NULL;\r
231 Status = gBS->InstallProtocolInterface (\r
232 &Handle,\r
233 (EFI_GUID *) Name,\r
234 EFI_NATIVE_INTERFACE,\r
235 NULL\r
236 );\r
237 ASSERT_EFI_ERROR (Status);\r
238\r
239 Status = gBS->UninstallProtocolInterface (\r
240 Handle,\r
241 (EFI_GUID *) Name,\r
242 NULL\r
243 );\r
244 ASSERT_EFI_ERROR (Status);\r
245\r
246 return EFI_SUCCESS;\r
247}\r
248\r
249/**\r
250 Returns the current TPL.\r
251\r
252 This function returns the current TPL. There is no EFI service to directly\r
253 retrieve the current TPL. Instead, the RaiseTPL() function is used to raise\r
254 the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level\r
255 can then immediately be restored back to the current TPL level with a call\r
256 to RestoreTPL().\r
257\r
258 @param VOID\r
259\r
260 @retvale EFI_TPL The current TPL.\r
261\r
262**/\r
263EFI_TPL\r
264EFIAPI\r
265EfiGetCurrentTpl (\r
266 VOID\r
267 )\r
268{\r
269 EFI_TPL Tpl;\r
270\r
271 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
272 gBS->RestoreTPL (Tpl);\r
273\r
274 return Tpl;\r
275}\r
276\r
277\r
278/**\r
279 This function initializes a basic mutual exclusion lock to the released state\r
280 and returns the lock. Each lock provides mutual exclusion access at its task\r
281 priority level. Since there is no preemption or multiprocessor support in EFI,\r
282 acquiring the lock only consists of raising to the locks TPL.\r
283\r
284 @param Lock A pointer to the lock data structure to initialize.\r
285 @param Priority EFI TPL associated with the lock.\r
286\r
287 @return The lock.\r
288\r
289**/\r
290EFI_LOCK *\r
291EFIAPI\r
292EfiInitializeLock (\r
293 IN OUT EFI_LOCK *Lock,\r
294 IN EFI_TPL Priority\r
295 )\r
296{\r
297 ASSERT (Lock != NULL);\r
298 ASSERT (Priority <= TPL_HIGH_LEVEL);\r
299\r
300 Lock->Tpl = Priority;\r
301 Lock->OwnerTpl = TPL_APPLICATION;\r
302 Lock->Lock = EfiLockReleased ;\r
303 return Lock;\r
304}\r
305\r
306/**\r
307 This function raises the system's current task priority level to the task\r
308 priority level of the mutual exclusion lock. Then, it places the lock in the\r
309 acquired state.\r
310\r
311 @param Priority The task priority level of the lock.\r
312\r
313**/\r
314VOID\r
315EFIAPI\r
316EfiAcquireLock (\r
317 IN EFI_LOCK *Lock\r
318 )\r
319{\r
320 ASSERT (Lock != NULL);\r
321 ASSERT (Lock->Lock == EfiLockReleased);\r
322\r
323 Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);\r
324 Lock->Lock = EfiLockAcquired;\r
325}\r
326\r
327/**\r
328 This function raises the system's current task priority level to the task\r
329 priority level of the mutual exclusion lock. Then, it attempts to place the\r
330 lock in the acquired state.\r
331\r
332 @param Lock A pointer to the lock to acquire.\r
333\r
334 @retval EFI_SUCCESS The lock was acquired.\r
335 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.\r
336\r
337**/\r
338EFI_STATUS\r
339EFIAPI\r
340EfiAcquireLockOrFail (\r
341 IN EFI_LOCK *Lock\r
342 )\r
343{\r
344\r
345 ASSERT (Lock != NULL);\r
346 ASSERT (Lock->Lock != EfiLockUninitialized);\r
347\r
348 if (Lock->Lock == EfiLockAcquired) {\r
349 //\r
350 // Lock is already owned, so bail out\r
351 //\r
352 return EFI_ACCESS_DENIED;\r
353 }\r
354\r
355 Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);\r
356\r
357 Lock->Lock = EfiLockAcquired;\r
358\r
359 return EFI_SUCCESS;\r
360}\r
361\r
362/**\r
363 This function transitions a mutual exclusion lock from the acquired state to\r
364 the released state, and restores the system's task priority level to its\r
365 previous level.\r
366\r
367 @param Lock A pointer to the lock to release.\r
368\r
369**/\r
370VOID\r
371EFIAPI\r
372EfiReleaseLock (\r
373 IN EFI_LOCK *Lock\r
374 )\r
375{\r
376 EFI_TPL Tpl;\r
377\r
378 ASSERT (Lock != NULL);\r
379 ASSERT (Lock->Lock == EfiLockAcquired);\r
380\r
381 Tpl = Lock->OwnerTpl;\r
382\r
383 Lock->Lock = EfiLockReleased;\r
384\r
385 gBS->RestoreTPL (Tpl);\r
386}\r
387\r
388/**\r
389 Tests whether a controller handle is being managed by a specific driver.\r
390\r
391 This function tests whether the driver specified by DriverBindingHandle is\r
392 currently managing the controller specified by ControllerHandle. This test\r
393 is performed by evaluating if the the protocol specified by ProtocolGuid is\r
394 present on ControllerHandle and is was opened by DriverBindingHandle with an\r
395 attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.\r
396 If ProtocolGuid is NULL, then ASSERT().\r
397\r
398 @param ControllerHandle A handle for a controller to test.\r
399 @param DriverBindingHandle Specifies the driver binding handle for the\r
400 driver.\r
401 @param ProtocolGuid Specifies the protocol that the driver specified\r
402 by DriverBindingHandle opens in its Start()\r
403 function.\r
404\r
405 @retval EFI_SUCCESS ControllerHandle is managed by the driver\r
406 specifed by DriverBindingHandle.\r
407 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver\r
408 specifed by DriverBindingHandle.\r
409\r
410**/\r
411EFI_STATUS\r
412EFIAPI\r
413EfiTestManagedDevice (\r
414 IN CONST EFI_HANDLE ControllerHandle,\r
415 IN CONST EFI_HANDLE DriverBindingHandle,\r
416 IN CONST EFI_GUID *ProtocolGuid\r
417 )\r
418{\r
419 EFI_STATUS Status;\r
420 VOID *ManagedInterface;\r
421\r
422 ASSERT (ProtocolGuid != NULL);\r
423\r
424 Status = gBS->OpenProtocol (\r
425 ControllerHandle,\r
426 (EFI_GUID *) ProtocolGuid,\r
427 &ManagedInterface,\r
428 DriverBindingHandle,\r
429 ControllerHandle,\r
430 EFI_OPEN_PROTOCOL_BY_DRIVER\r
431 );\r
432 if (!EFI_ERROR (Status)) {\r
433 gBS->CloseProtocol (\r
434 ControllerHandle,\r
435 (EFI_GUID *) ProtocolGuid,\r
436 DriverBindingHandle,\r
437 ControllerHandle\r
438 );\r
439 return EFI_UNSUPPORTED;\r
440 }\r
441\r
442 if (Status != EFI_ALREADY_STARTED) {\r
443 return EFI_UNSUPPORTED;\r
444 }\r
445\r
446 return EFI_SUCCESS;\r
447}\r
448\r
449/**\r
450 Tests whether a child handle is a child device of the controller.\r
451\r
452 This function tests whether ChildHandle is one of the children of\r
453 ControllerHandle. This test is performed by checking to see if the protocol\r
454 specified by ProtocolGuid is present on ControllerHandle and opened by\r
455 ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
456 If ProtocolGuid is NULL, then ASSERT().\r
457\r
458 @param ControllerHandle A handle for a (parent) controller to test.\r
459 @param ChildHandle A child handle to test.\r
460 @param ConsumsedGuid Supplies the protocol that the child controller\r
461 opens on its parent controller.\r
462\r
463 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.\r
464 @retval EFI_UNSUPPORTED ChildHandle is not a child of the\r
465 ControllerHandle.\r
466\r
467**/\r
468EFI_STATUS\r
469EFIAPI\r
470EfiTestChildHandle (\r
471 IN CONST EFI_HANDLE ControllerHandle,\r
472 IN CONST EFI_HANDLE ChildHandle,\r
473 IN CONST EFI_GUID *ProtocolGuid\r
474 )\r
475{\r
476 EFI_STATUS Status;\r
477 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
478 UINTN EntryCount;\r
479 UINTN Index;\r
480\r
481 ASSERT (ProtocolGuid != NULL);\r
482\r
483 //\r
484 // Retrieve the list of agents that are consuming the specific protocol\r
485 // on ControllerHandle.\r
486 //\r
487 Status = gBS->OpenProtocolInformation (\r
488 ControllerHandle,\r
489 (EFI_GUID *) ProtocolGuid,\r
490 &OpenInfoBuffer,\r
491 &EntryCount\r
492 );\r
493 if (EFI_ERROR (Status)) {\r
494 return EFI_UNSUPPORTED;\r
495 }\r
496\r
497 //\r
498 // Inspect if ChildHandle is one of the agents.\r
499 //\r
500 Status = EFI_UNSUPPORTED;\r
501 for (Index = 0; Index < EntryCount; Index++) {\r
502 if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&\r
503 (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
504 Status = EFI_SUCCESS;\r
505 break;\r
506 }\r
507 }\r
508\r
509 FreePool (OpenInfoBuffer);\r
510 return Status;\r
511}\r
512\r
513/**\r
dd51a993 514 This function looks up a Unicode string in UnicodeStringTable.\r
515 If Language is a member of SupportedLanguages and a Unicode\r
516 string is found in UnicodeStringTable that matches the\r
517 language code specified by Language, then it is returned in\r
e386b444 518 UnicodeString.\r
519\r
dd51a993 520 @param Language A pointer to the ISO 639-2\r
521 language code for the Unicode\r
522 string to look up and return.\r
523 \r
524 @param SupportedLanguages A pointer to the set of ISO\r
525 639-2language\r
526 codes that the Unicode string\r
527 table supports. Language must\r
528 be a member of this set.\r
529 \r
530 @param UnicodeStringTable A pointer to the table of\r
531 Unicode strings.\r
532 \r
533 @param UnicodeString A pointer to the Unicode\r
534 string from UnicodeStringTable\r
535 that matches the language\r
536 specified by Language.\r
537\r
538 @retval EFI_SUCCESS The Unicode string that\r
539 matches the language specified\r
540 by Language was found in the\r
541 table of Unicoide strings\r
542 UnicodeStringTable, and it was\r
543 returned in UnicodeString.\r
544 \r
e386b444 545 @retval EFI_INVALID_PARAMETER Language is NULL.\r
dd51a993 546 \r
e386b444 547 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
548 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
dd51a993 549 \r
e386b444 550 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.\r
dd51a993 551 \r
552 @retval EFI_UNSUPPORTED The language specified by\r
553 Language is not a member\r
554 ofSupportedLanguages.\r
555 \r
556 @retval EFI_UNSUPPORTED The language specified by\r
557 Language is not supported by\r
558 UnicodeStringTable.\r
e386b444 559\r
560**/\r
561EFI_STATUS\r
562EFIAPI\r
563LookupUnicodeString (\r
564 IN CONST CHAR8 *Language,\r
565 IN CONST CHAR8 *SupportedLanguages,\r
566 IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable,\r
567 OUT CHAR16 **UnicodeString\r
568 )\r
569{\r
570 //\r
571 // Make sure the parameters are valid\r
572 //\r
573 if (Language == NULL || UnicodeString == NULL) {\r
574 return EFI_INVALID_PARAMETER;\r
575 }\r
576\r
577 //\r
578 // If there are no supported languages, or the Unicode String Table is empty, then the\r
579 // Unicode String specified by Language is not supported by this Unicode String Table\r
580 //\r
581 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {\r
582 return EFI_UNSUPPORTED;\r
583 }\r
584\r
585 //\r
586 // Make sure Language is in the set of Supported Languages\r
587 //\r
588 while (*SupportedLanguages != 0) {\r
589 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
590\r
591 //\r
592 // Search the Unicode String Table for the matching Language specifier\r
593 //\r
594 while (UnicodeStringTable->Language != NULL) {\r
595 if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) {\r
596\r
597 //\r
598 // A matching string was found, so return it\r
599 //\r
600 *UnicodeString = UnicodeStringTable->UnicodeString;\r
601 return EFI_SUCCESS;\r
602 }\r
603\r
604 UnicodeStringTable++;\r
605 }\r
606\r
607 return EFI_UNSUPPORTED;\r
608 }\r
609\r
610 SupportedLanguages += 3;\r
611 }\r
612\r
613 return EFI_UNSUPPORTED;\r
614}\r
615\r
dd51a993 616\r
617\r
e386b444 618/**\r
dd51a993 619 This function looks up a Unicode string in UnicodeStringTable.\r
620 If Language is a member of SupportedLanguages and a Unicode\r
621 string is found in UnicodeStringTable that matches the\r
622 language code specified by Language, then it is returned in\r
623 UnicodeString.\r
624\r
625 @param Language A pointer to the ISO 639-2 or\r
626 RFC 3066 language code for the\r
627 Unicode string to look up and\r
628 return.\r
629 \r
630 @param SupportedLanguages A pointer to the set of ISO\r
631 639-2 or RFC 3066 language\r
632 codes that the Unicode string\r
633 table supports. Language must\r
634 be a member of this set.\r
635 \r
636 @param UnicodeStringTable A pointer to the table of\r
637 Unicode strings.\r
638 \r
639 @param UnicodeString A pointer to the Unicode\r
640 string from UnicodeStringTable\r
641 that matches the language\r
642 specified by Language.\r
643\r
644 @param Iso639Language Specify the language code\r
645 format supported. If true,\r
646 then the format follow ISO\r
647 639-2. If false, then it\r
648 follows RFC3066.\r
649\r
650 @retval EFI_SUCCESS The Unicode string that\r
651 matches the language specified\r
652 by Language was found in the\r
653 table of Unicoide strings\r
654 UnicodeStringTable, and it was\r
655 returned in UnicodeString.\r
656 \r
657 @retval EFI_INVALID_PARAMETER Language is NULL.\r
658 \r
659 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
660 \r
661 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
662 \r
663 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.\r
664 \r
665 @retval EFI_UNSUPPORTED The language specified by\r
666 Language is not a member\r
667 ofSupportedLanguages.\r
668 \r
669 @retval EFI_UNSUPPORTED The language specified by\r
670 Language is not supported by\r
671 UnicodeStringTable.\r
672\r
673**/\r
674EFI_STATUS\r
675EFIAPI\r
676LookupUnicodeString2 (\r
677 IN CONST CHAR8 *Language,\r
678 IN CONST CHAR8 *SupportedLanguages,\r
679 IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable,\r
680 OUT CHAR16 **UnicodeString,\r
681 IN BOOLEAN Iso639Language\r
682 )\r
683{\r
684 BOOLEAN Found;\r
685 UINTN Index;\r
686 CHAR8 *LanguageString;\r
687\r
688 //\r
689 // Make sure the parameters are valid\r
690 //\r
691 if (Language == NULL || UnicodeString == NULL) {\r
692 return EFI_INVALID_PARAMETER;\r
693 }\r
694\r
695 //\r
696 // If there are no supported languages, or the Unicode String Table is empty, then the\r
697 // Unicode String specified by Language is not supported by this Unicode String Table\r
698 //\r
699 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {\r
700 return EFI_UNSUPPORTED;\r
701 }\r
702\r
703 //\r
704 // Make sure Language is in the set of Supported Languages\r
705 //\r
706 Found = FALSE;\r
707 while (*SupportedLanguages != 0) {\r
708 if (Iso639Language) {\r
709 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
710 Found = TRUE;\r
711 break;\r
712 }\r
713 SupportedLanguages += 3;\r
714 } else {\r
715 for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);\r
716 if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {\r
717 Found = TRUE;\r
718 break;\r
719 }\r
720 SupportedLanguages += Index;\r
721 for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);\r
722 }\r
723 }\r
724\r
725 //\r
726 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED\r
727 //\r
728 if (!Found) {\r
729 return EFI_UNSUPPORTED;\r
730 }\r
731\r
732 //\r
733 // Search the Unicode String Table for the matching Language specifier\r
734 //\r
735 while (UnicodeStringTable->Language != NULL) {\r
736 LanguageString = UnicodeStringTable->Language;\r
737 while (0 != *LanguageString) {\r
738 for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);\r
739 if (AsciiStrnCmp(LanguageString, Language, Index) == 0) {\r
740 *UnicodeString = UnicodeStringTable->UnicodeString;\r
741 return EFI_SUCCESS;\r
742 }\r
743 LanguageString += Index;\r
744 for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] == ';'; Index++);\r
745 }\r
746 UnicodeStringTable++;\r
747 }\r
748\r
749 return EFI_UNSUPPORTED;\r
750}\r
751\r
752\r
753/**\r
754 \r
e386b444 755 This function adds a Unicode string to UnicodeStringTable.\r
dd51a993 756 If Language is a member of SupportedLanguages then\r
757 UnicodeString is added to UnicodeStringTable. New buffers are\r
758 allocated for both Language and UnicodeString. The contents\r
759 of Language and UnicodeString are copied into these new\r
760 buffers. These buffers are automatically freed when\r
e386b444 761 FreeUnicodeStringTable() is called.\r
762\r
dd51a993 763 @param Language A pointer to the ISO 639-2\r
764 language code for the Unicode\r
e386b444 765 string to add.\r
dd51a993 766 \r
767 @param SupportedLanguages A pointer to the set of ISO\r
768 639-2 language codes that the\r
769 Unicode string table supports.\r
770 Language must be a member of\r
771 this set.\r
772 \r
773 @param UnicodeStringTable A pointer to the table of\r
774 Unicode strings.\r
775 \r
776 @param UnicodeString A pointer to the Unicode\r
777 string to add.\r
778\r
779 @retval EFI_SUCCESS The Unicode string that\r
780 matches the language specified\r
781 by Language was found in the\r
782 table of Unicode strings\r
783 UnicodeStringTable, and it was\r
e386b444 784 returned in UnicodeString.\r
dd51a993 785 \r
e386b444 786 @retval EFI_INVALID_PARAMETER Language is NULL.\r
dd51a993 787 \r
e386b444 788 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
dd51a993 789 \r
e386b444 790 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.\r
dd51a993 791 \r
e386b444 792 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
dd51a993 793 \r
794 @retval EFI_ALREADY_STARTED A Unicode string with language\r
795 Language is already present in\r
796 UnicodeStringTable.\r
797 \r
798 @retval EFI_OUT_OF_RESOURCES There is not enough memory to\r
799 add another Unicode string to\r
800 UnicodeStringTable.\r
801 \r
802 @retval EFI_UNSUPPORTED The language specified by\r
803 Language is not a member of\r
804 SupportedLanguages.\r
e386b444 805\r
806**/\r
807EFI_STATUS\r
808EFIAPI\r
809AddUnicodeString (\r
810 IN CONST CHAR8 *Language,\r
811 IN CONST CHAR8 *SupportedLanguages,\r
812 IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable,\r
813 IN CONST CHAR16 *UnicodeString\r
814 )\r
815{\r
816 UINTN NumberOfEntries;\r
817 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;\r
818 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;\r
819 UINTN UnicodeStringLength;\r
820\r
821 //\r
822 // Make sure the parameter are valid\r
823 //\r
824 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {\r
825 return EFI_INVALID_PARAMETER;\r
826 }\r
827\r
828 //\r
829 // If there are no supported languages, then a Unicode String can not be added\r
830 //\r
831 if (SupportedLanguages == NULL) {\r
832 return EFI_UNSUPPORTED;\r
833 }\r
834\r
835 //\r
836 // If the Unicode String is empty, then a Unicode String can not be added\r
837 //\r
838 if (UnicodeString[0] == 0) {\r
839 return EFI_INVALID_PARAMETER;\r
840 }\r
841\r
842 //\r
843 // Make sure Language is a member of SupportedLanguages\r
844 //\r
845 while (*SupportedLanguages != 0) {\r
846 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
847\r
848 //\r
849 // Determine the size of the Unicode String Table by looking for a NULL Language entry\r
850 //\r
851 NumberOfEntries = 0;\r
852 if (*UnicodeStringTable != NULL) {\r
853 OldUnicodeStringTable = *UnicodeStringTable;\r
854 while (OldUnicodeStringTable->Language != NULL) {\r
855 if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) {\r
856 return EFI_ALREADY_STARTED;\r
857 }\r
858\r
859 OldUnicodeStringTable++;\r
860 NumberOfEntries++;\r
861 }\r
862 }\r
863\r
864 //\r
865 // Allocate space for a new Unicode String Table. It must hold the current number of\r
866 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table\r
867 // marker\r
868 //\r
869 NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));\r
870 if (NewUnicodeStringTable == NULL) {\r
871 return EFI_OUT_OF_RESOURCES;\r
872 }\r
873\r
874 //\r
875 // If the current Unicode String Table contains any entries, then copy them to the\r
876 // newly allocated Unicode String Table.\r
877 //\r
878 if (*UnicodeStringTable != NULL) {\r
879 CopyMem (\r
880 NewUnicodeStringTable,\r
881 *UnicodeStringTable,\r
882 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)\r
883 );\r
884 }\r
885\r
886 //\r
887 // Allocate space for a copy of the Language specifier\r
888 //\r
889 NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language);\r
890 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {\r
891 gBS->FreePool (NewUnicodeStringTable);\r
892 return EFI_OUT_OF_RESOURCES;\r
893 }\r
894\r
895 //\r
896 // Compute the length of the Unicode String\r
897 //\r
898 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++)\r
899 ;\r
900\r
901 //\r
902 // Allocate space for a copy of the Unicode String\r
903 //\r
904 NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (\r
905 (UnicodeStringLength + 1) * sizeof (CHAR16),\r
906 UnicodeString\r
907 );\r
908 if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {\r
909 gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);\r
910 gBS->FreePool (NewUnicodeStringTable);\r
911 return EFI_OUT_OF_RESOURCES;\r
912 }\r
913\r
914 //\r
915 // Mark the end of the Unicode String Table\r
916 //\r
917 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;\r
918 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;\r
919\r
920 //\r
921 // Free the old Unicode String Table\r
922 //\r
923 if (*UnicodeStringTable != NULL) {\r
924 gBS->FreePool (*UnicodeStringTable);\r
925 }\r
926\r
927 //\r
928 // Point UnicodeStringTable at the newly allocated Unicode String Table\r
929 //\r
930 *UnicodeStringTable = NewUnicodeStringTable;\r
931\r
932 return EFI_SUCCESS;\r
933 }\r
934\r
935 SupportedLanguages += 3;\r
936 }\r
937\r
938 return EFI_UNSUPPORTED;\r
939}\r
940\r
dd51a993 941\r
942/**\r
943 \r
944 This function adds a Unicode string to UnicodeStringTable.\r
945 If Language is a member of SupportedLanguages then\r
946 UnicodeString is added to UnicodeStringTable. New buffers are\r
947 allocated for both Language and UnicodeString. The contents\r
948 of Language and UnicodeString are copied into these new\r
949 buffers. These buffers are automatically freed when\r
950 FreeUnicodeStringTable() is called.\r
951\r
952 @param Language A pointer to the ISO 639-2 or\r
953 RFC 3066 language code for the\r
954 Unicode string to add.\r
955 \r
956 @param SupportedLanguages A pointer to the set of ISO\r
957 639-2 or RFC 3.66 language\r
958 codes that the Unicode string\r
959 table supports. Language must\r
960 be a member of this set.\r
961 \r
962 @param UnicodeStringTable A pointer to the table of\r
963 Unicode strings.\r
964 \r
965 @param UnicodeString A pointer to the Unicode\r
966 string to add.\r
967 \r
968 @param Iso639Language Specify the language code\r
969 format supported. If true,\r
970 then the format follow ISO\r
971 639-2. If false, then it\r
972 follows RFC3066.\r
973\r
974 @retval EFI_SUCCESS The Unicode string that\r
975 matches the language specified\r
976 by Language was found in the\r
977 table of Unicode strings\r
978 UnicodeStringTable, and it was\r
979 returned in UnicodeString.\r
980 \r
981 @retval EFI_INVALID_PARAMETER Language is NULL.\r
982 \r
983 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
984 \r
985 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.\r
986 \r
987 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
988 \r
989 @retval EFI_ALREADY_STARTED A Unicode string with language\r
990 Language is already present in\r
991 UnicodeStringTable.\r
992 \r
993 @retval EFI_OUT_OF_RESOURCES There is not enough memory to\r
994 add another Unicode string to\r
995 UnicodeStringTable.\r
996 \r
997 @retval EFI_UNSUPPORTED The language specified by\r
998 Language is not a member of\r
999 SupportedLanguages.\r
1000\r
1001**/\r
1002EFI_STATUS\r
1003EFIAPI\r
1004AddUnicodeString2 (\r
1005 IN CONST CHAR8 *Language,\r
1006 IN CONST CHAR8 *SupportedLanguages,\r
1007 IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable,\r
1008 IN CONST CHAR16 *UnicodeString,\r
1009 IN BOOLEAN Iso639Language\r
1010 )\r
1011{\r
1012 UINTN NumberOfEntries;\r
1013 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;\r
1014 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;\r
1015 UINTN UnicodeStringLength;\r
1016 BOOLEAN Found;\r
1017 UINTN Index;\r
1018 CHAR8 *LanguageString;\r
1019\r
1020 //\r
1021 // Make sure the parameter are valid\r
1022 //\r
1023 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {\r
1024 return EFI_INVALID_PARAMETER;\r
1025 }\r
1026\r
1027 //\r
1028 // If there are no supported languages, then a Unicode String can not be added\r
1029 //\r
1030 if (SupportedLanguages == NULL) {\r
1031 return EFI_UNSUPPORTED;\r
1032 }\r
1033\r
1034 //\r
1035 // If the Unicode String is empty, then a Unicode String can not be added\r
1036 //\r
1037 if (UnicodeString[0] == 0) {\r
1038 return EFI_INVALID_PARAMETER;\r
1039 }\r
1040\r
1041 //\r
1042 // Make sure Language is a member of SupportedLanguages\r
1043 //\r
1044 Found = FALSE;\r
1045 while (*SupportedLanguages != 0) {\r
1046 if (Iso639Language) {\r
1047 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
1048 Found = TRUE;\r
1049 break;\r
1050 }\r
1051 SupportedLanguages += 3;\r
1052 } else {\r
1053 for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);\r
1054 if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {\r
1055 Found = TRUE;\r
1056 break;\r
1057 }\r
1058 SupportedLanguages += Index;\r
1059 for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);\r
1060 }\r
1061 }\r
1062\r
1063 //\r
1064 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED\r
1065 //\r
1066 if (!Found) {\r
1067 return EFI_UNSUPPORTED;\r
1068 }\r
1069\r
1070 //\r
1071 // Determine the size of the Unicode String Table by looking for a NULL Language entry\r
1072 //\r
1073 NumberOfEntries = 0;\r
1074 if (*UnicodeStringTable != NULL) {\r
1075 OldUnicodeStringTable = *UnicodeStringTable;\r
1076 while (OldUnicodeStringTable->Language != NULL) {\r
1077 LanguageString = OldUnicodeStringTable->Language;\r
1078\r
1079 while (*LanguageString) {\r
1080 for (Index = 0; LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);\r
1081\r
1082 if (AsciiStrnCmp (Language, LanguageString, Index) == 0) { \r
1083 return EFI_ALREADY_STARTED;\r
1084 }\r
1085 LanguageString += Index;\r
1086 for (; *LanguageString != 0 && *LanguageString == ';'; LanguageString++);\r
1087 }\r
1088 OldUnicodeStringTable++;\r
1089 NumberOfEntries++;\r
1090 }\r
1091 }\r
1092\r
1093 //\r
1094 // Allocate space for a new Unicode String Table. It must hold the current number of\r
1095 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table\r
1096 // marker\r
1097 //\r
1098 NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));\r
1099 if (NewUnicodeStringTable == NULL) {\r
1100 return EFI_OUT_OF_RESOURCES;\r
1101 }\r
1102\r
1103 //\r
1104 // If the current Unicode String Table contains any entries, then copy them to the\r
1105 // newly allocated Unicode String Table.\r
1106 //\r
1107 if (*UnicodeStringTable != NULL) {\r
1108 CopyMem (\r
1109 NewUnicodeStringTable,\r
1110 *UnicodeStringTable,\r
1111 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)\r
1112 );\r
1113 }\r
1114\r
1115 //\r
1116 // Allocate space for a copy of the Language specifier\r
1117 //\r
1118 NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (AsciiStrSize(Language), Language);\r
1119 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {\r
1120 gBS->FreePool (NewUnicodeStringTable);\r
1121 return EFI_OUT_OF_RESOURCES;\r
1122 }\r
1123\r
1124 //\r
1125 // Compute the length of the Unicode String\r
1126 //\r
1127 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++);\r
1128\r
1129 //\r
1130 // Allocate space for a copy of the Unicode String\r
1131 //\r
1132 NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (StrSize (UnicodeString), UnicodeString);\r
1133 if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {\r
1134 gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);\r
1135 gBS->FreePool (NewUnicodeStringTable);\r
1136 return EFI_OUT_OF_RESOURCES;\r
1137 }\r
1138\r
1139 //\r
1140 // Mark the end of the Unicode String Table\r
1141 //\r
1142 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;\r
1143 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;\r
1144\r
1145 //\r
1146 // Free the old Unicode String Table\r
1147 //\r
1148 if (*UnicodeStringTable != NULL) {\r
1149 gBS->FreePool (*UnicodeStringTable);\r
1150 }\r
1151\r
1152 //\r
1153 // Point UnicodeStringTable at the newly allocated Unicode String Table\r
1154 //\r
1155 *UnicodeStringTable = NewUnicodeStringTable;\r
1156\r
1157 return EFI_SUCCESS;\r
1158}\r
1159\r
e386b444 1160/**\r
1161 This function frees the table of Unicode strings in UnicodeStringTable.\r
1162 If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.\r
dd51a993 1163 Otherwise, each language code, and each Unicode string in the Unicode string \r
e386b444 1164 table are freed, and EFI_SUCCESS is returned.\r
1165\r
1166 @param UnicodeStringTable A pointer to the table of Unicode strings.\r
1167\r
1168 @retval EFI_SUCCESS The Unicode string table was freed.\r
1169\r
1170**/\r
1171EFI_STATUS\r
1172EFIAPI\r
1173FreeUnicodeStringTable (\r
1174 IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable\r
1175 )\r
1176{\r
1177 UINTN Index;\r
1178\r
1179 //\r
1180 // If the Unicode String Table is NULL, then it is already freed\r
1181 //\r
1182 if (UnicodeStringTable == NULL) {\r
1183 return EFI_SUCCESS;\r
1184 }\r
1185\r
1186 //\r
1187 // Loop through the Unicode String Table until we reach the end of table marker\r
1188 //\r
1189 for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) {\r
1190\r
1191 //\r
1192 // Free the Language string from the Unicode String Table\r
1193 //\r
1194 gBS->FreePool (UnicodeStringTable[Index].Language);\r
1195\r
1196 //\r
1197 // Free the Unicode String from the Unicode String Table\r
1198 //\r
1199 if (UnicodeStringTable[Index].UnicodeString != NULL) {\r
1200 gBS->FreePool (UnicodeStringTable[Index].UnicodeString);\r
1201 }\r
1202 }\r
1203\r
1204 //\r
1205 // Free the Unicode String Table itself\r
1206 //\r
1207 gBS->FreePool (UnicodeStringTable);\r
1208\r
1209 return EFI_SUCCESS;\r
1210}\r
1211\r