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 "UefiLibInternal.h"
19 Compare whether two names of languages are identical.
21 @param Language1 Name of language 1.
22 @param Language2 Name of language 2.
24 @retval TRUE Language 1 and language 2 are the same.
25 @retval FALSE Language 1 and language 2 are not the same.
29 CompareIso639LanguageCode (
30 IN CONST CHAR8
*Language1
,
31 IN CONST CHAR8
*Language2
37 Name1
= ReadUnaligned24 ((CONST UINT32
*) Language1
);
38 Name2
= ReadUnaligned24 ((CONST UINT32
*) Language2
);
40 return (BOOLEAN
) (Name1
== Name2
);
44 This function searches the list of configuration tables stored in the EFI System
45 Table for a table with a GUID that matches TableGuid. If a match is found,
46 then a pointer to the configuration table is returned in Table, and EFI_SUCCESS
47 is returned. If a matching GUID is not found, then EFI_NOT_FOUND is returned.
48 If TableGuid is NULL, then ASSERT().
49 If Table is NULL, then ASSERT().
51 @param TableGuid Pointer to table's GUID type..
52 @param Table Pointer to the table associated with TableGuid in the EFI System Table.
54 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
55 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
60 EfiGetSystemConfigurationTable (
61 IN EFI_GUID
*TableGuid
,
65 EFI_SYSTEM_TABLE
*SystemTable
;
68 ASSERT (TableGuid
!= NULL
);
69 ASSERT (Table
!= NULL
);
73 for (Index
= 0; Index
< SystemTable
->NumberOfTableEntries
; Index
++) {
74 if (CompareGuid (TableGuid
, &(SystemTable
->ConfigurationTable
[Index
].VendorGuid
))) {
75 *Table
= SystemTable
->ConfigurationTable
[Index
].VendorTable
;
84 This function causes the notification function to be executed for every protocol
85 of type ProtocolGuid instance that exists in the system when this function is
86 invoked. In addition, every time a protocol of type ProtocolGuid instance is
87 installed or reinstalled, the notification function is also executed.
89 @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.
90 @param NotifyTpl Supplies the task priority level of the event notifications.
91 @param NotifyFunction Supplies the function to notify when the event is signaled.
92 @param NotifyContext The context parameter to pass to NotifyFunction.
93 @param Registration A pointer to a memory location to receive the registration value.
95 @return The notification event that was created.
100 EfiCreateProtocolNotifyEvent(
101 IN EFI_GUID
*ProtocolGuid
,
102 IN EFI_TPL NotifyTpl
,
103 IN EFI_EVENT_NOTIFY NotifyFunction
,
104 IN VOID
*NotifyContext
, OPTIONAL
105 OUT VOID
**Registration
115 Status
= gBS
->CreateEvent (
122 ASSERT_EFI_ERROR (Status
);
125 // Register for protocol notifactions on this event
128 Status
= gBS
->RegisterProtocolNotify (
134 ASSERT_EFI_ERROR (Status
);
137 // Kick the event so we will perform an initial pass of
138 // current installed drivers
141 gBS
->SignalEvent (Event
);
146 This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.
147 This event is signaled with EfiNamedEventSignal(). This provide the ability for
148 one or more listeners on the same event named by the GUID specified by Name.
149 If Name is NULL, then ASSERT().
150 If NotifyTpl is not a legal TPL value, then ASSERT().
151 If NotifyFunction is NULL, then ASSERT().
153 @param Name Supplies GUID name of the event.
154 @param NotifyTpl Supplies the task priority level of the event notifications.
155 @param NotifyFunction Supplies the function to notify when the event is signaled.
156 @param NotifyContext The context parameter to pass to NotifyFunction.
157 @param Registration A pointer to a memory location to receive the registration value.
159 @retval EFI_SUCCESS A named event was created.
160 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.
165 EfiNamedEventListen (
166 IN CONST EFI_GUID
*Name
,
167 IN EFI_TPL NotifyTpl
,
168 IN EFI_EVENT_NOTIFY NotifyFunction
,
169 IN CONST VOID
*NotifyContext
, OPTIONAL
170 OUT VOID
*Registration OPTIONAL
175 VOID
*RegistrationLocal
;
177 ASSERT (Name
!= NULL
);
178 ASSERT (NotifyFunction
!= NULL
);
179 ASSERT (NotifyTpl
<= TPL_HIGH_LEVEL
);
184 Status
= gBS
->CreateEvent (
188 (VOID
*) NotifyContext
,
191 ASSERT_EFI_ERROR (Status
);
194 // The Registration is not optional to RegisterProtocolNotify().
195 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.
197 if (Registration
!= NULL
) {
198 RegistrationLocal
= Registration
;
200 RegistrationLocal
= &RegistrationLocal
;
204 // Register for an installation of protocol interface
207 Status
= gBS
->RegisterProtocolNotify (
212 ASSERT_EFI_ERROR (Status
);
218 This function signals the named event specified by Name. The named event must
219 have been created with EfiNamedEventListen().
221 @param Name Supplies GUID name of the event.
223 @retval EFI_SUCCESS A named event was signaled.
224 @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event.
229 EfiNamedEventSignal (
230 IN CONST EFI_GUID
*Name
237 Status
= gBS
->InstallProtocolInterface (
240 EFI_NATIVE_INTERFACE
,
243 ASSERT_EFI_ERROR (Status
);
245 Status
= gBS
->UninstallProtocolInterface (
250 ASSERT_EFI_ERROR (Status
);
256 Returns the current TPL.
258 This function returns the current TPL. There is no EFI service to directly
259 retrieve the current TPL. Instead, the RaiseTPL() function is used to raise
260 the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level
261 can then immediately be restored back to the current TPL level with a call
266 @retval EFI_TPL The current TPL.
277 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
278 gBS
->RestoreTPL (Tpl
);
285 This function initializes a basic mutual exclusion lock to the released state
286 and returns the lock. Each lock provides mutual exclusion access at its task
287 priority level. Since there is no preemption or multiprocessor support in EFI,
288 acquiring the lock only consists of raising to the locks TPL.
289 If Lock is NULL, then ASSERT().
290 If Priority is not a valid TPL value, then ASSERT().
292 @param Lock A pointer to the lock data structure to initialize.
293 @param Priority EFI TPL associated with the lock.
301 IN OUT EFI_LOCK
*Lock
,
305 ASSERT (Lock
!= NULL
);
306 ASSERT (Priority
<= TPL_HIGH_LEVEL
);
308 Lock
->Tpl
= Priority
;
309 Lock
->OwnerTpl
= TPL_APPLICATION
;
310 Lock
->Lock
= EfiLockReleased
;
315 This function raises the system's current task priority level to the task
316 priority level of the mutual exclusion lock. Then, it places the lock in the
318 If Lock is NULL, then ASSERT().
319 If Lock is not initialized, then ASSERT().
320 If Lock is already in the acquired state, then ASSERT().
322 @param Lock The task lock with priority level.
331 ASSERT (Lock
!= NULL
);
332 ASSERT (Lock
->Lock
== EfiLockReleased
);
334 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
335 Lock
->Lock
= EfiLockAcquired
;
339 This function raises the system's current task priority level to the task
340 priority level of the mutual exclusion lock. Then, it attempts to place the
341 lock in the acquired state.
343 @param Lock A pointer to the lock to acquire.
345 @retval EFI_SUCCESS The lock was acquired.
346 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
351 EfiAcquireLockOrFail (
356 ASSERT (Lock
!= NULL
);
357 ASSERT (Lock
->Lock
!= EfiLockUninitialized
);
359 if (Lock
->Lock
== EfiLockAcquired
) {
361 // Lock is already owned, so bail out
363 return EFI_ACCESS_DENIED
;
366 Lock
->OwnerTpl
= gBS
->RaiseTPL (Lock
->Tpl
);
368 Lock
->Lock
= EfiLockAcquired
;
374 This function transitions a mutual exclusion lock from the acquired state to
375 the released state, and restores the system's task priority level to its
378 @param Lock A pointer to the lock to release.
389 ASSERT (Lock
!= NULL
);
390 ASSERT (Lock
->Lock
== EfiLockAcquired
);
392 Tpl
= Lock
->OwnerTpl
;
394 Lock
->Lock
= EfiLockReleased
;
396 gBS
->RestoreTPL (Tpl
);
400 Tests whether a controller handle is being managed by a specific driver.
402 This function tests whether the driver specified by DriverBindingHandle is
403 currently managing the controller specified by ControllerHandle. This test
404 is performed by evaluating if the the protocol specified by ProtocolGuid is
405 present on ControllerHandle and is was opened by DriverBindingHandle with an
406 attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
407 If ProtocolGuid is NULL, then ASSERT().
409 @param ControllerHandle A handle for a controller to test.
410 @param DriverBindingHandle Specifies the driver binding handle for the
412 @param ProtocolGuid Specifies the protocol that the driver specified
413 by DriverBindingHandle opens in its Start()
416 @retval EFI_SUCCESS ControllerHandle is managed by the driver
417 specifed by DriverBindingHandle.
418 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
419 specifed by DriverBindingHandle.
424 EfiTestManagedDevice (
425 IN CONST EFI_HANDLE ControllerHandle
,
426 IN CONST EFI_HANDLE DriverBindingHandle
,
427 IN CONST EFI_GUID
*ProtocolGuid
431 VOID
*ManagedInterface
;
433 ASSERT (ProtocolGuid
!= NULL
);
435 Status
= gBS
->OpenProtocol (
437 (EFI_GUID
*) ProtocolGuid
,
441 EFI_OPEN_PROTOCOL_BY_DRIVER
443 if (!EFI_ERROR (Status
)) {
446 (EFI_GUID
*) ProtocolGuid
,
450 return EFI_UNSUPPORTED
;
453 if (Status
!= EFI_ALREADY_STARTED
) {
454 return EFI_UNSUPPORTED
;
461 Tests whether a child handle is a child device of the controller.
463 This function tests whether ChildHandle is one of the children of
464 ControllerHandle. This test is performed by checking to see if the protocol
465 specified by ProtocolGuid is present on ControllerHandle and opened by
466 ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
467 If ProtocolGuid is NULL, then ASSERT().
469 @param ControllerHandle A handle for a (parent) controller to test.
470 @param ChildHandle A child handle to test.
471 @param ProtocolGuid Supplies the protocol that the child controller
472 opens on its parent controller.
474 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
475 @retval EFI_UNSUPPORTED ChildHandle is not a child of the
482 IN CONST EFI_HANDLE ControllerHandle
,
483 IN CONST EFI_HANDLE ChildHandle
,
484 IN CONST EFI_GUID
*ProtocolGuid
488 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
492 ASSERT (ProtocolGuid
!= NULL
);
495 // Retrieve the list of agents that are consuming the specific protocol
496 // on ControllerHandle.
498 Status
= gBS
->OpenProtocolInformation (
500 (EFI_GUID
*) ProtocolGuid
,
504 if (EFI_ERROR (Status
)) {
505 return EFI_UNSUPPORTED
;
509 // Inspect if ChildHandle is one of the agents.
511 Status
= EFI_UNSUPPORTED
;
512 for (Index
= 0; Index
< EntryCount
; Index
++) {
513 if ((OpenInfoBuffer
[Index
].ControllerHandle
== ChildHandle
) &&
514 (OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
515 Status
= EFI_SUCCESS
;
520 FreePool (OpenInfoBuffer
);
525 This function looks up a Unicode string in UnicodeStringTable.
526 If Language is a member of SupportedLanguages and a Unicode
527 string is found in UnicodeStringTable that matches the
528 language code specified by Language, then it is returned in
531 @param Language A pointer to the ISO 639-2
532 language code for the Unicode
533 string to look up and return.
535 @param SupportedLanguages A pointer to the set of ISO
537 codes that the Unicode string
538 table supports. Language must
539 be a member of this set.
541 @param UnicodeStringTable A pointer to the table of
544 @param UnicodeString A pointer to the Unicode
545 string from UnicodeStringTable
546 that matches the language
547 specified by Language.
549 @retval EFI_SUCCESS The Unicode string that
550 matches the language specified
551 by Language was found in the
552 table of Unicoide strings
553 UnicodeStringTable, and it was
554 returned in UnicodeString.
556 @retval EFI_INVALID_PARAMETER Language is NULL.
558 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
559 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
561 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
563 @retval EFI_UNSUPPORTED The language specified by
564 Language is not a member
565 ofSupportedLanguages.
567 @retval EFI_UNSUPPORTED The language specified by
568 Language is not supported by
574 LookupUnicodeString (
575 IN CONST CHAR8
*Language
,
576 IN CONST CHAR8
*SupportedLanguages
,
577 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
578 OUT CHAR16
**UnicodeString
582 // Make sure the parameters are valid
584 if (Language
== NULL
|| UnicodeString
== NULL
) {
585 return EFI_INVALID_PARAMETER
;
589 // If there are no supported languages, or the Unicode String Table is empty, then the
590 // Unicode String specified by Language is not supported by this Unicode String Table
592 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
593 return EFI_UNSUPPORTED
;
597 // Make sure Language is in the set of Supported Languages
599 while (*SupportedLanguages
!= 0) {
600 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
603 // Search the Unicode String Table for the matching Language specifier
605 while (UnicodeStringTable
->Language
!= NULL
) {
606 if (CompareIso639LanguageCode (Language
, UnicodeStringTable
->Language
)) {
609 // A matching string was found, so return it
611 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
615 UnicodeStringTable
++;
618 return EFI_UNSUPPORTED
;
621 SupportedLanguages
+= 3;
624 return EFI_UNSUPPORTED
;
630 This function looks up a Unicode string in UnicodeStringTable.
631 If Language is a member of SupportedLanguages and a Unicode
632 string is found in UnicodeStringTable that matches the
633 language code specified by Language, then it is returned in
636 @param Language A pointer to the ISO 639-2 or
637 RFC 3066 language code for the
638 Unicode string to look up and
641 @param SupportedLanguages A pointer to the set of ISO
642 639-2 or RFC 3066 language
643 codes that the Unicode string
644 table supports. Language must
645 be a member of this set.
647 @param UnicodeStringTable A pointer to the table of
650 @param UnicodeString A pointer to the Unicode
651 string from UnicodeStringTable
652 that matches the language
653 specified by Language.
655 @param Iso639Language Specify the language code
656 format supported. If true,
657 then the format follow ISO
658 639-2. If false, then it
661 @retval EFI_SUCCESS The Unicode string that
662 matches the language specified
663 by Language was found in the
664 table of Unicoide strings
665 UnicodeStringTable, and it was
666 returned in UnicodeString.
668 @retval EFI_INVALID_PARAMETER Language is NULL.
670 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
672 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
674 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
676 @retval EFI_UNSUPPORTED The language specified by
677 Language is not a member
678 ofSupportedLanguages.
680 @retval EFI_UNSUPPORTED The language specified by
681 Language is not supported by
688 LookupUnicodeString2 (
689 IN CONST CHAR8
*Language
,
690 IN CONST CHAR8
*SupportedLanguages
,
691 IN CONST EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
,
692 OUT CHAR16
**UnicodeString
,
693 IN BOOLEAN Iso639Language
698 CHAR8
*LanguageString
;
701 // Make sure the parameters are valid
703 if (Language
== NULL
|| UnicodeString
== NULL
) {
704 return EFI_INVALID_PARAMETER
;
708 // If there are no supported languages, or the Unicode String Table is empty, then the
709 // Unicode String specified by Language is not supported by this Unicode String Table
711 if (SupportedLanguages
== NULL
|| UnicodeStringTable
== NULL
) {
712 return EFI_UNSUPPORTED
;
716 // Make sure Language is in the set of Supported Languages
719 while (*SupportedLanguages
!= 0) {
720 if (Iso639Language
) {
721 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
725 SupportedLanguages
+= 3;
727 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
728 if ((AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) && (Language
[Index
] == 0)) {
732 SupportedLanguages
+= Index
;
733 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
738 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
741 return EFI_UNSUPPORTED
;
745 // Search the Unicode String Table for the matching Language specifier
747 while (UnicodeStringTable
->Language
!= NULL
) {
748 LanguageString
= UnicodeStringTable
->Language
;
749 while (0 != *LanguageString
) {
750 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
751 if (AsciiStrnCmp(LanguageString
, Language
, Index
) == 0) {
752 *UnicodeString
= UnicodeStringTable
->UnicodeString
;
755 LanguageString
+= Index
;
756 for (Index
= 0 ;LanguageString
[Index
] != 0 && LanguageString
[Index
] == ';'; Index
++);
758 UnicodeStringTable
++;
761 return EFI_UNSUPPORTED
;
767 This function adds a Unicode string to UnicodeStringTable.
768 If Language is a member of SupportedLanguages then
769 UnicodeString is added to UnicodeStringTable. New buffers are
770 allocated for both Language and UnicodeString. The contents
771 of Language and UnicodeString are copied into these new
772 buffers. These buffers are automatically freed when
773 FreeUnicodeStringTable() is called.
775 @param Language A pointer to the ISO 639-2
776 language code for the Unicode
779 @param SupportedLanguages A pointer to the set of ISO
780 639-2 language codes that the
781 Unicode string table supports.
782 Language must be a member of
785 @param UnicodeStringTable A pointer to the table of
788 @param UnicodeString A pointer to the Unicode
791 @retval EFI_SUCCESS The Unicode string that
792 matches the language specified
793 by Language was found in the
794 table of Unicode strings
795 UnicodeStringTable, and it was
796 returned in UnicodeString.
798 @retval EFI_INVALID_PARAMETER Language is NULL.
800 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
802 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
804 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
806 @retval EFI_ALREADY_STARTED A Unicode string with language
807 Language is already present in
810 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
811 add another Unicode string to
814 @retval EFI_UNSUPPORTED The language specified by
815 Language is not a member of
822 IN CONST CHAR8
*Language
,
823 IN CONST CHAR8
*SupportedLanguages
,
824 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
825 IN CONST CHAR16
*UnicodeString
828 UINTN NumberOfEntries
;
829 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
830 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
831 UINTN UnicodeStringLength
;
834 // Make sure the parameter are valid
836 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
837 return EFI_INVALID_PARAMETER
;
841 // If there are no supported languages, then a Unicode String can not be added
843 if (SupportedLanguages
== NULL
) {
844 return EFI_UNSUPPORTED
;
848 // If the Unicode String is empty, then a Unicode String can not be added
850 if (UnicodeString
[0] == 0) {
851 return EFI_INVALID_PARAMETER
;
855 // Make sure Language is a member of SupportedLanguages
857 while (*SupportedLanguages
!= 0) {
858 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
861 // Determine the size of the Unicode String Table by looking for a NULL Language entry
864 if (*UnicodeStringTable
!= NULL
) {
865 OldUnicodeStringTable
= *UnicodeStringTable
;
866 while (OldUnicodeStringTable
->Language
!= NULL
) {
867 if (CompareIso639LanguageCode (Language
, OldUnicodeStringTable
->Language
)) {
868 return EFI_ALREADY_STARTED
;
871 OldUnicodeStringTable
++;
877 // Allocate space for a new Unicode String Table. It must hold the current number of
878 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
881 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
882 if (NewUnicodeStringTable
== NULL
) {
883 return EFI_OUT_OF_RESOURCES
;
887 // If the current Unicode String Table contains any entries, then copy them to the
888 // newly allocated Unicode String Table.
890 if (*UnicodeStringTable
!= NULL
) {
892 NewUnicodeStringTable
,
894 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
899 // Allocate space for a copy of the Language specifier
901 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (3, Language
);
902 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
903 gBS
->FreePool (NewUnicodeStringTable
);
904 return EFI_OUT_OF_RESOURCES
;
908 // Compute the length of the Unicode String
910 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++)
914 // Allocate space for a copy of the Unicode String
916 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (
917 (UnicodeStringLength
+ 1) * sizeof (CHAR16
),
920 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
921 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
922 gBS
->FreePool (NewUnicodeStringTable
);
923 return EFI_OUT_OF_RESOURCES
;
927 // Mark the end of the Unicode String Table
929 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
930 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
933 // Free the old Unicode String Table
935 if (*UnicodeStringTable
!= NULL
) {
936 gBS
->FreePool (*UnicodeStringTable
);
940 // Point UnicodeStringTable at the newly allocated Unicode String Table
942 *UnicodeStringTable
= NewUnicodeStringTable
;
947 SupportedLanguages
+= 3;
950 return EFI_UNSUPPORTED
;
956 This function adds a Unicode string to UnicodeStringTable.
957 If Language is a member of SupportedLanguages then
958 UnicodeString is added to UnicodeStringTable. New buffers are
959 allocated for both Language and UnicodeString. The contents
960 of Language and UnicodeString are copied into these new
961 buffers. These buffers are automatically freed when
962 FreeUnicodeStringTable() is called.
964 @param Language A pointer to the ISO 639-2 or
965 RFC 3066 language code for the
966 Unicode string to add.
968 @param SupportedLanguages A pointer to the set of ISO
969 639-2 or RFC 3.66 language
970 codes that the Unicode string
971 table supports. Language must
972 be a member of this set.
974 @param UnicodeStringTable A pointer to the table of
977 @param UnicodeString A pointer to the Unicode
980 @param Iso639Language Specify the language code
981 format supported. If true,
982 then the format follow ISO
983 639-2. If false, then it
986 @retval EFI_SUCCESS The Unicode string that
987 matches the language specified
988 by Language was found in the
989 table of Unicode strings
990 UnicodeStringTable, and it was
991 returned in UnicodeString.
993 @retval EFI_INVALID_PARAMETER Language is NULL.
995 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
997 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
999 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
1001 @retval EFI_ALREADY_STARTED A Unicode string with language
1002 Language is already present in
1005 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
1006 add another Unicode string to
1009 @retval EFI_UNSUPPORTED The language specified by
1010 Language is not a member of
1017 IN CONST CHAR8
*Language
,
1018 IN CONST CHAR8
*SupportedLanguages
,
1019 IN EFI_UNICODE_STRING_TABLE
**UnicodeStringTable
,
1020 IN CONST CHAR16
*UnicodeString
,
1021 IN BOOLEAN Iso639Language
1024 UINTN NumberOfEntries
;
1025 EFI_UNICODE_STRING_TABLE
*OldUnicodeStringTable
;
1026 EFI_UNICODE_STRING_TABLE
*NewUnicodeStringTable
;
1027 UINTN UnicodeStringLength
;
1030 CHAR8
*LanguageString
;
1033 // Make sure the parameter are valid
1035 if (Language
== NULL
|| UnicodeString
== NULL
|| UnicodeStringTable
== NULL
) {
1036 return EFI_INVALID_PARAMETER
;
1040 // If there are no supported languages, then a Unicode String can not be added
1042 if (SupportedLanguages
== NULL
) {
1043 return EFI_UNSUPPORTED
;
1047 // If the Unicode String is empty, then a Unicode String can not be added
1049 if (UnicodeString
[0] == 0) {
1050 return EFI_INVALID_PARAMETER
;
1054 // Make sure Language is a member of SupportedLanguages
1057 while (*SupportedLanguages
!= 0) {
1058 if (Iso639Language
) {
1059 if (CompareIso639LanguageCode (Language
, SupportedLanguages
)) {
1063 SupportedLanguages
+= 3;
1065 for (Index
= 0; SupportedLanguages
[Index
] != 0 && SupportedLanguages
[Index
] != ';'; Index
++);
1066 if (AsciiStrnCmp(SupportedLanguages
, Language
, Index
) == 0) {
1070 SupportedLanguages
+= Index
;
1071 for (; *SupportedLanguages
!= 0 && *SupportedLanguages
== ';'; SupportedLanguages
++);
1076 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
1079 return EFI_UNSUPPORTED
;
1083 // Determine the size of the Unicode String Table by looking for a NULL Language entry
1085 NumberOfEntries
= 0;
1086 if (*UnicodeStringTable
!= NULL
) {
1087 OldUnicodeStringTable
= *UnicodeStringTable
;
1088 while (OldUnicodeStringTable
->Language
!= NULL
) {
1089 LanguageString
= OldUnicodeStringTable
->Language
;
1091 while (*LanguageString
!= 0) {
1092 for (Index
= 0; LanguageString
[Index
] != 0 && LanguageString
[Index
] != ';'; Index
++);
1094 if (AsciiStrnCmp (Language
, LanguageString
, Index
) == 0) {
1095 return EFI_ALREADY_STARTED
;
1097 LanguageString
+= Index
;
1098 for (; *LanguageString
!= 0 && *LanguageString
== ';'; LanguageString
++);
1100 OldUnicodeStringTable
++;
1106 // Allocate space for a new Unicode String Table. It must hold the current number of
1107 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
1110 NewUnicodeStringTable
= AllocatePool ((NumberOfEntries
+ 2) * sizeof (EFI_UNICODE_STRING_TABLE
));
1111 if (NewUnicodeStringTable
== NULL
) {
1112 return EFI_OUT_OF_RESOURCES
;
1116 // If the current Unicode String Table contains any entries, then copy them to the
1117 // newly allocated Unicode String Table.
1119 if (*UnicodeStringTable
!= NULL
) {
1121 NewUnicodeStringTable
,
1122 *UnicodeStringTable
,
1123 NumberOfEntries
* sizeof (EFI_UNICODE_STRING_TABLE
)
1128 // Allocate space for a copy of the Language specifier
1130 NewUnicodeStringTable
[NumberOfEntries
].Language
= AllocateCopyPool (AsciiStrSize(Language
), Language
);
1131 if (NewUnicodeStringTable
[NumberOfEntries
].Language
== NULL
) {
1132 gBS
->FreePool (NewUnicodeStringTable
);
1133 return EFI_OUT_OF_RESOURCES
;
1137 // Compute the length of the Unicode String
1139 for (UnicodeStringLength
= 0; UnicodeString
[UnicodeStringLength
] != 0; UnicodeStringLength
++);
1142 // Allocate space for a copy of the Unicode String
1144 NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
= AllocateCopyPool (StrSize (UnicodeString
), UnicodeString
);
1145 if (NewUnicodeStringTable
[NumberOfEntries
].UnicodeString
== NULL
) {
1146 gBS
->FreePool (NewUnicodeStringTable
[NumberOfEntries
].Language
);
1147 gBS
->FreePool (NewUnicodeStringTable
);
1148 return EFI_OUT_OF_RESOURCES
;
1152 // Mark the end of the Unicode String Table
1154 NewUnicodeStringTable
[NumberOfEntries
+ 1].Language
= NULL
;
1155 NewUnicodeStringTable
[NumberOfEntries
+ 1].UnicodeString
= NULL
;
1158 // Free the old Unicode String Table
1160 if (*UnicodeStringTable
!= NULL
) {
1161 gBS
->FreePool (*UnicodeStringTable
);
1165 // Point UnicodeStringTable at the newly allocated Unicode String Table
1167 *UnicodeStringTable
= NewUnicodeStringTable
;
1173 This function frees the table of Unicode strings in UnicodeStringTable.
1174 If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.
1175 Otherwise, each language code, and each Unicode string in the Unicode string
1176 table are freed, and EFI_SUCCESS is returned.
1178 @param UnicodeStringTable A pointer to the table of Unicode strings.
1180 @retval EFI_SUCCESS The Unicode string table was freed.
1185 FreeUnicodeStringTable (
1186 IN EFI_UNICODE_STRING_TABLE
*UnicodeStringTable
1192 // If the Unicode String Table is NULL, then it is already freed
1194 if (UnicodeStringTable
== NULL
) {
1199 // Loop through the Unicode String Table until we reach the end of table marker
1201 for (Index
= 0; UnicodeStringTable
[Index
].Language
!= NULL
; Index
++) {
1204 // Free the Language string from the Unicode String Table
1206 gBS
->FreePool (UnicodeStringTable
[Index
].Language
);
1209 // Free the Unicode String from the Unicode String Table
1211 if (UnicodeStringTable
[Index
].UnicodeString
!= NULL
) {
1212 gBS
->FreePool (UnicodeStringTable
[Index
].UnicodeString
);
1217 // Free the Unicode String Table itself
1219 gBS
->FreePool (UnicodeStringTable
);