2 Mde UEFI library functions.
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
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.
16 // Include common header file for this module.
18 #include "UefiLibInternal.h"
21 Compare whether two names of languages are identical.
23 @param Language1 Name of language 1.
24 @param Language2 Name of language 2.
26 @retval TRUE Language 1 and language 2 are the same.
27 @retval FALSE Language 1 and language 2 are not the same.
32 CompareIso639LanguageCode (
33 IN CONST CHAR8
*Language1
,
34 IN CONST CHAR8
*Language2
40 Name1
= ReadUnaligned24 ((CONST UINT32
*) Language1
);
41 Name2
= ReadUnaligned24 ((CONST UINT32
*) Language2
);
43 return (BOOLEAN
) (Name1
== Name2
);
47 This function searches the list of configuration tables stored in the EFI System
48 Table for a table with a GUID that matches TableGuid. If a match is found,
49 then a pointer to the configuration table is returned in Table, and EFI_SUCCESS
50 is returned. If a matching GUID is not found, then EFI_NOT_FOUND is returned.
52 @param TableGuid Pointer to table's GUID type..
53 @param Table Pointer to the table associated with TableGuid in the EFI System Table.
55 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
56 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
61 EfiGetSystemConfigurationTable (
62 IN EFI_GUID
*TableGuid
,
66 EFI_SYSTEM_TABLE
*SystemTable
;
69 ASSERT (TableGuid
!= NULL
);
70 ASSERT (Table
!= NULL
);
74 for (Index
= 0; Index
< SystemTable
->NumberOfTableEntries
; Index
++) {
75 if (CompareGuid (TableGuid
, &(SystemTable
->ConfigurationTable
[Index
].VendorGuid
))) {
76 *Table
= SystemTable
->ConfigurationTable
[Index
].VendorTable
;
85 This function causes the notification function to be executed for every protocol
86 of type ProtocolGuid instance that exists in the system when this function is
87 invoked. In addition, every time a protocol of type ProtocolGuid instance is
88 installed or reinstalled, the notification function is also executed.
90 @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.
91 @param NotifyTpl Supplies the task priority level of the event notifications.
92 @param NotifyFunction Supplies the function to notify when the event is signaled.
93 @param NotifyContext The context parameter to pass to NotifyFunction.
94 @param Registration A pointer to a memory location to receive the registration value.
96 @return The notification event that was created.
101 EfiCreateProtocolNotifyEvent(
102 IN EFI_GUID
*ProtocolGuid
,
103 IN EFI_TPL NotifyTpl
,
104 IN EFI_EVENT_NOTIFY NotifyFunction
,
105 IN VOID
*NotifyContext
, OPTIONAL
106 OUT VOID
**Registration
116 Status
= gBS
->CreateEvent (
123 ASSERT_EFI_ERROR (Status
);
126 // Register for protocol notifactions on this event
129 Status
= gBS
->RegisterProtocolNotify (
135 ASSERT_EFI_ERROR (Status
);
138 // Kick the event so we will perform an initial pass of
139 // current installed drivers
142 gBS
->SignalEvent (Event
);
147 This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.
148 This event is signaled with EfiNamedEventSignal(). This provide the ability for
149 one or more listeners on the same event named by the GUID specified by Name.
151 @param Name Supplies GUID name of the event.
152 @param NotifyTpl Supplies the task priority level of the event notifications.
153 @param NotifyFunction Supplies the function to notify when the event is signaled.
154 @param NotifyContext The context parameter to pass to NotifyFunction.
155 @param Registration A pointer to a memory location to receive the registration value.
157 @retval EFI_SUCCESS A named event was created.
158 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
163 EfiNamedEventListen (
164 IN CONST EFI_GUID
*Name
,
165 IN EFI_TPL NotifyTpl
,
166 IN EFI_EVENT_NOTIFY NotifyFunction
,
167 IN CONST VOID
*NotifyContext
, OPTIONAL
168 OUT VOID
*Registration OPTIONAL
173 VOID
*RegistrationLocal
;
178 Status
= gBS
->CreateEvent (
182 (VOID
*) NotifyContext
,
185 ASSERT_EFI_ERROR (Status
);
188 // The Registration is not optional to RegisterProtocolNotify().
189 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.
191 if (Registration
!= NULL
) {
192 RegistrationLocal
= Registration
;
194 RegistrationLocal
= &RegistrationLocal
;
198 // Register for an installation of protocol interface
201 Status
= gBS
->RegisterProtocolNotify (
206 ASSERT_EFI_ERROR (Status
);
212 This function signals the named event specified by Name. The named event must
213 have been created with EfiNamedEventListen().
215 @param Name Supplies GUID name of the event.
217 @retval EFI_SUCCESS A named event was signaled.
218 @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event.
223 EfiNamedEventSignal (
224 IN CONST EFI_GUID
*Name
231 Status
= gBS
->InstallProtocolInterface (
234 EFI_NATIVE_INTERFACE
,
237 ASSERT_EFI_ERROR (Status
);
239 Status
= gBS
->UninstallProtocolInterface (
244 ASSERT_EFI_ERROR (Status
);
250 Returns the current TPL.
252 This function returns the current TPL. There is no EFI service to directly
253 retrieve the current TPL. Instead, the RaiseTPL() function is used to raise
254 the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level
255 can then immediately be restored back to the current TPL level with a call
260 @retvale EFI_TPL The current TPL.
271 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
272 gBS
->RestoreTPL (Tpl
);
279 This function initializes a basic mutual exclusion lock to the released state
280 and returns the lock. Each lock provides mutual exclusion access at its task
281 priority level. Since there is no preemption or multiprocessor support in EFI,
282 acquiring the lock only consists of raising to the locks TPL.
284 @param Lock A pointer to the lock data structure to initialize.
285 @param Priority EFI TPL associated with the lock.
293 IN OUT EFI_LOCK
*Lock
,
297 ASSERT (Lock
!= NULL
);
298 ASSERT (Priority
<= TPL_HIGH_LEVEL
);
300 Lock
->Tpl
= Priority
;
301 Lock
->OwnerTpl
= TPL_APPLICATION
;
302 Lock
->Lock
= EfiLockReleased
;
307 This function raises the system's current task priority level to the task
308 priority level of the mutual exclusion lock. Then, it places the lock in the
311 @param Priority The task priority level of the lock.
320 ASSERT (Lock
!= NULL
);
321 ASSERT (Lock
->Lock
== EfiLockReleased
);
323 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
324 Lock
->Lock
= EfiLockAcquired
;
328 This function raises the system's current task priority level to the task
329 priority level of the mutual exclusion lock. Then, it attempts to place the
330 lock in the acquired state.
332 @param Lock A pointer to the lock to acquire.
334 @retval EFI_SUCCESS The lock was acquired.
335 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
340 EfiAcquireLockOrFail (
345 ASSERT (Lock
!= NULL
);
346 ASSERT (Lock
->Lock
!= EfiLockUninitialized
);
348 if (Lock
->Lock
== EfiLockAcquired
) {
350 // Lock is already owned, so bail out
352 return EFI_ACCESS_DENIED
;
355 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
357 Lock
->Lock
= EfiLockAcquired
;
363 This function transitions a mutual exclusion lock from the acquired state to
364 the released state, and restores the system's task priority level to its
367 @param Lock A pointer to the lock to release.
378 ASSERT (Lock
!= NULL
);
379 ASSERT (Lock
->Lock
== EfiLockAcquired
);
381 Tpl
= Lock
->OwnerTpl
;
383 Lock
->Lock
= EfiLockReleased
;
385 gBS
->RestoreTPL (Tpl
);
389 Tests whether a controller handle is being managed by a specific driver.
391 This function tests whether the driver specified by DriverBindingHandle is
392 currently managing the controller specified by ControllerHandle. This test
393 is performed by evaluating if the the protocol specified by ProtocolGuid is
394 present on ControllerHandle and is was opened by DriverBindingHandle with an
395 attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
396 If ProtocolGuid is NULL, then ASSERT().
398 @param ControllerHandle A handle for a controller to test.
399 @param DriverBindingHandle Specifies the driver binding handle for the
401 @param ProtocolGuid Specifies the protocol that the driver specified
402 by DriverBindingHandle opens in its Start()
405 @retval EFI_SUCCESS ControllerHandle is managed by the driver
406 specifed by DriverBindingHandle.
407 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
408 specifed by DriverBindingHandle.
413 EfiTestManagedDevice (
414 IN CONST EFI_HANDLE ControllerHandle
,
415 IN CONST EFI_HANDLE DriverBindingHandle
,
416 IN CONST EFI_GUID
*ProtocolGuid
420 VOID
*ManagedInterface
;
422 ASSERT (ProtocolGuid
!= NULL
);
424 Status
= gBS
->OpenProtocol (
426 (EFI_GUID
*) ProtocolGuid
,
430 EFI_OPEN_PROTOCOL_BY_DRIVER
432 if (!EFI_ERROR (Status
)) {
435 (EFI_GUID
*) ProtocolGuid
,
439 return EFI_UNSUPPORTED
;
442 if (Status
!= EFI_ALREADY_STARTED
) {
443 return EFI_UNSUPPORTED
;
450 Tests whether a child handle is a child device of the controller.
452 This function tests whether ChildHandle is one of the children of
453 ControllerHandle. This test is performed by checking to see if the protocol
454 specified by ProtocolGuid is present on ControllerHandle and opened by
455 ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
456 If ProtocolGuid is NULL, then ASSERT().
458 @param ControllerHandle A handle for a (parent) controller to test.
459 @param ChildHandle A child handle to test.
460 @param ConsumsedGuid Supplies the protocol that the child controller
461 opens on its parent controller.
463 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
464 @retval EFI_UNSUPPORTED ChildHandle is not a child of the
471 IN CONST EFI_HANDLE ControllerHandle
,
472 IN CONST EFI_HANDLE ChildHandle
,
473 IN CONST EFI_GUID
*ProtocolGuid
477 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
481 ASSERT (ProtocolGuid
!= NULL
);
484 // Retrieve the list of agents that are consuming the specific protocol
485 // on ControllerHandle.
487 Status
= gBS
->OpenProtocolInformation (
489 (EFI_GUID
*) ProtocolGuid
,
493 if (EFI_ERROR (Status
)) {
494 return EFI_UNSUPPORTED
;
498 // Inspect if ChildHandle is one of the agents.
500 Status
= EFI_UNSUPPORTED
;
501 for (Index
= 0; Index
< EntryCount
; Index
++) {
502 if ((OpenInfoBuffer
[Index
].ControllerHandle
== ChildHandle
) &&
503 (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
504 Status
= EFI_SUCCESS
;
509 FreePool (OpenInfoBuffer
);
514 This function looks up a Unicode string in UnicodeStringTable.
515 If Language is a member of SupportedLanguages and a Unicode
516 string is found in UnicodeStringTable that matches the
517 language code specified by Language, then it is returned in
520 @param Language A pointer to the ISO 639-2
521 language code for the Unicode
522 string to look up and return.
524 @param SupportedLanguages A pointer to the set of ISO
526 codes that the Unicode string
527 table supports. Language must
528 be a member of this set.
530 @param UnicodeStringTable A pointer to the table of
533 @param UnicodeString A pointer to the Unicode
534 string from UnicodeStringTable
535 that matches the language
536 specified by Language.
538 @retval EFI_SUCCESS The Unicode string that
539 matches the language specified
540 by Language was found in the
541 table of Unicoide strings
542 UnicodeStringTable, and it was
543 returned in UnicodeString.
545 @retval EFI_INVALID_PARAMETER Language is NULL.
547 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
548 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
550 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
552 @retval EFI_UNSUPPORTED The language specified by
553 Language is not a member
554 ofSupportedLanguages.
556 @retval EFI_UNSUPPORTED The language specified by
557 Language is not supported by
563 LookupUnicodeString (
564 IN CONST CHAR8
*Language
,
565 IN CONST CHAR8
*SupportedLanguages
,
566 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
567 OUT CHAR16
**UnicodeString
571 // Make sure the parameters are valid
573 if (Language
== NULL
|| UnicodeString
== NULL
) {
574 return EFI_INVALID_PARAMETER
;
578 // If there are no supported languages, or the Unicode String Table is empty, then the
579 // Unicode String specified by Language is not supported by this Unicode String Table
581 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
582 return EFI_UNSUPPORTED
;
586 // Make sure Language is in the set of Supported Languages
588 while (*SupportedLanguages
!= 0) {
589 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
592 // Search the Unicode String Table for the matching Language specifier
594 while (UnicodeStringTable
->Language
!= NULL
) {
595 if (CompareIso639LanguageCode (Language
, UnicodeStringTable
->Language
)) {
598 // A matching string was found, so return it
600 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
604 UnicodeStringTable
++;
607 return EFI_UNSUPPORTED
;
610 SupportedLanguages
+= 3;
613 return EFI_UNSUPPORTED
;
619 This function looks up a Unicode string in UnicodeStringTable.
620 If Language is a member of SupportedLanguages and a Unicode
621 string is found in UnicodeStringTable that matches the
622 language code specified by Language, then it is returned in
625 @param Language A pointer to the ISO 639-2 or
626 RFC 3066 language code for the
627 Unicode string to look up and
630 @param SupportedLanguages A pointer to the set of ISO
631 639-2 or RFC 3066 language
632 codes that the Unicode string
633 table supports. Language must
634 be a member of this set.
636 @param UnicodeStringTable A pointer to the table of
639 @param UnicodeString A pointer to the Unicode
640 string from UnicodeStringTable
641 that matches the language
642 specified by Language.
644 @param Iso639Language Specify the language code
645 format supported. If true,
646 then the format follow ISO
647 639-2. If false, then it
650 @retval EFI_SUCCESS The Unicode string that
651 matches the language specified
652 by Language was found in the
653 table of Unicoide strings
654 UnicodeStringTable, and it was
655 returned in UnicodeString.
657 @retval EFI_INVALID_PARAMETER Language is NULL.
659 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
661 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
663 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
665 @retval EFI_UNSUPPORTED The language specified by
666 Language is not a member
667 ofSupportedLanguages.
669 @retval EFI_UNSUPPORTED The language specified by
670 Language is not supported by
676 LookupUnicodeString2 (
677 IN CONST CHAR8
*Language
,
678 IN CONST CHAR8
*SupportedLanguages
,
679 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
680 OUT CHAR16
**UnicodeString
,
681 IN BOOLEAN Iso639Language
686 CHAR8
*LanguageString
;
689 // Make sure the parameters are valid
691 if (Language
== NULL
|| UnicodeString
== NULL
) {
692 return EFI_INVALID_PARAMETER
;
696 // If there are no supported languages, or the Unicode String Table is empty, then the
697 // Unicode String specified by Language is not supported by this Unicode String Table
699 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
700 return EFI_UNSUPPORTED
;
704 // Make sure Language is in the set of Supported Languages
707 while (*SupportedLanguages
!= 0) {
708 if (Iso639Language
) {
709 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
713 SupportedLanguages
+= 3;
715 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
716 if ((AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) && (Language
[Index
] == 0)) {
720 SupportedLanguages
+= Index
;
721 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
726 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
729 return EFI_UNSUPPORTED
;
733 // Search the Unicode String Table for the matching Language specifier
735 while (UnicodeStringTable
->Language
!= NULL
) {
736 LanguageString
= UnicodeStringTable
->Language
;
737 while (0 != *LanguageString
) {
738 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
739 if (AsciiStrnCmp(LanguageString
, Language
, Index
) == 0) {
740 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
743 LanguageString
+= Index
;
744 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] == ';'; Index
++);
746 UnicodeStringTable
++;
749 return EFI_UNSUPPORTED
;
755 This function adds a Unicode string to UnicodeStringTable.
756 If Language is a member of SupportedLanguages then
757 UnicodeString is added to UnicodeStringTable. New buffers are
758 allocated for both Language and UnicodeString. The contents
759 of Language and UnicodeString are copied into these new
760 buffers. These buffers are automatically freed when
761 FreeUnicodeStringTable() is called.
763 @param Language A pointer to the ISO 639-2
764 language code for the Unicode
767 @param SupportedLanguages A pointer to the set of ISO
768 639-2 language codes that the
769 Unicode string table supports.
770 Language must be a member of
773 @param UnicodeStringTable A pointer to the table of
776 @param UnicodeString A pointer to the Unicode
779 @retval EFI_SUCCESS The Unicode string that
780 matches the language specified
781 by Language was found in the
782 table of Unicode strings
783 UnicodeStringTable, and it was
784 returned in UnicodeString.
786 @retval EFI_INVALID_PARAMETER Language is NULL.
788 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
790 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
792 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
794 @retval EFI_ALREADY_STARTED A Unicode string with language
795 Language is already present in
798 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
799 add another Unicode string to
802 @retval EFI_UNSUPPORTED The language specified by
803 Language is not a member of
810 IN CONST CHAR8
*Language
,
811 IN CONST CHAR8
*SupportedLanguages
,
812 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
813 IN CONST CHAR16
*UnicodeString
816 UINTN NumberOfEntries
;
817 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
818 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
819 UINTN UnicodeStringLength
;
822 // Make sure the parameter are valid
824 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
825 return EFI_INVALID_PARAMETER
;
829 // If there are no supported languages, then a Unicode String can not be added
831 if (SupportedLanguages
== NULL
) {
832 return EFI_UNSUPPORTED
;
836 // If the Unicode String is empty, then a Unicode String can not be added
838 if (UnicodeString
[0] == 0) {
839 return EFI_INVALID_PARAMETER
;
843 // Make sure Language is a member of SupportedLanguages
845 while (*SupportedLanguages
!= 0) {
846 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
849 // Determine the size of the Unicode String Table by looking for a NULL Language entry
852 if (*UnicodeStringTable
!= NULL
) {
853 OldUnicodeStringTable
= *UnicodeStringTable
;
854 while (OldUnicodeStringTable
->Language
!= NULL
) {
855 if (CompareIso639LanguageCode (Language
, OldUnicodeStringTable
->Language
)) {
856 return EFI_ALREADY_STARTED
;
859 OldUnicodeStringTable
++;
865 // Allocate space for a new Unicode String Table. It must hold the current number of
866 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
869 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
870 if (NewUnicodeStringTable
== NULL
) {
871 return EFI_OUT_OF_RESOURCES
;
875 // If the current Unicode String Table contains any entries, then copy them to the
876 // newly allocated Unicode String Table.
878 if (*UnicodeStringTable
!= NULL
) {
880 NewUnicodeStringTable
,
882 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
887 // Allocate space for a copy of the Language specifier
889 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (3, Language
);
890 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
891 gBS
->FreePool (NewUnicodeStringTable
);
892 return EFI_OUT_OF_RESOURCES
;
896 // Compute the length of the Unicode String
898 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++)
902 // Allocate space for a copy of the Unicode String
904 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (
905 (UnicodeStringLength
+ 1) * sizeof (CHAR16
),
908 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
909 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
910 gBS
->FreePool (NewUnicodeStringTable
);
911 return EFI_OUT_OF_RESOURCES
;
915 // Mark the end of the Unicode String Table
917 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
918 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
921 // Free the old Unicode String Table
923 if (*UnicodeStringTable
!= NULL
) {
924 gBS
->FreePool (*UnicodeStringTable
);
928 // Point UnicodeStringTable at the newly allocated Unicode String Table
930 *UnicodeStringTable
= NewUnicodeStringTable
;
935 SupportedLanguages
+= 3;
938 return EFI_UNSUPPORTED
;
944 This function adds a Unicode string to UnicodeStringTable.
945 If Language is a member of SupportedLanguages then
946 UnicodeString is added to UnicodeStringTable. New buffers are
947 allocated for both Language and UnicodeString. The contents
948 of Language and UnicodeString are copied into these new
949 buffers. These buffers are automatically freed when
950 FreeUnicodeStringTable() is called.
952 @param Language A pointer to the ISO 639-2 or
953 RFC 3066 language code for the
954 Unicode string to add.
956 @param SupportedLanguages A pointer to the set of ISO
957 639-2 or RFC 3.66 language
958 codes that the Unicode string
959 table supports. Language must
960 be a member of this set.
962 @param UnicodeStringTable A pointer to the table of
965 @param UnicodeString A pointer to the Unicode
968 @param Iso639Language Specify the language code
969 format supported. If true,
970 then the format follow ISO
971 639-2. If false, then it
974 @retval EFI_SUCCESS The Unicode string that
975 matches the language specified
976 by Language was found in the
977 table of Unicode strings
978 UnicodeStringTable, and it was
979 returned in UnicodeString.
981 @retval EFI_INVALID_PARAMETER Language is NULL.
983 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
985 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
987 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
989 @retval EFI_ALREADY_STARTED A Unicode string with language
990 Language is already present in
993 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
994 add another Unicode string to
997 @retval EFI_UNSUPPORTED The language specified by
998 Language is not a member of
1005 IN CONST CHAR8
*Language
,
1006 IN CONST CHAR8
*SupportedLanguages
,
1007 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
1008 IN CONST CHAR16
*UnicodeString
,
1009 IN BOOLEAN Iso639Language
1012 UINTN NumberOfEntries
;
1013 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
1014 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
1015 UINTN UnicodeStringLength
;
1018 CHAR8
*LanguageString
;
1021 // Make sure the parameter are valid
1023 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
1024 return EFI_INVALID_PARAMETER
;
1028 // If there are no supported languages, then a Unicode String can not be added
1030 if (SupportedLanguages
== NULL
) {
1031 return EFI_UNSUPPORTED
;
1035 // If the Unicode String is empty, then a Unicode String can not be added
1037 if (UnicodeString
[0] == 0) {
1038 return EFI_INVALID_PARAMETER
;
1042 // Make sure Language is a member of SupportedLanguages
1045 while (*SupportedLanguages
!= 0) {
1046 if (Iso639Language
) {
1047 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
1051 SupportedLanguages
+= 3;
1053 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
1054 if (AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) {
1058 SupportedLanguages
+= Index
;
1059 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
1064 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
1067 return EFI_UNSUPPORTED
;
1071 // Determine the size of the Unicode String Table by looking for a NULL Language entry
1073 NumberOfEntries
= 0;
1074 if (*UnicodeStringTable
!= NULL
) {
1075 OldUnicodeStringTable
= *UnicodeStringTable
;
1076 while (OldUnicodeStringTable
->Language
!= NULL
) {
1077 LanguageString
= OldUnicodeStringTable
->Language
;
1079 while (*LanguageString
) {
1080 for (Index
= 0; LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
1082 if (AsciiStrnCmp (Language
, LanguageString
, Index
) == 0) {
1083 return EFI_ALREADY_STARTED
;
1085 LanguageString
+= Index
;
1086 for (; *LanguageString
!= 0 && *LanguageString
== ';'; LanguageString
++);
1088 OldUnicodeStringTable
++;
1094 // Allocate space for a new Unicode String Table. It must hold the current number of
1095 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
1098 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
1099 if (NewUnicodeStringTable
== NULL
) {
1100 return EFI_OUT_OF_RESOURCES
;
1104 // If the current Unicode String Table contains any entries, then copy them to the
1105 // newly allocated Unicode String Table.
1107 if (*UnicodeStringTable
!= NULL
) {
1109 NewUnicodeStringTable
,
1110 *UnicodeStringTable
,
1111 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
1116 // Allocate space for a copy of the Language specifier
1118 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (AsciiStrSize(Language
), Language
);
1119 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
1120 gBS
->FreePool (NewUnicodeStringTable
);
1121 return EFI_OUT_OF_RESOURCES
;
1125 // Compute the length of the Unicode String
1127 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++);
1130 // Allocate space for a copy of the Unicode String
1132 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (StrSize (UnicodeString
), UnicodeString
);
1133 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
1134 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
1135 gBS
->FreePool (NewUnicodeStringTable
);
1136 return EFI_OUT_OF_RESOURCES
;
1140 // Mark the end of the Unicode String Table
1142 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
1143 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
1146 // Free the old Unicode String Table
1148 if (*UnicodeStringTable
!= NULL
) {
1149 gBS
->FreePool (*UnicodeStringTable
);
1153 // Point UnicodeStringTable at the newly allocated Unicode String Table
1155 *UnicodeStringTable
= NewUnicodeStringTable
;
1161 This function frees the table of Unicode strings in UnicodeStringTable.
1162 If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.
1163 Otherwise, each language code, and each Unicode string in the Unicode string
1164 table are freed, and EFI_SUCCESS is returned.
1166 @param UnicodeStringTable A pointer to the table of Unicode strings.
1168 @retval EFI_SUCCESS The Unicode string table was freed.
1173 FreeUnicodeStringTable (
1174 IN EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
1180 // If the Unicode String Table is NULL, then it is already freed
1182 if (UnicodeStringTable
== NULL
) {
1187 // Loop through the Unicode String Table until we reach the end of table marker
1189 for (Index
= 0; UnicodeStringTable
[Index
].Language
!= NULL
; Index
++) {
1192 // Free the Language string from the Unicode String Table
1194 gBS
->FreePool (UnicodeStringTable
[Index
].Language
);
1197 // Free the Unicode String from the Unicode String Table
1199 if (UnicodeStringTable
[Index
].UnicodeString
!= NULL
) {
1200 gBS
->FreePool (UnicodeStringTable
[Index
].UnicodeString
);
1205 // Free the Unicode String Table itself
1207 gBS
->FreePool (UnicodeStringTable
);