2 The UEFI Library provides functions and macros that simplify the development of
3 UEFI Drivers and UEFI Applications. These functions and macros help manage EFI
4 events, build simple locks utilizing EFI Task Priority Levels (TPLs), install
5 EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers,
6 and print messages on the console output and standard error devices.
8 Copyright (c) 2006 - 2007, Intel Corporation<BR>
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include "UefiLibInternal.h"
23 Compare whether two names of languages are identical.
25 @param Language1 Name of language 1.
26 @param Language2 Name of language 2.
28 @retval TRUE Language 1 and language 2 are the same.
29 @retval FALSE Language 1 and language 2 are not the same.
33 CompareIso639LanguageCode (
34 IN CONST CHAR8
*Language1
,
35 IN CONST CHAR8
*Language2
41 Name1
= ReadUnaligned24 ((CONST UINT32
*) Language1
);
42 Name2
= ReadUnaligned24 ((CONST UINT32
*) Language2
);
44 return (BOOLEAN
) (Name1
== Name2
);
48 This function searches the list of configuration tables stored in the EFI System
49 Table for a table with a GUID that matches TableGuid. If a match is found,
50 then a pointer to the configuration table is returned in Table, and EFI_SUCCESS
51 is returned. If a matching GUID is not found, then EFI_NOT_FOUND is returned.
52 If TableGuid is NULL, then ASSERT().
53 If Table is NULL, then ASSERT().
55 @param TableGuid Pointer to table's GUID type..
56 @param Table Pointer to the table associated with TableGuid in the EFI System Table.
58 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
59 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
64 EfiGetSystemConfigurationTable (
65 IN EFI_GUID
*TableGuid
,
69 EFI_SYSTEM_TABLE
*SystemTable
;
72 ASSERT (TableGuid
!= NULL
);
73 ASSERT (Table
!= NULL
);
77 for (Index
= 0; Index
< SystemTable
->NumberOfTableEntries
; Index
++) {
78 if (CompareGuid (TableGuid
, &(SystemTable
->ConfigurationTable
[Index
].VendorGuid
))) {
79 *Table
= SystemTable
->ConfigurationTable
[Index
].VendorTable
;
88 This function causes the notification function to be executed for every protocol
89 of type ProtocolGuid instance that exists in the system when this function is
90 invoked. In addition, every time a protocol of type ProtocolGuid instance is
91 installed or reinstalled, the notification function is also executed.
93 @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.
94 @param NotifyTpl Supplies the task priority level of the event notifications.
95 @param NotifyFunction Supplies the function to notify when the event is signaled.
96 @param NotifyContext The context parameter to pass to NotifyFunction.
97 @param Registration A pointer to a memory location to receive the registration value.
99 @return The notification event that was created.
104 EfiCreateProtocolNotifyEvent(
105 IN EFI_GUID
*ProtocolGuid
,
106 IN EFI_TPL NotifyTpl
,
107 IN EFI_EVENT_NOTIFY NotifyFunction
,
108 IN VOID
*NotifyContext
, OPTIONAL
109 OUT VOID
**Registration
119 Status
= gBS
->CreateEvent (
126 ASSERT_EFI_ERROR (Status
);
129 // Register for protocol notifactions on this event
132 Status
= gBS
->RegisterProtocolNotify (
138 ASSERT_EFI_ERROR (Status
);
141 // Kick the event so we will perform an initial pass of
142 // current installed drivers
145 gBS
->SignalEvent (Event
);
150 This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.
151 This event is signaled with EfiNamedEventSignal(). This provide the ability for
152 one or more listeners on the same event named by the GUID specified by Name.
153 If Name is NULL, then ASSERT().
154 If NotifyTpl is not a legal TPL value, then ASSERT().
155 If NotifyFunction is NULL, then ASSERT().
157 @param Name Supplies GUID name of the event.
158 @param NotifyTpl Supplies the task priority level of the event notifications.
159 @param NotifyFunction Supplies the function to notify when the event is signaled.
160 @param NotifyContext The context parameter to pass to NotifyFunction.
161 @param Registration A pointer to a memory location to receive the registration value.
163 @retval EFI_SUCCESS A named event was created.
164 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
169 EfiNamedEventListen (
170 IN CONST EFI_GUID
*Name
,
171 IN EFI_TPL NotifyTpl
,
172 IN EFI_EVENT_NOTIFY NotifyFunction
,
173 IN CONST VOID
*NotifyContext
, OPTIONAL
174 OUT VOID
*Registration OPTIONAL
179 VOID
*RegistrationLocal
;
181 ASSERT (Name
!= NULL
);
182 ASSERT (NotifyFunction
!= NULL
);
183 ASSERT (NotifyTpl
<= TPL_HIGH_LEVEL
);
188 Status
= gBS
->CreateEvent (
192 (VOID
*) NotifyContext
,
195 ASSERT_EFI_ERROR (Status
);
198 // The Registration is not optional to RegisterProtocolNotify().
199 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.
201 if (Registration
!= NULL
) {
202 RegistrationLocal
= Registration
;
204 RegistrationLocal
= &RegistrationLocal
;
208 // Register for an installation of protocol interface
211 Status
= gBS
->RegisterProtocolNotify (
216 ASSERT_EFI_ERROR (Status
);
222 This function signals the named event specified by Name. The named event must
223 have been created with EfiNamedEventListen().
225 @param Name Supplies GUID name of the event.
227 @retval EFI_SUCCESS A named event was signaled.
228 @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event.
233 EfiNamedEventSignal (
234 IN CONST EFI_GUID
*Name
241 Status
= gBS
->InstallProtocolInterface (
244 EFI_NATIVE_INTERFACE
,
247 ASSERT_EFI_ERROR (Status
);
249 Status
= gBS
->UninstallProtocolInterface (
254 ASSERT_EFI_ERROR (Status
);
260 Returns the current TPL.
262 This function returns the current TPL. There is no EFI service to directly
263 retrieve the current TPL. Instead, the RaiseTPL() function is used to raise
264 the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level
265 can then immediately be restored back to the current TPL level with a call
270 @retval EFI_TPL The current TPL.
281 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
282 gBS
->RestoreTPL (Tpl
);
289 This function initializes a basic mutual exclusion lock to the released state
290 and returns the lock. Each lock provides mutual exclusion access at its task
291 priority level. Since there is no preemption or multiprocessor support in EFI,
292 acquiring the lock only consists of raising to the locks TPL.
293 If Lock is NULL, then ASSERT().
294 If Priority is not a valid TPL value, then ASSERT().
296 @param Lock A pointer to the lock data structure to initialize.
297 @param Priority EFI TPL associated with the lock.
305 IN OUT EFI_LOCK
*Lock
,
309 ASSERT (Lock
!= NULL
);
310 ASSERT (Priority
<= TPL_HIGH_LEVEL
);
312 Lock
->Tpl
= Priority
;
313 Lock
->OwnerTpl
= TPL_APPLICATION
;
314 Lock
->Lock
= EfiLockReleased
;
319 This function raises the system's current task priority level to the task
320 priority level of the mutual exclusion lock. Then, it places the lock in the
322 If Lock is NULL, then ASSERT().
323 If Lock is not initialized, then ASSERT().
324 If Lock is already in the acquired state, then ASSERT().
326 @param Lock The task lock with priority level.
335 ASSERT (Lock
!= NULL
);
336 ASSERT (Lock
->Lock
== EfiLockReleased
);
338 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
339 Lock
->Lock
= EfiLockAcquired
;
343 This function raises the system's current task priority level to the task
344 priority level of the mutual exclusion lock. Then, it attempts to place the
345 lock in the acquired state.
347 @param Lock A pointer to the lock to acquire.
349 @retval EFI_SUCCESS The lock was acquired.
350 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
355 EfiAcquireLockOrFail (
360 ASSERT (Lock
!= NULL
);
361 ASSERT (Lock
->Lock
!= EfiLockUninitialized
);
363 if (Lock
->Lock
== EfiLockAcquired
) {
365 // Lock is already owned, so bail out
367 return EFI_ACCESS_DENIED
;
370 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
372 Lock
->Lock
= EfiLockAcquired
;
378 This function transitions a mutual exclusion lock from the acquired state to
379 the released state, and restores the system's task priority level to its
382 @param Lock A pointer to the lock to release.
393 ASSERT (Lock
!= NULL
);
394 ASSERT (Lock
->Lock
== EfiLockAcquired
);
396 Tpl
= Lock
->OwnerTpl
;
398 Lock
->Lock
= EfiLockReleased
;
400 gBS
->RestoreTPL (Tpl
);
404 Tests whether a controller handle is being managed by a specific driver.
406 This function tests whether the driver specified by DriverBindingHandle is
407 currently managing the controller specified by ControllerHandle. This test
408 is performed by evaluating if the the protocol specified by ProtocolGuid is
409 present on ControllerHandle and is was opened by DriverBindingHandle with an
410 attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
411 If ProtocolGuid is NULL, then ASSERT().
413 @param ControllerHandle A handle for a controller to test.
414 @param DriverBindingHandle Specifies the driver binding handle for the
416 @param ProtocolGuid Specifies the protocol that the driver specified
417 by DriverBindingHandle opens in its Start()
420 @retval EFI_SUCCESS ControllerHandle is managed by the driver
421 specifed by DriverBindingHandle.
422 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
423 specifed by DriverBindingHandle.
428 EfiTestManagedDevice (
429 IN CONST EFI_HANDLE ControllerHandle
,
430 IN CONST EFI_HANDLE DriverBindingHandle
,
431 IN CONST EFI_GUID
*ProtocolGuid
435 VOID
*ManagedInterface
;
437 ASSERT (ProtocolGuid
!= NULL
);
439 Status
= gBS
->OpenProtocol (
441 (EFI_GUID
*) ProtocolGuid
,
445 EFI_OPEN_PROTOCOL_BY_DRIVER
447 if (!EFI_ERROR (Status
)) {
450 (EFI_GUID
*) ProtocolGuid
,
454 return EFI_UNSUPPORTED
;
457 if (Status
!= EFI_ALREADY_STARTED
) {
458 return EFI_UNSUPPORTED
;
465 Tests whether a child handle is a child device of the controller.
467 This function tests whether ChildHandle is one of the children of
468 ControllerHandle. This test is performed by checking to see if the protocol
469 specified by ProtocolGuid is present on ControllerHandle and opened by
470 ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
471 If ProtocolGuid is NULL, then ASSERT().
473 @param ControllerHandle A handle for a (parent) controller to test.
474 @param ChildHandle A child handle to test.
475 @param ProtocolGuid Supplies the protocol that the child controller
476 opens on its parent controller.
478 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
479 @retval EFI_UNSUPPORTED ChildHandle is not a child of the
486 IN CONST EFI_HANDLE ControllerHandle
,
487 IN CONST EFI_HANDLE ChildHandle
,
488 IN CONST EFI_GUID
*ProtocolGuid
492 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
496 ASSERT (ProtocolGuid
!= NULL
);
499 // Retrieve the list of agents that are consuming the specific protocol
500 // on ControllerHandle.
502 Status
= gBS
->OpenProtocolInformation (
504 (EFI_GUID
*) ProtocolGuid
,
508 if (EFI_ERROR (Status
)) {
509 return EFI_UNSUPPORTED
;
513 // Inspect if ChildHandle is one of the agents.
515 Status
= EFI_UNSUPPORTED
;
516 for (Index
= 0; Index
< EntryCount
; Index
++) {
517 if ((OpenInfoBuffer
[Index
].ControllerHandle
== ChildHandle
) &&
518 (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
519 Status
= EFI_SUCCESS
;
524 FreePool (OpenInfoBuffer
);
529 This function looks up a Unicode string in UnicodeStringTable.
530 If Language is a member of SupportedLanguages and a Unicode
531 string is found in UnicodeStringTable that matches the
532 language code specified by Language, then it is returned in
535 @param Language A pointer to the ISO 639-2
536 language code for the Unicode
537 string to look up and return.
539 @param SupportedLanguages A pointer to the set of ISO
541 codes that the Unicode string
542 table supports. Language must
543 be a member of this set.
545 @param UnicodeStringTable A pointer to the table of
548 @param UnicodeString A pointer to the Unicode
549 string from UnicodeStringTable
550 that matches the language
551 specified by Language.
553 @retval EFI_SUCCESS The Unicode string that
554 matches the language specified
555 by Language was found in the
556 table of Unicoide strings
557 UnicodeStringTable, and it was
558 returned in UnicodeString.
560 @retval EFI_INVALID_PARAMETER Language is NULL.
562 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
563 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
565 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
567 @retval EFI_UNSUPPORTED The language specified by
568 Language is not a member
569 ofSupportedLanguages.
571 @retval EFI_UNSUPPORTED The language specified by
572 Language is not supported by
578 LookupUnicodeString (
579 IN CONST CHAR8
*Language
,
580 IN CONST CHAR8
*SupportedLanguages
,
581 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
582 OUT CHAR16
**UnicodeString
586 // Make sure the parameters are valid
588 if (Language
== NULL
|| UnicodeString
== NULL
) {
589 return EFI_INVALID_PARAMETER
;
593 // If there are no supported languages, or the Unicode String Table is empty, then the
594 // Unicode String specified by Language is not supported by this Unicode String Table
596 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
597 return EFI_UNSUPPORTED
;
601 // Make sure Language is in the set of Supported Languages
603 while (*SupportedLanguages
!= 0) {
604 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
607 // Search the Unicode String Table for the matching Language specifier
609 while (UnicodeStringTable
->Language
!= NULL
) {
610 if (CompareIso639LanguageCode (Language
, UnicodeStringTable
->Language
)) {
613 // A matching string was found, so return it
615 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
619 UnicodeStringTable
++;
622 return EFI_UNSUPPORTED
;
625 SupportedLanguages
+= 3;
628 return EFI_UNSUPPORTED
;
634 This function looks up a Unicode string in UnicodeStringTable.
635 If Language is a member of SupportedLanguages and a Unicode
636 string is found in UnicodeStringTable that matches the
637 language code specified by Language, then it is returned in
640 @param Language A pointer to the ISO 639-2 or
641 RFC 3066 language code for the
642 Unicode string to look up and
645 @param SupportedLanguages A pointer to the set of ISO
646 639-2 or RFC 3066 language
647 codes that the Unicode string
648 table supports. Language must
649 be a member of this set.
651 @param UnicodeStringTable A pointer to the table of
654 @param UnicodeString A pointer to the Unicode
655 string from UnicodeStringTable
656 that matches the language
657 specified by Language.
659 @param Iso639Language Specify the language code
660 format supported. If true,
661 then the format follow ISO
662 639-2. If false, then it
665 @retval EFI_SUCCESS The Unicode string that
666 matches the language specified
667 by Language was found in the
668 table of Unicoide strings
669 UnicodeStringTable, and it was
670 returned in UnicodeString.
672 @retval EFI_INVALID_PARAMETER Language is NULL.
674 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
676 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
678 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
680 @retval EFI_UNSUPPORTED The language specified by
681 Language is not a member
682 ofSupportedLanguages.
684 @retval EFI_UNSUPPORTED The language specified by
685 Language is not supported by
692 LookupUnicodeString2 (
693 IN CONST CHAR8
*Language
,
694 IN CONST CHAR8
*SupportedLanguages
,
695 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
696 OUT CHAR16
**UnicodeString
,
697 IN BOOLEAN Iso639Language
702 CHAR8
*LanguageString
;
705 // Make sure the parameters are valid
707 if (Language
== NULL
|| UnicodeString
== NULL
) {
708 return EFI_INVALID_PARAMETER
;
712 // If there are no supported languages, or the Unicode String Table is empty, then the
713 // Unicode String specified by Language is not supported by this Unicode String Table
715 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
716 return EFI_UNSUPPORTED
;
720 // Make sure Language is in the set of Supported Languages
723 while (*SupportedLanguages
!= 0) {
724 if (Iso639Language
) {
725 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
729 SupportedLanguages
+= 3;
731 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
732 if ((AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) && (Language
[Index
] == 0)) {
736 SupportedLanguages
+= Index
;
737 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
742 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
745 return EFI_UNSUPPORTED
;
749 // Search the Unicode String Table for the matching Language specifier
751 while (UnicodeStringTable
->Language
!= NULL
) {
752 LanguageString
= UnicodeStringTable
->Language
;
753 while (0 != *LanguageString
) {
754 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
755 if (AsciiStrnCmp(LanguageString
, Language
, Index
) == 0) {
756 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
759 LanguageString
+= Index
;
760 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] == ';'; Index
++);
762 UnicodeStringTable
++;
765 return EFI_UNSUPPORTED
;
771 This function adds a Unicode string to UnicodeStringTable.
772 If Language is a member of SupportedLanguages then
773 UnicodeString is added to UnicodeStringTable. New buffers are
774 allocated for both Language and UnicodeString. The contents
775 of Language and UnicodeString are copied into these new
776 buffers. These buffers are automatically freed when
777 FreeUnicodeStringTable() is called.
779 @param Language A pointer to the ISO 639-2
780 language code for the Unicode
783 @param SupportedLanguages A pointer to the set of ISO
784 639-2 language codes that the
785 Unicode string table supports.
786 Language must be a member of
789 @param UnicodeStringTable A pointer to the table of
792 @param UnicodeString A pointer to the Unicode
795 @retval EFI_SUCCESS The Unicode string that
796 matches the language specified
797 by Language was found in the
798 table of Unicode strings
799 UnicodeStringTable, and it was
800 returned in UnicodeString.
802 @retval EFI_INVALID_PARAMETER Language is NULL.
804 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
806 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
808 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
810 @retval EFI_ALREADY_STARTED A Unicode string with language
811 Language is already present in
814 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
815 add another Unicode string to
818 @retval EFI_UNSUPPORTED The language specified by
819 Language is not a member of
826 IN CONST CHAR8
*Language
,
827 IN CONST CHAR8
*SupportedLanguages
,
828 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
829 IN CONST CHAR16
*UnicodeString
832 UINTN NumberOfEntries
;
833 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
834 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
835 UINTN UnicodeStringLength
;
838 // Make sure the parameter are valid
840 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
841 return EFI_INVALID_PARAMETER
;
845 // If there are no supported languages, then a Unicode String can not be added
847 if (SupportedLanguages
== NULL
) {
848 return EFI_UNSUPPORTED
;
852 // If the Unicode String is empty, then a Unicode String can not be added
854 if (UnicodeString
[0] == 0) {
855 return EFI_INVALID_PARAMETER
;
859 // Make sure Language is a member of SupportedLanguages
861 while (*SupportedLanguages
!= 0) {
862 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
865 // Determine the size of the Unicode String Table by looking for a NULL Language entry
868 if (*UnicodeStringTable
!= NULL
) {
869 OldUnicodeStringTable
= *UnicodeStringTable
;
870 while (OldUnicodeStringTable
->Language
!= NULL
) {
871 if (CompareIso639LanguageCode (Language
, OldUnicodeStringTable
->Language
)) {
872 return EFI_ALREADY_STARTED
;
875 OldUnicodeStringTable
++;
881 // Allocate space for a new Unicode String Table. It must hold the current number of
882 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
885 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
886 if (NewUnicodeStringTable
== NULL
) {
887 return EFI_OUT_OF_RESOURCES
;
891 // If the current Unicode String Table contains any entries, then copy them to the
892 // newly allocated Unicode String Table.
894 if (*UnicodeStringTable
!= NULL
) {
896 NewUnicodeStringTable
,
898 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
903 // Allocate space for a copy of the Language specifier
905 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (3, Language
);
906 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
907 gBS
->FreePool (NewUnicodeStringTable
);
908 return EFI_OUT_OF_RESOURCES
;
912 // Compute the length of the Unicode String
914 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++)
918 // Allocate space for a copy of the Unicode String
920 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (
921 (UnicodeStringLength
+ 1) * sizeof (CHAR16
),
924 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
925 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
926 gBS
->FreePool (NewUnicodeStringTable
);
927 return EFI_OUT_OF_RESOURCES
;
931 // Mark the end of the Unicode String Table
933 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
934 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
937 // Free the old Unicode String Table
939 if (*UnicodeStringTable
!= NULL
) {
940 gBS
->FreePool (*UnicodeStringTable
);
944 // Point UnicodeStringTable at the newly allocated Unicode String Table
946 *UnicodeStringTable
= NewUnicodeStringTable
;
951 SupportedLanguages
+= 3;
954 return EFI_UNSUPPORTED
;
960 This function adds a Unicode string to UnicodeStringTable.
961 If Language is a member of SupportedLanguages then
962 UnicodeString is added to UnicodeStringTable. New buffers are
963 allocated for both Language and UnicodeString. The contents
964 of Language and UnicodeString are copied into these new
965 buffers. These buffers are automatically freed when
966 FreeUnicodeStringTable() is called.
968 @param Language A pointer to the ISO 639-2 or
969 RFC 3066 language code for the
970 Unicode string to add.
972 @param SupportedLanguages A pointer to the set of ISO
973 639-2 or RFC 3.66 language
974 codes that the Unicode string
975 table supports. Language must
976 be a member of this set.
978 @param UnicodeStringTable A pointer to the table of
981 @param UnicodeString A pointer to the Unicode
984 @param Iso639Language Specify the language code
985 format supported. If true,
986 then the format follow ISO
987 639-2. If false, then it
990 @retval EFI_SUCCESS The Unicode string that
991 matches the language specified
992 by Language was found in the
993 table of Unicode strings
994 UnicodeStringTable, and it was
995 returned in UnicodeString.
997 @retval EFI_INVALID_PARAMETER Language is NULL.
999 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
1001 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
1003 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
1005 @retval EFI_ALREADY_STARTED A Unicode string with language
1006 Language is already present in
1009 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
1010 add another Unicode string to
1013 @retval EFI_UNSUPPORTED The language specified by
1014 Language is not a member of
1021 IN CONST CHAR8
*Language
,
1022 IN CONST CHAR8
*SupportedLanguages
,
1023 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
1024 IN CONST CHAR16
*UnicodeString
,
1025 IN BOOLEAN Iso639Language
1028 UINTN NumberOfEntries
;
1029 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
1030 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
1031 UINTN UnicodeStringLength
;
1034 CHAR8
*LanguageString
;
1037 // Make sure the parameter are valid
1039 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
1040 return EFI_INVALID_PARAMETER
;
1044 // If there are no supported languages, then a Unicode String can not be added
1046 if (SupportedLanguages
== NULL
) {
1047 return EFI_UNSUPPORTED
;
1051 // If the Unicode String is empty, then a Unicode String can not be added
1053 if (UnicodeString
[0] == 0) {
1054 return EFI_INVALID_PARAMETER
;
1058 // Make sure Language is a member of SupportedLanguages
1061 while (*SupportedLanguages
!= 0) {
1062 if (Iso639Language
) {
1063 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
1067 SupportedLanguages
+= 3;
1069 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
1070 if (AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) {
1074 SupportedLanguages
+= Index
;
1075 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
1080 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
1083 return EFI_UNSUPPORTED
;
1087 // Determine the size of the Unicode String Table by looking for a NULL Language entry
1089 NumberOfEntries
= 0;
1090 if (*UnicodeStringTable
!= NULL
) {
1091 OldUnicodeStringTable
= *UnicodeStringTable
;
1092 while (OldUnicodeStringTable
->Language
!= NULL
) {
1093 LanguageString
= OldUnicodeStringTable
->Language
;
1095 while (*LanguageString
!= 0) {
1096 for (Index
= 0; LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
1098 if (AsciiStrnCmp (Language
, LanguageString
, Index
) == 0) {
1099 return EFI_ALREADY_STARTED
;
1101 LanguageString
+= Index
;
1102 for (; *LanguageString
!= 0 && *LanguageString
== ';'; LanguageString
++);
1104 OldUnicodeStringTable
++;
1110 // Allocate space for a new Unicode String Table. It must hold the current number of
1111 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
1114 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
1115 if (NewUnicodeStringTable
== NULL
) {
1116 return EFI_OUT_OF_RESOURCES
;
1120 // If the current Unicode String Table contains any entries, then copy them to the
1121 // newly allocated Unicode String Table.
1123 if (*UnicodeStringTable
!= NULL
) {
1125 NewUnicodeStringTable
,
1126 *UnicodeStringTable
,
1127 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
1132 // Allocate space for a copy of the Language specifier
1134 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (AsciiStrSize(Language
), Language
);
1135 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
1136 gBS
->FreePool (NewUnicodeStringTable
);
1137 return EFI_OUT_OF_RESOURCES
;
1141 // Compute the length of the Unicode String
1143 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++);
1146 // Allocate space for a copy of the Unicode String
1148 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (StrSize (UnicodeString
), UnicodeString
);
1149 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
1150 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
1151 gBS
->FreePool (NewUnicodeStringTable
);
1152 return EFI_OUT_OF_RESOURCES
;
1156 // Mark the end of the Unicode String Table
1158 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
1159 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
1162 // Free the old Unicode String Table
1164 if (*UnicodeStringTable
!= NULL
) {
1165 gBS
->FreePool (*UnicodeStringTable
);
1169 // Point UnicodeStringTable at the newly allocated Unicode String Table
1171 *UnicodeStringTable
= NewUnicodeStringTable
;
1177 This function frees the table of Unicode strings in UnicodeStringTable.
1178 If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.
1179 Otherwise, each language code, and each Unicode string in the Unicode string
1180 table are freed, and EFI_SUCCESS is returned.
1182 @param UnicodeStringTable A pointer to the table of Unicode strings.
1184 @retval EFI_SUCCESS The Unicode string table was freed.
1189 FreeUnicodeStringTable (
1190 IN EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
1196 // If the Unicode String Table is NULL, then it is already freed
1198 if (UnicodeStringTable
== NULL
) {
1203 // Loop through the Unicode String Table until we reach the end of table marker
1205 for (Index
= 0; UnicodeStringTable
[Index
].Language
!= NULL
; Index
++) {
1208 // Free the Language string from the Unicode String Table
1210 gBS
->FreePool (UnicodeStringTable
[Index
].Language
);
1213 // Free the Unicode String from the Unicode String Table
1215 if (UnicodeStringTable
[Index
].UnicodeString
!= NULL
) {
1216 gBS
->FreePool (UnicodeStringTable
[Index
].UnicodeString
);
1221 // Free the Unicode String Table itself
1223 gBS
->FreePool (UnicodeStringTable
);
1229 Determine what is the current language setting. The space reserved for Lang
1230 must be at least RFC_3066_ENTRY_SIZE bytes;
1232 If Lang is NULL, then ASSERT.
1234 @param Lang Pointer of system language. Lang will always be filled with
1235 a valid RFC 3066 language string. If "PlatformLang" is not
1236 set in the system, the default language specifed by PcdUefiVariableDefaultPlatformLang
1239 @return EFI_SUCCESS If the EFI Variable with "PlatformLang" is set and return in Lang.
1240 @return EFI_NOT_FOUND If the EFI Variable with "PlatformLang" is not set, but a valid default language is return in Lang.
1245 GetCurrentLanguage (
1252 ASSERT (Lang
!= NULL
);
1255 // Get current language setting
1257 Size
= RFC_3066_ENTRY_SIZE
;
1258 Status
= gRT
->GetVariable (
1260 &gEfiGlobalVariableGuid
,
1266 if (EFI_ERROR (Status
)) {
1267 AsciiStrCpy (Lang
, (CHAR8
*) PcdGetPtr (PcdUefiVariableDefaultPlatformLang
));