]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/UefiLib/UefiLib.c
Removed MdePkg usage of ModuleName: in file headers
[mirror_edk2.git] / MdePkg / Library / UefiLib / UefiLib.c
1 /** @file
2 Mde UEFI library functions.
3
4 Copyright (c) 2006 - 2007, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 //
16 // Include common header file for this module.
17 //
18 #include "UefiLibInternal.h"
19
20 /**
21 Compare whether two names of languages are identical.
22
23 @param Language1 Name of language 1.
24 @param Language2 Name of language 2.
25
26 @retval TRUE Language 1 and language 2 are the same.
27 @retval FALSE Language 1 and language 2 are not the same.
28
29 **/
30 STATIC
31 BOOLEAN
32 CompareIso639LanguageCode (
33 IN CONST CHAR8 *Language1,
34 IN CONST CHAR8 *Language2
35 )
36 {
37 UINT32 Name1;
38 UINT32 Name2;
39
40 Name1 = ReadUnaligned24 ((CONST UINT32 *) Language1);
41 Name2 = ReadUnaligned24 ((CONST UINT32 *) Language2);
42
43 return (BOOLEAN) (Name1 == Name2);
44 }
45
46 /**
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.
51
52 @param TableGuid Pointer to table's GUID type..
53 @param Table Pointer to the table associated with TableGuid in the EFI System Table.
54
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.
57
58 **/
59 EFI_STATUS
60 EFIAPI
61 EfiGetSystemConfigurationTable (
62 IN EFI_GUID *TableGuid,
63 OUT VOID **Table
64 )
65 {
66 EFI_SYSTEM_TABLE *SystemTable;
67 UINTN Index;
68
69 ASSERT (TableGuid != NULL);
70 ASSERT (Table != NULL);
71
72 SystemTable = gST;
73 *Table = NULL;
74 for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
75 if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) {
76 *Table = SystemTable->ConfigurationTable[Index].VendorTable;
77 return EFI_SUCCESS;
78 }
79 }
80
81 return EFI_NOT_FOUND;
82 }
83
84 /**
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.
89
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.
95
96 @return The notification event that was created.
97
98 **/
99 EFI_EVENT
100 EFIAPI
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
107 )
108 {
109 EFI_STATUS Status;
110 EFI_EVENT Event;
111
112 //
113 // Create the event
114 //
115
116 Status = gBS->CreateEvent (
117 EVT_NOTIFY_SIGNAL,
118 NotifyTpl,
119 NotifyFunction,
120 NotifyContext,
121 &Event
122 );
123 ASSERT_EFI_ERROR (Status);
124
125 //
126 // Register for protocol notifactions on this event
127 //
128
129 Status = gBS->RegisterProtocolNotify (
130 ProtocolGuid,
131 Event,
132 Registration
133 );
134
135 ASSERT_EFI_ERROR (Status);
136
137 //
138 // Kick the event so we will perform an initial pass of
139 // current installed drivers
140 //
141
142 gBS->SignalEvent (Event);
143 return Event;
144 }
145
146 /**
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.
150
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.
156
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.
159
160 **/
161 EFI_STATUS
162 EFIAPI
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
169 )
170 {
171 EFI_STATUS Status;
172 EFI_EVENT Event;
173 VOID *RegistrationLocal;
174
175 //
176 // Create event
177 //
178 Status = gBS->CreateEvent (
179 EVT_NOTIFY_SIGNAL,
180 NotifyTpl,
181 NotifyFunction,
182 (VOID *) NotifyContext,
183 &Event
184 );
185 ASSERT_EFI_ERROR (Status);
186
187 //
188 // The Registration is not optional to RegisterProtocolNotify().
189 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.
190 //
191 if (Registration != NULL) {
192 RegistrationLocal = Registration;
193 } else {
194 RegistrationLocal = &RegistrationLocal;
195 }
196
197 //
198 // Register for an installation of protocol interface
199 //
200
201 Status = gBS->RegisterProtocolNotify (
202 (EFI_GUID *) Name,
203 Event,
204 RegistrationLocal
205 );
206 ASSERT_EFI_ERROR (Status);
207
208 return EFI_SUCCESS;
209 }
210
211 /**
212 This function signals the named event specified by Name. The named event must
213 have been created with EfiNamedEventListen().
214
215 @param Name Supplies GUID name of the event.
216
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.
219
220 **/
221 EFI_STATUS
222 EFIAPI
223 EfiNamedEventSignal (
224 IN CONST EFI_GUID *Name
225 )
226 {
227 EFI_STATUS Status;
228 EFI_HANDLE Handle;
229
230 Handle = NULL;
231 Status = gBS->InstallProtocolInterface (
232 &Handle,
233 (EFI_GUID *) Name,
234 EFI_NATIVE_INTERFACE,
235 NULL
236 );
237 ASSERT_EFI_ERROR (Status);
238
239 Status = gBS->UninstallProtocolInterface (
240 Handle,
241 (EFI_GUID *) Name,
242 NULL
243 );
244 ASSERT_EFI_ERROR (Status);
245
246 return EFI_SUCCESS;
247 }
248
249 /**
250 Returns the current TPL.
251
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
256 to RestoreTPL().
257
258 @param VOID
259
260 @retvale EFI_TPL The current TPL.
261
262 **/
263 EFI_TPL
264 EFIAPI
265 EfiGetCurrentTpl (
266 VOID
267 )
268 {
269 EFI_TPL Tpl;
270
271 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
272 gBS->RestoreTPL (Tpl);
273
274 return Tpl;
275 }
276
277
278 /**
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.
283
284 @param Lock A pointer to the lock data structure to initialize.
285 @param Priority EFI TPL associated with the lock.
286
287 @return The lock.
288
289 **/
290 EFI_LOCK *
291 EFIAPI
292 EfiInitializeLock (
293 IN OUT EFI_LOCK *Lock,
294 IN EFI_TPL Priority
295 )
296 {
297 ASSERT (Lock != NULL);
298 ASSERT (Priority <= TPL_HIGH_LEVEL);
299
300 Lock->Tpl = Priority;
301 Lock->OwnerTpl = TPL_APPLICATION;
302 Lock->Lock = EfiLockReleased ;
303 return Lock;
304 }
305
306 /**
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
309 acquired state.
310
311 @param Priority The task priority level of the lock.
312
313 **/
314 VOID
315 EFIAPI
316 EfiAcquireLock (
317 IN EFI_LOCK *Lock
318 )
319 {
320 ASSERT (Lock != NULL);
321 ASSERT (Lock->Lock == EfiLockReleased);
322
323 Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);
324 Lock->Lock = EfiLockAcquired;
325 }
326
327 /**
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.
331
332 @param Lock A pointer to the lock to acquire.
333
334 @retval EFI_SUCCESS The lock was acquired.
335 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
336
337 **/
338 EFI_STATUS
339 EFIAPI
340 EfiAcquireLockOrFail (
341 IN EFI_LOCK *Lock
342 )
343 {
344
345 ASSERT (Lock != NULL);
346 ASSERT (Lock->Lock != EfiLockUninitialized);
347
348 if (Lock->Lock == EfiLockAcquired) {
349 //
350 // Lock is already owned, so bail out
351 //
352 return EFI_ACCESS_DENIED;
353 }
354
355 Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);
356
357 Lock->Lock = EfiLockAcquired;
358
359 return EFI_SUCCESS;
360 }
361
362 /**
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
365 previous level.
366
367 @param Lock A pointer to the lock to release.
368
369 **/
370 VOID
371 EFIAPI
372 EfiReleaseLock (
373 IN EFI_LOCK *Lock
374 )
375 {
376 EFI_TPL Tpl;
377
378 ASSERT (Lock != NULL);
379 ASSERT (Lock->Lock == EfiLockAcquired);
380
381 Tpl = Lock->OwnerTpl;
382
383 Lock->Lock = EfiLockReleased;
384
385 gBS->RestoreTPL (Tpl);
386 }
387
388 /**
389 Tests whether a controller handle is being managed by a specific driver.
390
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().
397
398 @param ControllerHandle A handle for a controller to test.
399 @param DriverBindingHandle Specifies the driver binding handle for the
400 driver.
401 @param ProtocolGuid Specifies the protocol that the driver specified
402 by DriverBindingHandle opens in its Start()
403 function.
404
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.
409
410 **/
411 EFI_STATUS
412 EFIAPI
413 EfiTestManagedDevice (
414 IN CONST EFI_HANDLE ControllerHandle,
415 IN CONST EFI_HANDLE DriverBindingHandle,
416 IN CONST EFI_GUID *ProtocolGuid
417 )
418 {
419 EFI_STATUS Status;
420 VOID *ManagedInterface;
421
422 ASSERT (ProtocolGuid != NULL);
423
424 Status = gBS->OpenProtocol (
425 ControllerHandle,
426 (EFI_GUID *) ProtocolGuid,
427 &ManagedInterface,
428 DriverBindingHandle,
429 ControllerHandle,
430 EFI_OPEN_PROTOCOL_BY_DRIVER
431 );
432 if (!EFI_ERROR (Status)) {
433 gBS->CloseProtocol (
434 ControllerHandle,
435 (EFI_GUID *) ProtocolGuid,
436 DriverBindingHandle,
437 ControllerHandle
438 );
439 return EFI_UNSUPPORTED;
440 }
441
442 if (Status != EFI_ALREADY_STARTED) {
443 return EFI_UNSUPPORTED;
444 }
445
446 return EFI_SUCCESS;
447 }
448
449 /**
450 Tests whether a child handle is a child device of the controller.
451
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().
457
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.
462
463 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
464 @retval EFI_UNSUPPORTED ChildHandle is not a child of the
465 ControllerHandle.
466
467 **/
468 EFI_STATUS
469 EFIAPI
470 EfiTestChildHandle (
471 IN CONST EFI_HANDLE ControllerHandle,
472 IN CONST EFI_HANDLE ChildHandle,
473 IN CONST EFI_GUID *ProtocolGuid
474 )
475 {
476 EFI_STATUS Status;
477 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
478 UINTN EntryCount;
479 UINTN Index;
480
481 ASSERT (ProtocolGuid != NULL);
482
483 //
484 // Retrieve the list of agents that are consuming the specific protocol
485 // on ControllerHandle.
486 //
487 Status = gBS->OpenProtocolInformation (
488 ControllerHandle,
489 (EFI_GUID *) ProtocolGuid,
490 &OpenInfoBuffer,
491 &EntryCount
492 );
493 if (EFI_ERROR (Status)) {
494 return EFI_UNSUPPORTED;
495 }
496
497 //
498 // Inspect if ChildHandle is one of the agents.
499 //
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;
505 break;
506 }
507 }
508
509 FreePool (OpenInfoBuffer);
510 return Status;
511 }
512
513 /**
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
518 UnicodeString.
519
520 @param Language A pointer to the ISO 639-2
521 language code for the Unicode
522 string to look up and return.
523
524 @param SupportedLanguages A pointer to the set of ISO
525 639-2language
526 codes that the Unicode string
527 table supports. Language must
528 be a member of this set.
529
530 @param UnicodeStringTable A pointer to the table of
531 Unicode strings.
532
533 @param UnicodeString A pointer to the Unicode
534 string from UnicodeStringTable
535 that matches the language
536 specified by Language.
537
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.
544
545 @retval EFI_INVALID_PARAMETER Language is NULL.
546
547 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
548 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
549
550 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
551
552 @retval EFI_UNSUPPORTED The language specified by
553 Language is not a member
554 ofSupportedLanguages.
555
556 @retval EFI_UNSUPPORTED The language specified by
557 Language is not supported by
558 UnicodeStringTable.
559
560 **/
561 EFI_STATUS
562 EFIAPI
563 LookupUnicodeString (
564 IN CONST CHAR8 *Language,
565 IN CONST CHAR8 *SupportedLanguages,
566 IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable,
567 OUT CHAR16 **UnicodeString
568 )
569 {
570 //
571 // Make sure the parameters are valid
572 //
573 if (Language == NULL || UnicodeString == NULL) {
574 return EFI_INVALID_PARAMETER;
575 }
576
577 //
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
580 //
581 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
582 return EFI_UNSUPPORTED;
583 }
584
585 //
586 // Make sure Language is in the set of Supported Languages
587 //
588 while (*SupportedLanguages != 0) {
589 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
590
591 //
592 // Search the Unicode String Table for the matching Language specifier
593 //
594 while (UnicodeStringTable->Language != NULL) {
595 if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) {
596
597 //
598 // A matching string was found, so return it
599 //
600 *UnicodeString = UnicodeStringTable->UnicodeString;
601 return EFI_SUCCESS;
602 }
603
604 UnicodeStringTable++;
605 }
606
607 return EFI_UNSUPPORTED;
608 }
609
610 SupportedLanguages += 3;
611 }
612
613 return EFI_UNSUPPORTED;
614 }
615
616
617
618 /**
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
623 UnicodeString.
624
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
628 return.
629
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.
635
636 @param UnicodeStringTable A pointer to the table of
637 Unicode strings.
638
639 @param UnicodeString A pointer to the Unicode
640 string from UnicodeStringTable
641 that matches the language
642 specified by Language.
643
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
648 follows RFC3066.
649
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.
656
657 @retval EFI_INVALID_PARAMETER Language is NULL.
658
659 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
660
661 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
662
663 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.
664
665 @retval EFI_UNSUPPORTED The language specified by
666 Language is not a member
667 ofSupportedLanguages.
668
669 @retval EFI_UNSUPPORTED The language specified by
670 Language is not supported by
671 UnicodeStringTable.
672
673 **/
674 EFI_STATUS
675 EFIAPI
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
682 )
683 {
684 BOOLEAN Found;
685 UINTN Index;
686 CHAR8 *LanguageString;
687
688 //
689 // Make sure the parameters are valid
690 //
691 if (Language == NULL || UnicodeString == NULL) {
692 return EFI_INVALID_PARAMETER;
693 }
694
695 //
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
698 //
699 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
700 return EFI_UNSUPPORTED;
701 }
702
703 //
704 // Make sure Language is in the set of Supported Languages
705 //
706 Found = FALSE;
707 while (*SupportedLanguages != 0) {
708 if (Iso639Language) {
709 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
710 Found = TRUE;
711 break;
712 }
713 SupportedLanguages += 3;
714 } else {
715 for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);
716 if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {
717 Found = TRUE;
718 break;
719 }
720 SupportedLanguages += Index;
721 for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);
722 }
723 }
724
725 //
726 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
727 //
728 if (!Found) {
729 return EFI_UNSUPPORTED;
730 }
731
732 //
733 // Search the Unicode String Table for the matching Language specifier
734 //
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;
741 return EFI_SUCCESS;
742 }
743 LanguageString += Index;
744 for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] == ';'; Index++);
745 }
746 UnicodeStringTable++;
747 }
748
749 return EFI_UNSUPPORTED;
750 }
751
752
753 /**
754
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.
762
763 @param Language A pointer to the ISO 639-2
764 language code for the Unicode
765 string to add.
766
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
771 this set.
772
773 @param UnicodeStringTable A pointer to the table of
774 Unicode strings.
775
776 @param UnicodeString A pointer to the Unicode
777 string to add.
778
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.
785
786 @retval EFI_INVALID_PARAMETER Language is NULL.
787
788 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
789
790 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
791
792 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
793
794 @retval EFI_ALREADY_STARTED A Unicode string with language
795 Language is already present in
796 UnicodeStringTable.
797
798 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
799 add another Unicode string to
800 UnicodeStringTable.
801
802 @retval EFI_UNSUPPORTED The language specified by
803 Language is not a member of
804 SupportedLanguages.
805
806 **/
807 EFI_STATUS
808 EFIAPI
809 AddUnicodeString (
810 IN CONST CHAR8 *Language,
811 IN CONST CHAR8 *SupportedLanguages,
812 IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable,
813 IN CONST CHAR16 *UnicodeString
814 )
815 {
816 UINTN NumberOfEntries;
817 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;
818 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;
819 UINTN UnicodeStringLength;
820
821 //
822 // Make sure the parameter are valid
823 //
824 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {
825 return EFI_INVALID_PARAMETER;
826 }
827
828 //
829 // If there are no supported languages, then a Unicode String can not be added
830 //
831 if (SupportedLanguages == NULL) {
832 return EFI_UNSUPPORTED;
833 }
834
835 //
836 // If the Unicode String is empty, then a Unicode String can not be added
837 //
838 if (UnicodeString[0] == 0) {
839 return EFI_INVALID_PARAMETER;
840 }
841
842 //
843 // Make sure Language is a member of SupportedLanguages
844 //
845 while (*SupportedLanguages != 0) {
846 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
847
848 //
849 // Determine the size of the Unicode String Table by looking for a NULL Language entry
850 //
851 NumberOfEntries = 0;
852 if (*UnicodeStringTable != NULL) {
853 OldUnicodeStringTable = *UnicodeStringTable;
854 while (OldUnicodeStringTable->Language != NULL) {
855 if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) {
856 return EFI_ALREADY_STARTED;
857 }
858
859 OldUnicodeStringTable++;
860 NumberOfEntries++;
861 }
862 }
863
864 //
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
867 // marker
868 //
869 NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));
870 if (NewUnicodeStringTable == NULL) {
871 return EFI_OUT_OF_RESOURCES;
872 }
873
874 //
875 // If the current Unicode String Table contains any entries, then copy them to the
876 // newly allocated Unicode String Table.
877 //
878 if (*UnicodeStringTable != NULL) {
879 CopyMem (
880 NewUnicodeStringTable,
881 *UnicodeStringTable,
882 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)
883 );
884 }
885
886 //
887 // Allocate space for a copy of the Language specifier
888 //
889 NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language);
890 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {
891 gBS->FreePool (NewUnicodeStringTable);
892 return EFI_OUT_OF_RESOURCES;
893 }
894
895 //
896 // Compute the length of the Unicode String
897 //
898 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++)
899 ;
900
901 //
902 // Allocate space for a copy of the Unicode String
903 //
904 NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (
905 (UnicodeStringLength + 1) * sizeof (CHAR16),
906 UnicodeString
907 );
908 if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {
909 gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);
910 gBS->FreePool (NewUnicodeStringTable);
911 return EFI_OUT_OF_RESOURCES;
912 }
913
914 //
915 // Mark the end of the Unicode String Table
916 //
917 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;
918 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;
919
920 //
921 // Free the old Unicode String Table
922 //
923 if (*UnicodeStringTable != NULL) {
924 gBS->FreePool (*UnicodeStringTable);
925 }
926
927 //
928 // Point UnicodeStringTable at the newly allocated Unicode String Table
929 //
930 *UnicodeStringTable = NewUnicodeStringTable;
931
932 return EFI_SUCCESS;
933 }
934
935 SupportedLanguages += 3;
936 }
937
938 return EFI_UNSUPPORTED;
939 }
940
941
942 /**
943
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.
951
952 @param Language A pointer to the ISO 639-2 or
953 RFC 3066 language code for the
954 Unicode string to add.
955
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.
961
962 @param UnicodeStringTable A pointer to the table of
963 Unicode strings.
964
965 @param UnicodeString A pointer to the Unicode
966 string to add.
967
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
972 follows RFC3066.
973
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.
980
981 @retval EFI_INVALID_PARAMETER Language is NULL.
982
983 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.
984
985 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.
986
987 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.
988
989 @retval EFI_ALREADY_STARTED A Unicode string with language
990 Language is already present in
991 UnicodeStringTable.
992
993 @retval EFI_OUT_OF_RESOURCES There is not enough memory to
994 add another Unicode string to
995 UnicodeStringTable.
996
997 @retval EFI_UNSUPPORTED The language specified by
998 Language is not a member of
999 SupportedLanguages.
1000
1001 **/
1002 EFI_STATUS
1003 EFIAPI
1004 AddUnicodeString2 (
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
1010 )
1011 {
1012 UINTN NumberOfEntries;
1013 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;
1014 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;
1015 UINTN UnicodeStringLength;
1016 BOOLEAN Found;
1017 UINTN Index;
1018 CHAR8 *LanguageString;
1019
1020 //
1021 // Make sure the parameter are valid
1022 //
1023 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {
1024 return EFI_INVALID_PARAMETER;
1025 }
1026
1027 //
1028 // If there are no supported languages, then a Unicode String can not be added
1029 //
1030 if (SupportedLanguages == NULL) {
1031 return EFI_UNSUPPORTED;
1032 }
1033
1034 //
1035 // If the Unicode String is empty, then a Unicode String can not be added
1036 //
1037 if (UnicodeString[0] == 0) {
1038 return EFI_INVALID_PARAMETER;
1039 }
1040
1041 //
1042 // Make sure Language is a member of SupportedLanguages
1043 //
1044 Found = FALSE;
1045 while (*SupportedLanguages != 0) {
1046 if (Iso639Language) {
1047 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
1048 Found = TRUE;
1049 break;
1050 }
1051 SupportedLanguages += 3;
1052 } else {
1053 for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);
1054 if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {
1055 Found = TRUE;
1056 break;
1057 }
1058 SupportedLanguages += Index;
1059 for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);
1060 }
1061 }
1062
1063 //
1064 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
1065 //
1066 if (!Found) {
1067 return EFI_UNSUPPORTED;
1068 }
1069
1070 //
1071 // Determine the size of the Unicode String Table by looking for a NULL Language entry
1072 //
1073 NumberOfEntries = 0;
1074 if (*UnicodeStringTable != NULL) {
1075 OldUnicodeStringTable = *UnicodeStringTable;
1076 while (OldUnicodeStringTable->Language != NULL) {
1077 LanguageString = OldUnicodeStringTable->Language;
1078
1079 while (*LanguageString) {
1080 for (Index = 0; LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);
1081
1082 if (AsciiStrnCmp (Language, LanguageString, Index) == 0) {
1083 return EFI_ALREADY_STARTED;
1084 }
1085 LanguageString += Index;
1086 for (; *LanguageString != 0 && *LanguageString == ';'; LanguageString++);
1087 }
1088 OldUnicodeStringTable++;
1089 NumberOfEntries++;
1090 }
1091 }
1092
1093 //
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
1096 // marker
1097 //
1098 NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));
1099 if (NewUnicodeStringTable == NULL) {
1100 return EFI_OUT_OF_RESOURCES;
1101 }
1102
1103 //
1104 // If the current Unicode String Table contains any entries, then copy them to the
1105 // newly allocated Unicode String Table.
1106 //
1107 if (*UnicodeStringTable != NULL) {
1108 CopyMem (
1109 NewUnicodeStringTable,
1110 *UnicodeStringTable,
1111 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)
1112 );
1113 }
1114
1115 //
1116 // Allocate space for a copy of the Language specifier
1117 //
1118 NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (AsciiStrSize(Language), Language);
1119 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {
1120 gBS->FreePool (NewUnicodeStringTable);
1121 return EFI_OUT_OF_RESOURCES;
1122 }
1123
1124 //
1125 // Compute the length of the Unicode String
1126 //
1127 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++);
1128
1129 //
1130 // Allocate space for a copy of the Unicode String
1131 //
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;
1137 }
1138
1139 //
1140 // Mark the end of the Unicode String Table
1141 //
1142 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;
1143 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;
1144
1145 //
1146 // Free the old Unicode String Table
1147 //
1148 if (*UnicodeStringTable != NULL) {
1149 gBS->FreePool (*UnicodeStringTable);
1150 }
1151
1152 //
1153 // Point UnicodeStringTable at the newly allocated Unicode String Table
1154 //
1155 *UnicodeStringTable = NewUnicodeStringTable;
1156
1157 return EFI_SUCCESS;
1158 }
1159
1160 /**
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.
1165
1166 @param UnicodeStringTable A pointer to the table of Unicode strings.
1167
1168 @retval EFI_SUCCESS The Unicode string table was freed.
1169
1170 **/
1171 EFI_STATUS
1172 EFIAPI
1173 FreeUnicodeStringTable (
1174 IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable
1175 )
1176 {
1177 UINTN Index;
1178
1179 //
1180 // If the Unicode String Table is NULL, then it is already freed
1181 //
1182 if (UnicodeStringTable == NULL) {
1183 return EFI_SUCCESS;
1184 }
1185
1186 //
1187 // Loop through the Unicode String Table until we reach the end of table marker
1188 //
1189 for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) {
1190
1191 //
1192 // Free the Language string from the Unicode String Table
1193 //
1194 gBS->FreePool (UnicodeStringTable[Index].Language);
1195
1196 //
1197 // Free the Unicode String from the Unicode String Table
1198 //
1199 if (UnicodeStringTable[Index].UnicodeString != NULL) {
1200 gBS->FreePool (UnicodeStringTable[Index].UnicodeString);
1201 }
1202 }
1203
1204 //
1205 // Free the Unicode String Table itself
1206 //
1207 gBS->FreePool (UnicodeStringTable);
1208
1209 return EFI_SUCCESS;
1210 }
1211