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