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 Retrieves a pointer to the system configuration table from the EFI System Table
49 based on a specified GUID.
51 This function searches the list of configuration tables stored in the EFI System Table
52 for a table with a GUID that matches TableGuid. If a match is found, then a pointer to
53 the configuration table is returned in Table., and EFI_SUCCESS is returned. If a matching GUID
54 is not found, then EFI_NOT_FOUND is returned.
55 If TableGuid is NULL, then ASSERT().
56 If Table is NULL, then ASSERT().
58 @param TableGuid Pointer to table's GUID type..
59 @param Table Pointer to the table associated with TableGuid in the EFI System Table.
61 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
62 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
67 EfiGetSystemConfigurationTable (
68 IN EFI_GUID
*TableGuid
,
72 EFI_SYSTEM_TABLE
*SystemTable
;
75 ASSERT (TableGuid
!= NULL
);
76 ASSERT (Table
!= NULL
);
80 for (Index
= 0; Index
< SystemTable
->NumberOfTableEntries
; Index
++) {
81 if (CompareGuid (TableGuid
, &(SystemTable
->ConfigurationTable
[Index
].VendorGuid
))) {
82 *Table
= SystemTable
->ConfigurationTable
[Index
].VendorTable
;
91 Creates and returns a notification event and registers that event with all the protocol
92 instances specified by ProtocolGuid.
94 This function causes the notification function to be executed for every protocol of type
95 ProtocolGuid instance that exists in the system when this function is invoked.
96 In addition, every time a protocol of type ProtocolGuid instance is installed or reinstalled,
97 the notification function is also executed. This function returns the notification event
99 If ProtocolGuid is NULL, then ASSERT().
100 If NotifyTpl is not a legal TPL value, then ASSERT().
101 If NotifyFunction is NULL, then ASSERT().
102 If Registration is NULL, then ASSERT().
104 @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.
105 @param NotifyTpl Supplies the task priority level of the event notifications.
106 @param NotifyFunction Supplies the function to notify when the event is signaled.
107 @param NotifyContext The context parameter to pass to NotifyFunction.
108 @param Registration A pointer to a memory location to receive the registration value.
109 This value is passed to LocateHandle() to obtain new handles that
110 have been added that support the ProtocolGuid-specified protocol.
112 @return The notification event that was created.
117 EfiCreateProtocolNotifyEvent(
118 IN EFI_GUID
*ProtocolGuid
,
119 IN EFI_TPL NotifyTpl
,
120 IN EFI_EVENT_NOTIFY NotifyFunction
,
121 IN VOID
*NotifyContext
, OPTIONAL
122 OUT VOID
**Registration
128 ASSERT (ProtocolGuid
!= NULL
);
129 ASSERT (NotifyFunction
!= NULL
);
130 ASSERT (Registration
!= NULL
);
136 Status
= gBS
->CreateEvent (
143 ASSERT_EFI_ERROR (Status
);
146 // Register for protocol notifactions on this event
149 Status
= gBS
->RegisterProtocolNotify (
155 ASSERT_EFI_ERROR (Status
);
158 // Kick the event so we will perform an initial pass of
159 // current installed drivers
162 gBS
->SignalEvent (Event
);
167 Creates a named event that can be signaled with EfiNamedEventSignal().
169 This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.
170 This event is signaled with EfiNamedEventSignal(). This provides the ability for one or more
171 listeners on the same event named by the GUID specified by Name.
172 If Name is NULL, then ASSERT().
173 If NotifyTpl is not a legal TPL value, then ASSERT().
174 If NotifyFunction is NULL, then ASSERT().
176 @param Name Supplies GUID name of the event.
177 @param NotifyTpl Supplies the task priority level of the event notifications.
178 @param NotifyFunction Supplies the function to notify when the event is signaled.
179 @param NotifyContext The context parameter to pass to NotifyFunction.
180 @param Registration A pointer to a memory location to receive the registration value.
182 @retval EFI_SUCCESS A named event was created.
183 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
188 EfiNamedEventListen (
189 IN CONST EFI_GUID
*Name
,
190 IN EFI_TPL NotifyTpl
,
191 IN EFI_EVENT_NOTIFY NotifyFunction
,
192 IN CONST VOID
*NotifyContext
, OPTIONAL
193 OUT VOID
*Registration OPTIONAL
198 VOID
*RegistrationLocal
;
200 ASSERT (Name
!= NULL
);
201 ASSERT (NotifyFunction
!= NULL
);
202 ASSERT (NotifyTpl
<= TPL_HIGH_LEVEL
);
207 Status
= gBS
->CreateEvent (
211 (VOID
*) NotifyContext
,
214 ASSERT_EFI_ERROR (Status
);
217 // The Registration is not optional to RegisterProtocolNotify().
218 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.
220 if (Registration
!= NULL
) {
221 RegistrationLocal
= Registration
;
223 RegistrationLocal
= &RegistrationLocal
;
227 // Register for an installation of protocol interface
230 Status
= gBS
->RegisterProtocolNotify (
235 ASSERT_EFI_ERROR (Status
);
241 Signals a named event created with EfiNamedEventListen().
243 This function signals the named event specified by Name. The named event must have been
244 created with EfiNamedEventListen().
245 If Name is NULL, then ASSERT().
247 @param Name Supplies GUID name of the event.
249 @retval EFI_SUCCESS A named event was signaled.
250 @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event.
255 EfiNamedEventSignal (
256 IN CONST EFI_GUID
*Name
262 ASSERT(Name
!= NULL
);
265 Status
= gBS
->InstallProtocolInterface (
268 EFI_NATIVE_INTERFACE
,
271 ASSERT_EFI_ERROR (Status
);
273 Status
= gBS
->UninstallProtocolInterface (
278 ASSERT_EFI_ERROR (Status
);
284 Returns the current TPL.
286 This function returns the current TPL. There is no EFI service to directly
287 retrieve the current TPL. Instead, the RaiseTPL() function is used to raise
288 the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level
289 can then immediately be restored back to the current TPL level with a call
292 @return The current TPL.
303 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
304 gBS
->RestoreTPL (Tpl
);
311 Initializes a basic mutual exclusion lock.
313 This function initializes a basic mutual exclusion lock to the released state
314 and returns the lock. Each lock provides mutual exclusion access at its task
315 priority level. Since there is no preemption or multiprocessor support in EFI,
316 acquiring the lock only consists of raising to the locks TPL.
317 If Lock is NULL, then ASSERT().
318 If Priority is not a valid TPL value, then ASSERT().
320 @param Lock A pointer to the lock data structure to initialize.
321 @param Priority EFI TPL associated with the lock.
329 IN OUT EFI_LOCK
*Lock
,
333 ASSERT (Lock
!= NULL
);
334 ASSERT (Priority
<= TPL_HIGH_LEVEL
);
336 Lock
->Tpl
= Priority
;
337 Lock
->OwnerTpl
= TPL_APPLICATION
;
338 Lock
->Lock
= EfiLockReleased
;
343 Acquires ownership of a lock.
345 This function raises the system's current task priority level to the task
346 priority level of the mutual exclusion lock. Then, it places the lock in the
348 If Lock is NULL, then ASSERT().
349 If Lock is not initialized, then ASSERT().
350 If Lock is already in the acquired state, then ASSERT().
352 @param Lock A pointer to the lock to acquire.
361 ASSERT (Lock
!= NULL
);
362 ASSERT (Lock
->Lock
== EfiLockReleased
);
364 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
365 Lock
->Lock
= EfiLockAcquired
;
369 Acquires ownership of a lock.
371 This function raises the system's current task priority level to the task priority
372 level of the mutual exclusion lock. Then, it attempts to place the lock in the acquired state.
373 If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.
374 Otherwise, EFI_SUCCESS is returned.
375 If Lock is NULL, then ASSERT().
376 If Lock is not initialized, then ASSERT().
378 @param Lock A pointer to the lock to acquire.
380 @retval EFI_SUCCESS The lock was acquired.
381 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
386 EfiAcquireLockOrFail (
391 ASSERT (Lock
!= NULL
);
392 ASSERT (Lock
->Lock
!= EfiLockUninitialized
);
394 if (Lock
->Lock
== EfiLockAcquired
) {
396 // Lock is already owned, so bail out
398 return EFI_ACCESS_DENIED
;
401 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
403 Lock
->Lock
= EfiLockAcquired
;
409 Releases ownership of a lock.
411 This function transitions a mutual exclusion lock from the acquired state to
412 the released state, and restores the system's task priority level to its
414 If Lock is NULL, then ASSERT().
415 If Lock is not initialized, then ASSERT().
416 If Lock is already in the released state, then ASSERT().
418 @param Lock A pointer to the lock to release.
429 ASSERT (Lock
!= NULL
);
430 ASSERT (Lock
->Lock
== EfiLockAcquired
);
432 Tpl
= Lock
->OwnerTpl
;
434 Lock
->Lock
= EfiLockReleased
;
436 gBS
->RestoreTPL (Tpl
);
440 Tests whether a controller handle is being managed by a specific driver.
442 This function tests whether the driver specified by DriverBindingHandle is
443 currently managing the controller specified by ControllerHandle. This test
444 is performed by evaluating if the the protocol specified by ProtocolGuid is
445 present on ControllerHandle and is was opened by DriverBindingHandle with an
446 attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
447 If ProtocolGuid is NULL, then ASSERT().
449 @param ControllerHandle A handle for a controller to test.
450 @param DriverBindingHandle Specifies the driver binding handle for the
452 @param ProtocolGuid Specifies the protocol that the driver specified
453 by DriverBindingHandle opens in its Start()
456 @retval EFI_SUCCESS ControllerHandle is managed by the driver
457 specifed by DriverBindingHandle.
458 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
459 specifed by DriverBindingHandle.
464 EfiTestManagedDevice (
465 IN CONST EFI_HANDLE ControllerHandle
,
466 IN CONST EFI_HANDLE DriverBindingHandle
,
467 IN CONST EFI_GUID
*ProtocolGuid
471 VOID
*ManagedInterface
;
473 ASSERT (ProtocolGuid
!= NULL
);
475 Status
= gBS
->OpenProtocol (
477 (EFI_GUID
*) ProtocolGuid
,
481 EFI_OPEN_PROTOCOL_BY_DRIVER
483 if (!EFI_ERROR (Status
)) {
486 (EFI_GUID
*) ProtocolGuid
,
490 return EFI_UNSUPPORTED
;
493 if (Status
!= EFI_ALREADY_STARTED
) {
494 return EFI_UNSUPPORTED
;
501 Tests whether a child handle is a child device of the controller.
503 This function tests whether ChildHandle is one of the children of
504 ControllerHandle. This test is performed by checking to see if the protocol
505 specified by ProtocolGuid is present on ControllerHandle and opened by
506 ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
507 If ProtocolGuid is NULL, then ASSERT().
509 @param ControllerHandle A handle for a (parent) controller to test.
510 @param ChildHandle A child handle to test.
511 @param ProtocolGuid Supplies the protocol that the child controller
512 opens on its parent controller.
514 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
515 @retval EFI_UNSUPPORTED ChildHandle is not a child of the
522 IN CONST EFI_HANDLE ControllerHandle
,
523 IN CONST EFI_HANDLE ChildHandle
,
524 IN CONST EFI_GUID
*ProtocolGuid
528 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
532 ASSERT (ProtocolGuid
!= NULL
);
535 // Retrieve the list of agents that are consuming the specific protocol
536 // on ControllerHandle.
538 Status
= gBS
->OpenProtocolInformation (
540 (EFI_GUID
*) ProtocolGuid
,
544 if (EFI_ERROR (Status
)) {
545 return EFI_UNSUPPORTED
;
549 // Inspect if ChildHandle is one of the agents.
551 Status
= EFI_UNSUPPORTED
;
552 for (Index
= 0; Index
< EntryCount
; Index
++) {
553 if ((OpenInfoBuffer
[Index
].ControllerHandle
== ChildHandle
) &&
554 (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
555 Status
= EFI_SUCCESS
;
560 FreePool (OpenInfoBuffer
);
565 This function looks up a Unicode string in UnicodeStringTable.
567 If Language is a member of SupportedLanguages and a Unicode string is found in
568 UnicodeStringTable that matches the language code specified by Language, then it
569 is returned in UnicodeString.
571 @param Language A pointer to the ISO 639-2 language code for the
572 Unicode string to look up and return.
573 @param SupportedLanguages A pointer to the set of ISO 639-2 language codes
574 that the Unicode string table supports. Language
575 must be a member of this set.
576 @param UnicodeStringTable A pointer to the table of Unicode strings.
577 @param UnicodeString A pointer to the Unicode string from UnicodeStringTable
578 that matches the language specified by Language.
580 @retval EFI_SUCCESS The Unicode string that matches the language
581 specified by Language was found
582 in the table of Unicoide strings UnicodeStringTable,
583 and it was returned in UnicodeString.
584 @retval EFI_INVALID_PARAMETER Language is NULL.
585 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
586 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
587 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
588 @retval EFI_UNSUPPORTED The language specified by Language is not a
589 member of SupportedLanguages.
590 @retval EFI_UNSUPPORTED The language specified by Language is not
591 supported by UnicodeStringTable.
596 LookupUnicodeString (
597 IN CONST CHAR8
*Language
,
598 IN CONST CHAR8
*SupportedLanguages
,
599 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
600 OUT CHAR16
**UnicodeString
604 // Make sure the parameters are valid
606 if (Language
== NULL
|| UnicodeString
== NULL
) {
607 return EFI_INVALID_PARAMETER
;
611 // If there are no supported languages, or the Unicode String Table is empty, then the
612 // Unicode String specified by Language is not supported by this Unicode String Table
614 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
615 return EFI_UNSUPPORTED
;
619 // Make sure Language is in the set of Supported Languages
621 while (*SupportedLanguages
!= 0) {
622 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
625 // Search the Unicode String Table for the matching Language specifier
627 while (UnicodeStringTable
->Language
!= NULL
) {
628 if (CompareIso639LanguageCode (Language
, UnicodeStringTable
->Language
)) {
631 // A matching string was found, so return it
633 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
637 UnicodeStringTable
++;
640 return EFI_UNSUPPORTED
;
643 SupportedLanguages
+= 3;
646 return EFI_UNSUPPORTED
;
652 This function looks up a Unicode string in UnicodeStringTable.
654 If Language is a member of SupportedLanguages and a Unicode string is found in
655 UnicodeStringTable that matches the language code specified by Language, then
656 it is returned in UnicodeString.
658 @param Language A pointer to an ASCII string containing the ISO 639-2 or the
659 RFC 4646 language code for the Unicode string to look up and
660 return. If Iso639Language is TRUE, then this ASCII string is
661 not assumed to be Null-terminated, and only the first three
662 chacters are used. If Iso639Language is FALSE, then this ASCII
663 string must be Null-terminated.
664 @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains a
665 set of ISO 639-2 or RFC 4646 language codes that the Unicode
666 string table supports. Language must be a member of this set.
667 If Iso639Language is TRUE, then this string contains one or more
668 ISO 639-2 language codes with no separator characters. If Iso639Language
669 is FALSE, then is string contains one or more RFC 4646 language
670 codes separated by ';'.
671 @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE
672 is defined in "Related Definitions".
673 @param UnicodeString A pointer to the Null-terminated Unicode string from UnicodeStringTable
674 that matches the language specified by Language.
675 @param Iso639Language Specifies the supported language code format. If it is TRUE, then
676 Language and SupportedLanguages follow ISO 639-2 language code format.
677 Otherwise, they follow RFC 4646 language code format.
680 @retval EFI_SUCCESS The Unicode string that matches the language specified by Language
681 was found in the table of Unicode strings UnicodeStringTable, and
682 it was returned in UnicodeString.
683 @retval EFI_INVALID_PARAMETER Language is NULL.
684 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
685 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
686 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
687 @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages.
688 @retval EFI_UNSUPPORTED The language specified by Language is not supported by UnicodeStringTable.
694 LookupUnicodeString2 (
695 IN CONST CHAR8
*Language
,
696 IN CONST CHAR8
*SupportedLanguages
,
697 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
698 OUT CHAR16
**UnicodeString
,
699 IN BOOLEAN Iso639Language
704 CHAR8
*LanguageString
;
707 // Make sure the parameters are valid
709 if (Language
== NULL
|| UnicodeString
== NULL
) {
710 return EFI_INVALID_PARAMETER
;
714 // If there are no supported languages, or the Unicode String Table is empty, then the
715 // Unicode String specified by Language is not supported by this Unicode String Table
717 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
718 return EFI_UNSUPPORTED
;
722 // Make sure Language is in the set of Supported Languages
725 while (*SupportedLanguages
!= 0) {
726 if (Iso639Language
) {
727 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
731 SupportedLanguages
+= 3;
733 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
734 if ((AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) && (Language
[Index
] == 0)) {
738 SupportedLanguages
+= Index
;
739 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
744 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
747 return EFI_UNSUPPORTED
;
751 // Search the Unicode String Table for the matching Language specifier
753 while (UnicodeStringTable
->Language
!= NULL
) {
754 LanguageString
= UnicodeStringTable
->Language
;
755 while (0 != *LanguageString
) {
756 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
757 if (AsciiStrnCmp(LanguageString
, Language
, Index
) == 0) {
758 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
761 LanguageString
+= Index
;
762 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] == ';'; Index
++);
764 UnicodeStringTable
++;
767 return EFI_UNSUPPORTED
;
772 This function adds a Unicode string to UnicodeStringTable.
774 If Language is a member of SupportedLanguages then UnicodeString is added to
775 UnicodeStringTable. New buffers are allocated for both Language and
776 UnicodeString. The contents of Language and UnicodeString are copied into
777 these new buffers. These buffers are automatically freed when
778 FreeUnicodeStringTable() is called.
780 @param Language A pointer to the ISO 639-2 language code for the Unicode
782 @param SupportedLanguages A pointer to the set of ISO 639-2 language codes
783 that the Unicode string table supports.
784 Language must be a member of this set.
785 @param UnicodeStringTable A pointer to the table of Unicode strings.
786 @param UnicodeString A pointer to the Unicode string to add.
788 @retval EFI_SUCCESS The Unicode string that matches the language
789 specified by Language was found in the table of
790 Unicode strings UnicodeStringTable, and it was
791 returned in UnicodeString.
792 @retval EFI_INVALID_PARAMETER Language is NULL.
793 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
794 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
795 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
796 @retval EFI_ALREADY_STARTED A Unicode string with language Language is
797 already present in UnicodeStringTable.
798 @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another
799 Unicode string to UnicodeStringTable.
800 @retval EFI_UNSUPPORTED The language specified by Language is not a
801 member of SupportedLanguages.
807 IN CONST CHAR8
*Language
,
808 IN CONST CHAR8
*SupportedLanguages
,
809 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
810 IN CONST CHAR16
*UnicodeString
813 UINTN NumberOfEntries
;
814 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
815 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
816 UINTN UnicodeStringLength
;
819 // Make sure the parameter are valid
821 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
822 return EFI_INVALID_PARAMETER
;
826 // If there are no supported languages, then a Unicode String can not be added
828 if (SupportedLanguages
== NULL
) {
829 return EFI_UNSUPPORTED
;
833 // If the Unicode String is empty, then a Unicode String can not be added
835 if (UnicodeString
[0] == 0) {
836 return EFI_INVALID_PARAMETER
;
840 // Make sure Language is a member of SupportedLanguages
842 while (*SupportedLanguages
!= 0) {
843 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
846 // Determine the size of the Unicode String Table by looking for a NULL Language entry
849 if (*UnicodeStringTable
!= NULL
) {
850 OldUnicodeStringTable
= *UnicodeStringTable
;
851 while (OldUnicodeStringTable
->Language
!= NULL
) {
852 if (CompareIso639LanguageCode (Language
, OldUnicodeStringTable
->Language
)) {
853 return EFI_ALREADY_STARTED
;
856 OldUnicodeStringTable
++;
862 // Allocate space for a new Unicode String Table. It must hold the current number of
863 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
866 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
867 if (NewUnicodeStringTable
== NULL
) {
868 return EFI_OUT_OF_RESOURCES
;
872 // If the current Unicode String Table contains any entries, then copy them to the
873 // newly allocated Unicode String Table.
875 if (*UnicodeStringTable
!= NULL
) {
877 NewUnicodeStringTable
,
879 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
884 // Allocate space for a copy of the Language specifier
886 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (3, Language
);
887 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
888 gBS
->FreePool (NewUnicodeStringTable
);
889 return EFI_OUT_OF_RESOURCES
;
893 // Compute the length of the Unicode String
895 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++)
899 // Allocate space for a copy of the Unicode String
901 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (
902 (UnicodeStringLength
+ 1) * sizeof (CHAR16
),
905 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
906 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
907 gBS
->FreePool (NewUnicodeStringTable
);
908 return EFI_OUT_OF_RESOURCES
;
912 // Mark the end of the Unicode String Table
914 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
915 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
918 // Free the old Unicode String Table
920 if (*UnicodeStringTable
!= NULL
) {
921 gBS
->FreePool (*UnicodeStringTable
);
925 // Point UnicodeStringTable at the newly allocated Unicode String Table
927 *UnicodeStringTable
= NewUnicodeStringTable
;
932 SupportedLanguages
+= 3;
935 return EFI_UNSUPPORTED
;
940 This function adds the Null-terminated Unicode string specified by UnicodeString
941 to UnicodeStringTable.
943 If Language is a member of SupportedLanguages then UnicodeString is added to
944 UnicodeStringTable. New buffers are allocated for both Language and UnicodeString.
945 The contents of Language and UnicodeString are copied into these new buffers.
946 These buffers are automatically freed when EfiLibFreeUnicodeStringTable() is called.
948 @param Language A pointer to an ASCII string containing the ISO 639-2 or
949 the RFC 4646 language code for the Unicode string to add.
950 If Iso639Language is TRUE, then this ASCII string is not
951 assumed to be Null-terminated, and only the first three
952 chacters are used. If Iso639Language is FALSE, then this
953 ASCII string must be Null-terminated.
954 @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains
955 a set of ISO 639-2 or RFC 4646 language codes that the Unicode
956 string table supports. Language must be a member of this set.
957 If Iso639Language is TRUE, then this string contains one or more
958 ISO 639-2 language codes with no separator characters.
959 If Iso639Language is FALSE, then is string contains one or more
960 RFC 4646 language codes separated by ';'.
961 @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE
962 is defined in "Related Definitions".
963 @param UnicodeString A pointer to the Unicode string to add.
964 @param Iso639Language Specifies the supported language code format. If it is TRUE,
965 then Language and SupportedLanguages follow ISO 639-2 language code format.
966 Otherwise, they follow RFC 4646 language code format.
968 @retval EFI_SUCCESS The Unicode string that matches the language specified by
969 Language was found in the table of Unicode strings UnicodeStringTable,
970 and it was returned in UnicodeString.
971 @retval EFI_INVALID_PARAMETER Language is NULL.
972 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
973 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
974 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
975 @retval EFI_ALREADY_STARTED A Unicode string with language Language is already present in
977 @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another Unicode string UnicodeStringTable.
978 @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages.
984 IN CONST CHAR8
*Language
,
985 IN CONST CHAR8
*SupportedLanguages
,
986 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
987 IN CONST CHAR16
*UnicodeString
,
988 IN BOOLEAN Iso639Language
991 UINTN NumberOfEntries
;
992 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
993 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
994 UINTN UnicodeStringLength
;
997 CHAR8
*LanguageString
;
1000 // Make sure the parameter are valid
1002 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
1003 return EFI_INVALID_PARAMETER
;
1007 // If there are no supported languages, then a Unicode String can not be added
1009 if (SupportedLanguages
== NULL
) {
1010 return EFI_UNSUPPORTED
;
1014 // If the Unicode String is empty, then a Unicode String can not be added
1016 if (UnicodeString
[0] == 0) {
1017 return EFI_INVALID_PARAMETER
;
1021 // Make sure Language is a member of SupportedLanguages
1024 while (*SupportedLanguages
!= 0) {
1025 if (Iso639Language
) {
1026 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
1030 SupportedLanguages
+= 3;
1032 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
1033 if (AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) {
1037 SupportedLanguages
+= Index
;
1038 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
1043 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
1046 return EFI_UNSUPPORTED
;
1050 // Determine the size of the Unicode String Table by looking for a NULL Language entry
1052 NumberOfEntries
= 0;
1053 if (*UnicodeStringTable
!= NULL
) {
1054 OldUnicodeStringTable
= *UnicodeStringTable
;
1055 while (OldUnicodeStringTable
->Language
!= NULL
) {
1056 LanguageString
= OldUnicodeStringTable
->Language
;
1058 while (*LanguageString
!= 0) {
1059 for (Index
= 0; LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
1061 if (AsciiStrnCmp (Language
, LanguageString
, Index
) == 0) {
1062 return EFI_ALREADY_STARTED
;
1064 LanguageString
+= Index
;
1065 for (; *LanguageString
!= 0 && *LanguageString
== ';'; LanguageString
++);
1067 OldUnicodeStringTable
++;
1073 // Allocate space for a new Unicode String Table. It must hold the current number of
1074 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
1077 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
1078 if (NewUnicodeStringTable
== NULL
) {
1079 return EFI_OUT_OF_RESOURCES
;
1083 // If the current Unicode String Table contains any entries, then copy them to the
1084 // newly allocated Unicode String Table.
1086 if (*UnicodeStringTable
!= NULL
) {
1088 NewUnicodeStringTable
,
1089 *UnicodeStringTable
,
1090 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
1095 // Allocate space for a copy of the Language specifier
1097 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (AsciiStrSize(Language
), Language
);
1098 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
1099 gBS
->FreePool (NewUnicodeStringTable
);
1100 return EFI_OUT_OF_RESOURCES
;
1104 // Compute the length of the Unicode String
1106 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++);
1109 // Allocate space for a copy of the Unicode String
1111 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (StrSize (UnicodeString
), UnicodeString
);
1112 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
1113 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
1114 gBS
->FreePool (NewUnicodeStringTable
);
1115 return EFI_OUT_OF_RESOURCES
;
1119 // Mark the end of the Unicode String Table
1121 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
1122 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
1125 // Free the old Unicode String Table
1127 if (*UnicodeStringTable
!= NULL
) {
1128 gBS
->FreePool (*UnicodeStringTable
);
1132 // Point UnicodeStringTable at the newly allocated Unicode String Table
1134 *UnicodeStringTable
= NewUnicodeStringTable
;
1140 This function frees the table of Unicode strings in UnicodeStringTable.
1142 If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.
1143 Otherwise, each language code, and each Unicode string in the Unicode string
1144 table are freed, and EFI_SUCCESS is returned.
1146 @param UnicodeStringTable A pointer to the table of Unicode strings.
1148 @retval EFI_SUCCESS The Unicode string table was freed.
1153 FreeUnicodeStringTable (
1154 IN EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
1160 // If the Unicode String Table is NULL, then it is already freed
1162 if (UnicodeStringTable
== NULL
) {
1167 // Loop through the Unicode String Table until we reach the end of table marker
1169 for (Index
= 0; UnicodeStringTable
[Index
].Language
!= NULL
; Index
++) {
1172 // Free the Language string from the Unicode String Table
1174 gBS
->FreePool (UnicodeStringTable
[Index
].Language
);
1177 // Free the Unicode String from the Unicode String Table
1179 if (UnicodeStringTable
[Index
].UnicodeString
!= NULL
) {
1180 gBS
->FreePool (UnicodeStringTable
[Index
].UnicodeString
);
1185 // Free the Unicode String Table itself
1187 gBS
->FreePool (UnicodeStringTable
);