]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkPkg/Library/FrameworkUefiLib/UefiLib.c
IntelFrameworkPkg/FrameworkUefiLib: move InternalEmptyFunction to UefiLib.c
[mirror_edk2.git] / IntelFrameworkPkg / Library / FrameworkUefiLib / UefiLib.c
... / ...
CommitLineData
1/** @file\r
2 The UEFI Library provides functions and macros that simplify the development of \r
3 UEFI Drivers and UEFI Applications. These functions and macros help manage EFI \r
4 events, build simple locks utilizing EFI Task Priority Levels (TPLs), install \r
5 EFI Driver Model related protocols, manage Unicode string tables for UEFI Drivers, \r
6 and print messages on the console output and standard error devices.\r
7\r
8 Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
9 This program and the accompanying materials\r
10 are licensed and made available under the terms and conditions of the BSD License\r
11 which accompanies this distribution. The full text of the license may be found at\r
12 http://opensource.org/licenses/bsd-license.php\r
13\r
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18\r
19\r
20#include "UefiLibInternal.h"\r
21\r
22/**\r
23 Compare whether two names of languages are identical.\r
24\r
25 @param Language1 Name of language 1.\r
26 @param Language2 Name of language 2.\r
27\r
28 @retval TRUE Language 1 and language 2 are the same.\r
29 @retval FALSE Language 1 and language 2 are not the same.\r
30\r
31**/\r
32BOOLEAN\r
33CompareIso639LanguageCode (\r
34 IN CONST CHAR8 *Language1,\r
35 IN CONST CHAR8 *Language2\r
36 )\r
37{\r
38 UINT32 Name1;\r
39 UINT32 Name2;\r
40\r
41 Name1 = ReadUnaligned24 ((CONST UINT32 *) Language1);\r
42 Name2 = ReadUnaligned24 ((CONST UINT32 *) Language2);\r
43\r
44 return (BOOLEAN) (Name1 == Name2);\r
45}\r
46\r
47/**\r
48 Retrieves a pointer to the system configuration table from the EFI System Table\r
49 based on a specified GUID.\r
50 \r
51 This function searches the list of configuration tables stored in the EFI System Table\r
52 for a table with a GUID that matches TableGuid. If a match is found, then a pointer to\r
53 the configuration table is returned in Table., and EFI_SUCCESS is returned. If a matching GUID\r
54 is not found, then EFI_NOT_FOUND is returned.\r
55 If TableGuid is NULL, then ASSERT().\r
56 If Table is NULL, then ASSERT().\r
57\r
58 @param TableGuid Pointer to table's GUID type..\r
59 @param Table Pointer to the table associated with TableGuid in the EFI System Table.\r
60\r
61 @retval EFI_SUCCESS A configuration table matching TableGuid was found.\r
62 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.\r
63\r
64**/\r
65EFI_STATUS\r
66EFIAPI\r
67EfiGetSystemConfigurationTable (\r
68 IN EFI_GUID *TableGuid,\r
69 OUT VOID **Table\r
70 )\r
71{\r
72 EFI_SYSTEM_TABLE *SystemTable;\r
73 UINTN Index;\r
74\r
75 ASSERT (TableGuid != NULL);\r
76 ASSERT (Table != NULL);\r
77\r
78 SystemTable = gST;\r
79 *Table = NULL;\r
80 for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {\r
81 if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) {\r
82 *Table = SystemTable->ConfigurationTable[Index].VendorTable;\r
83 return EFI_SUCCESS;\r
84 }\r
85 }\r
86\r
87 return EFI_NOT_FOUND;\r
88}\r
89\r
90/**\r
91 Creates and returns a notification event and registers that event with all the protocol\r
92 instances specified by ProtocolGuid.\r
93\r
94 This function causes the notification function to be executed for every protocol of type\r
95 ProtocolGuid instance that exists in the system when this function is invoked. If there are\r
96 no instances of ProtocolGuid in the handle database at the time this function is invoked,\r
97 then the notification function is still executed one time. In addition, every time a protocol\r
98 of type ProtocolGuid instance is installed or reinstalled, the notification function is also\r
99 executed. This function returns the notification event that was created. \r
100 If ProtocolGuid is NULL, then ASSERT().\r
101 If NotifyTpl is not a legal TPL value, then ASSERT().\r
102 If NotifyFunction is NULL, then ASSERT().\r
103 If Registration is NULL, then ASSERT().\r
104\r
105\r
106 @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired.\r
107 @param NotifyTpl Supplies the task priority level of the event notifications.\r
108 @param NotifyFunction Supplies the function to notify when the event is signaled.\r
109 @param NotifyContext The context parameter to pass to NotifyFunction.\r
110 @param Registration A pointer to a memory location to receive the registration value.\r
111 This value is passed to LocateHandle() to obtain new handles that\r
112 have been added that support the ProtocolGuid-specified protocol. \r
113\r
114 @return The notification event that was created.\r
115\r
116**/\r
117EFI_EVENT\r
118EFIAPI\r
119EfiCreateProtocolNotifyEvent(\r
120 IN EFI_GUID *ProtocolGuid,\r
121 IN EFI_TPL NotifyTpl,\r
122 IN EFI_EVENT_NOTIFY NotifyFunction,\r
123 IN VOID *NotifyContext, OPTIONAL\r
124 OUT VOID **Registration\r
125 )\r
126{\r
127 EFI_STATUS Status;\r
128 EFI_EVENT Event;\r
129\r
130 ASSERT (ProtocolGuid != NULL);\r
131 ASSERT (NotifyFunction != NULL);\r
132 ASSERT (Registration != NULL);\r
133\r
134 //\r
135 // Create the event\r
136 //\r
137\r
138 Status = gBS->CreateEvent (\r
139 EVT_NOTIFY_SIGNAL,\r
140 NotifyTpl,\r
141 NotifyFunction,\r
142 NotifyContext,\r
143 &Event\r
144 );\r
145 ASSERT_EFI_ERROR (Status);\r
146\r
147 //\r
148 // Register for protocol notifications on this event\r
149 //\r
150\r
151 Status = gBS->RegisterProtocolNotify (\r
152 ProtocolGuid,\r
153 Event,\r
154 Registration\r
155 );\r
156\r
157 ASSERT_EFI_ERROR (Status);\r
158\r
159 //\r
160 // Kick the event so we will perform an initial pass of\r
161 // current installed drivers\r
162 //\r
163\r
164 gBS->SignalEvent (Event);\r
165 return Event;\r
166}\r
167\r
168/**\r
169 Creates a named event that can be signaled with EfiNamedEventSignal().\r
170\r
171 This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.\r
172 This event is signaled with EfiNamedEventSignal(). This provides the ability for one or more\r
173 listeners on the same event named by the GUID specified by Name. \r
174 If Name is NULL, then ASSERT().\r
175 If NotifyTpl is not a legal TPL value, then ASSERT().\r
176 If NotifyFunction is NULL, then ASSERT().\r
177\r
178 @param Name Supplies GUID name of the event.\r
179 @param NotifyTpl Supplies the task priority level of the event notifications.\r
180 @param NotifyFunction Supplies the function to notify when the event is signaled.\r
181 @param NotifyContext The context parameter to pass to NotifyFunction. \r
182 @param Registration A pointer to a memory location to receive the registration value.\r
183\r
184 @retval EFI_SUCCESS A named event was created.\r
185 @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event.\r
186\r
187**/\r
188EFI_STATUS\r
189EFIAPI\r
190EfiNamedEventListen (\r
191 IN CONST EFI_GUID *Name,\r
192 IN EFI_TPL NotifyTpl,\r
193 IN EFI_EVENT_NOTIFY NotifyFunction,\r
194 IN CONST VOID *NotifyContext, OPTIONAL\r
195 OUT VOID *Registration OPTIONAL\r
196 )\r
197{\r
198 EFI_STATUS Status;\r
199 EFI_EVENT Event;\r
200 VOID *RegistrationLocal;\r
201\r
202 ASSERT (Name != NULL);\r
203 ASSERT (NotifyFunction != NULL);\r
204 ASSERT (NotifyTpl <= TPL_HIGH_LEVEL);\r
205 \r
206 //\r
207 // Create event\r
208 //\r
209 Status = gBS->CreateEvent (\r
210 EVT_NOTIFY_SIGNAL,\r
211 NotifyTpl,\r
212 NotifyFunction,\r
213 (VOID *) NotifyContext,\r
214 &Event\r
215 );\r
216 ASSERT_EFI_ERROR (Status);\r
217\r
218 //\r
219 // The Registration is not optional to RegisterProtocolNotify().\r
220 // To make it optional to EfiNamedEventListen(), may need to substitute with a local.\r
221 //\r
222 if (Registration != NULL) {\r
223 RegistrationLocal = Registration;\r
224 } else {\r
225 RegistrationLocal = &RegistrationLocal;\r
226 }\r
227\r
228 //\r
229 // Register for an installation of protocol interface\r
230 //\r
231\r
232 Status = gBS->RegisterProtocolNotify (\r
233 (EFI_GUID *) Name,\r
234 Event,\r
235 RegistrationLocal\r
236 );\r
237 ASSERT_EFI_ERROR (Status);\r
238\r
239 return Status;\r
240}\r
241\r
242/**\r
243 Signals a named event created with EfiNamedEventListen().\r
244\r
245 This function signals the named event specified by Name. The named event must have been\r
246 created with EfiNamedEventListen().\r
247 If Name is NULL, then ASSERT().\r
248\r
249 @param Name Supplies GUID name of the event.\r
250\r
251 @retval EFI_SUCCESS A named event was signaled.\r
252 @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event.\r
253\r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257EfiNamedEventSignal (\r
258 IN CONST EFI_GUID *Name\r
259 )\r
260{\r
261 EFI_STATUS Status;\r
262 EFI_HANDLE Handle;\r
263\r
264 ASSERT(Name != NULL);\r
265\r
266 Handle = NULL;\r
267 Status = gBS->InstallProtocolInterface (\r
268 &Handle,\r
269 (EFI_GUID *) Name,\r
270 EFI_NATIVE_INTERFACE,\r
271 NULL\r
272 );\r
273 ASSERT_EFI_ERROR (Status);\r
274\r
275 Status = gBS->UninstallProtocolInterface (\r
276 Handle,\r
277 (EFI_GUID *) Name,\r
278 NULL\r
279 );\r
280 ASSERT_EFI_ERROR (Status);\r
281\r
282 return Status;\r
283}\r
284\r
285/** \r
286 Returns the current TPL.\r
287\r
288 This function returns the current TPL. There is no EFI service to directly \r
289 retrieve the current TPL. Instead, the RaiseTPL() function is used to raise \r
290 the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level \r
291 can then immediately be restored back to the current TPL level with a call \r
292 to RestoreTPL().\r
293\r
294 @return The current TPL.\r
295\r
296**/\r
297EFI_TPL\r
298EFIAPI\r
299EfiGetCurrentTpl (\r
300 VOID\r
301 )\r
302{\r
303 EFI_TPL Tpl;\r
304\r
305 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
306 gBS->RestoreTPL (Tpl);\r
307\r
308 return Tpl;\r
309}\r
310\r
311\r
312/**\r
313 Initializes a basic mutual exclusion lock.\r
314\r
315 This function initializes a basic mutual exclusion lock to the released state \r
316 and returns the lock. Each lock provides mutual exclusion access at its task \r
317 priority level. Since there is no preemption or multiprocessor support in EFI,\r
318 acquiring the lock only consists of raising to the locks TPL.\r
319 If Lock is NULL, then ASSERT().\r
320 If Priority is not a valid TPL value, then ASSERT().\r
321\r
322 @param Lock A pointer to the lock data structure to initialize.\r
323 @param Priority EFI TPL associated with the lock.\r
324\r
325 @return The lock.\r
326\r
327**/\r
328EFI_LOCK *\r
329EFIAPI\r
330EfiInitializeLock (\r
331 IN OUT EFI_LOCK *Lock,\r
332 IN EFI_TPL Priority\r
333 )\r
334{\r
335 ASSERT (Lock != NULL);\r
336 ASSERT (Priority <= TPL_HIGH_LEVEL);\r
337\r
338 Lock->Tpl = Priority;\r
339 Lock->OwnerTpl = TPL_APPLICATION;\r
340 Lock->Lock = EfiLockReleased ;\r
341 return Lock;\r
342}\r
343\r
344/**\r
345 Acquires ownership of a lock.\r
346\r
347 This function raises the system's current task priority level to the task \r
348 priority level of the mutual exclusion lock. Then, it places the lock in the \r
349 acquired state.\r
350 If Lock is NULL, then ASSERT().\r
351 If Lock is not initialized, then ASSERT().\r
352 If Lock is already in the acquired state, then ASSERT().\r
353\r
354 @param Lock A pointer to the lock to acquire.\r
355\r
356**/\r
357VOID\r
358EFIAPI\r
359EfiAcquireLock (\r
360 IN EFI_LOCK *Lock\r
361 )\r
362{\r
363 ASSERT (Lock != NULL);\r
364 ASSERT (Lock->Lock == EfiLockReleased);\r
365\r
366 Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);\r
367 Lock->Lock = EfiLockAcquired;\r
368}\r
369\r
370/**\r
371 Acquires ownership of a lock.\r
372\r
373 This function raises the system's current task priority level to the task priority\r
374 level of the mutual exclusion lock. Then, it attempts to place the lock in the acquired state.\r
375 If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.\r
376 Otherwise, EFI_SUCCESS is returned.\r
377 If Lock is NULL, then ASSERT().\r
378 If Lock is not initialized, then ASSERT().\r
379\r
380 @param Lock A pointer to the lock to acquire.\r
381\r
382 @retval EFI_SUCCESS The lock was acquired.\r
383 @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.\r
384\r
385**/\r
386EFI_STATUS\r
387EFIAPI\r
388EfiAcquireLockOrFail (\r
389 IN EFI_LOCK *Lock\r
390 )\r
391{\r
392\r
393 ASSERT (Lock != NULL);\r
394 ASSERT (Lock->Lock != EfiLockUninitialized);\r
395\r
396 if (Lock->Lock == EfiLockAcquired) {\r
397 //\r
398 // Lock is already owned, so bail out\r
399 //\r
400 return EFI_ACCESS_DENIED;\r
401 }\r
402\r
403 Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);\r
404\r
405 Lock->Lock = EfiLockAcquired;\r
406\r
407 return EFI_SUCCESS;\r
408}\r
409\r
410/**\r
411 Releases ownership of a lock.\r
412\r
413 This function transitions a mutual exclusion lock from the acquired state to \r
414 the released state, and restores the system's task priority level to its \r
415 previous level.\r
416 If Lock is NULL, then ASSERT().\r
417 If Lock is not initialized, then ASSERT().\r
418 If Lock is already in the released state, then ASSERT().\r
419\r
420 @param Lock A pointer to the lock to release.\r
421\r
422**/\r
423VOID\r
424EFIAPI\r
425EfiReleaseLock (\r
426 IN EFI_LOCK *Lock\r
427 )\r
428{\r
429 EFI_TPL Tpl;\r
430\r
431 ASSERT (Lock != NULL);\r
432 ASSERT (Lock->Lock == EfiLockAcquired);\r
433\r
434 Tpl = Lock->OwnerTpl;\r
435\r
436 Lock->Lock = EfiLockReleased;\r
437\r
438 gBS->RestoreTPL (Tpl);\r
439}\r
440\r
441/**\r
442 Tests whether a controller handle is being managed by a specific driver.\r
443\r
444 This function tests whether the driver specified by DriverBindingHandle is\r
445 currently managing the controller specified by ControllerHandle. This test\r
446 is performed by evaluating if the the protocol specified by ProtocolGuid is\r
447 present on ControllerHandle and is was opened by DriverBindingHandle with an\r
448 attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. \r
449 If ProtocolGuid is NULL, then ASSERT().\r
450\r
451 @param ControllerHandle A handle for a controller to test.\r
452 @param DriverBindingHandle Specifies the driver binding handle for the\r
453 driver.\r
454 @param ProtocolGuid Specifies the protocol that the driver specified\r
455 by DriverBindingHandle opens in its Start()\r
456 function.\r
457\r
458 @retval EFI_SUCCESS ControllerHandle is managed by the driver\r
459 specified by DriverBindingHandle.\r
460 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver\r
461 specified by DriverBindingHandle.\r
462\r
463**/\r
464EFI_STATUS\r
465EFIAPI\r
466EfiTestManagedDevice (\r
467 IN CONST EFI_HANDLE ControllerHandle,\r
468 IN CONST EFI_HANDLE DriverBindingHandle,\r
469 IN CONST EFI_GUID *ProtocolGuid\r
470 )\r
471{\r
472 EFI_STATUS Status;\r
473 VOID *ManagedInterface;\r
474\r
475 ASSERT (ProtocolGuid != NULL);\r
476\r
477 Status = gBS->OpenProtocol (\r
478 ControllerHandle,\r
479 (EFI_GUID *) ProtocolGuid,\r
480 &ManagedInterface,\r
481 DriverBindingHandle,\r
482 ControllerHandle,\r
483 EFI_OPEN_PROTOCOL_BY_DRIVER\r
484 );\r
485 if (!EFI_ERROR (Status)) {\r
486 gBS->CloseProtocol (\r
487 ControllerHandle,\r
488 (EFI_GUID *) ProtocolGuid,\r
489 DriverBindingHandle,\r
490 ControllerHandle\r
491 );\r
492 return EFI_UNSUPPORTED;\r
493 }\r
494\r
495 if (Status != EFI_ALREADY_STARTED) {\r
496 return EFI_UNSUPPORTED;\r
497 }\r
498\r
499 return EFI_SUCCESS;\r
500}\r
501\r
502/**\r
503 Tests whether a child handle is a child device of the controller.\r
504\r
505 This function tests whether ChildHandle is one of the children of\r
506 ControllerHandle. This test is performed by checking to see if the protocol\r
507 specified by ProtocolGuid is present on ControllerHandle and opened by\r
508 ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
509 If ProtocolGuid is NULL, then ASSERT().\r
510\r
511 @param ControllerHandle A handle for a (parent) controller to test. \r
512 @param ChildHandle A child handle to test.\r
513 @param ProtocolGuid Supplies the protocol that the child controller\r
514 opens on its parent controller. \r
515\r
516 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.\r
517 @retval EFI_UNSUPPORTED ChildHandle is not a child of the\r
518 ControllerHandle.\r
519\r
520**/\r
521EFI_STATUS\r
522EFIAPI\r
523EfiTestChildHandle (\r
524 IN CONST EFI_HANDLE ControllerHandle,\r
525 IN CONST EFI_HANDLE ChildHandle,\r
526 IN CONST EFI_GUID *ProtocolGuid\r
527 )\r
528{\r
529 EFI_STATUS Status;\r
530 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
531 UINTN EntryCount;\r
532 UINTN Index;\r
533\r
534 ASSERT (ProtocolGuid != NULL);\r
535\r
536 //\r
537 // Retrieve the list of agents that are consuming the specific protocol\r
538 // on ControllerHandle.\r
539 //\r
540 Status = gBS->OpenProtocolInformation (\r
541 ControllerHandle,\r
542 (EFI_GUID *) ProtocolGuid,\r
543 &OpenInfoBuffer,\r
544 &EntryCount\r
545 );\r
546 if (EFI_ERROR (Status)) {\r
547 return EFI_UNSUPPORTED;\r
548 }\r
549\r
550 //\r
551 // Inspect if ChildHandle is one of the agents.\r
552 //\r
553 Status = EFI_UNSUPPORTED;\r
554 for (Index = 0; Index < EntryCount; Index++) {\r
555 if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&\r
556 (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
557 Status = EFI_SUCCESS;\r
558 break;\r
559 }\r
560 }\r
561\r
562 FreePool (OpenInfoBuffer);\r
563 return Status;\r
564}\r
565\r
566/**\r
567 This function looks up a Unicode string in UnicodeStringTable.\r
568\r
569 If Language is a member of SupportedLanguages and a Unicode string is found in\r
570 UnicodeStringTable that matches the language code specified by Language, then it\r
571 is returned in UnicodeString.\r
572\r
573 @param Language A pointer to the ISO 639-2 language code for the \r
574 Unicode string to look up and return.\r
575 @param SupportedLanguages A pointer to the set of ISO 639-2 language codes \r
576 that the Unicode string table supports. Language \r
577 must be a member of this set.\r
578 @param UnicodeStringTable A pointer to the table of Unicode strings.\r
579 @param UnicodeString A pointer to the Unicode string from UnicodeStringTable\r
580 that matches the language specified by Language.\r
581\r
582 @retval EFI_SUCCESS The Unicode string that matches the language \r
583 specified by Language was found\r
584 in the table of Unicode strings UnicodeStringTable, \r
585 and it was returned in UnicodeString.\r
586 @retval EFI_INVALID_PARAMETER Language is NULL.\r
587 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
588 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
589 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL.\r
590 @retval EFI_UNSUPPORTED The language specified by Language is not a \r
591 member of SupportedLanguages.\r
592 @retval EFI_UNSUPPORTED The language specified by Language is not \r
593 supported by UnicodeStringTable.\r
594\r
595**/\r
596EFI_STATUS\r
597EFIAPI\r
598LookupUnicodeString (\r
599 IN CONST CHAR8 *Language,\r
600 IN CONST CHAR8 *SupportedLanguages,\r
601 IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable,\r
602 OUT CHAR16 **UnicodeString\r
603 )\r
604{\r
605 //\r
606 // Make sure the parameters are valid\r
607 //\r
608 if (Language == NULL || UnicodeString == NULL) {\r
609 return EFI_INVALID_PARAMETER;\r
610 }\r
611\r
612 //\r
613 // If there are no supported languages, or the Unicode String Table is empty, then the\r
614 // Unicode String specified by Language is not supported by this Unicode String Table\r
615 //\r
616 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {\r
617 return EFI_UNSUPPORTED;\r
618 }\r
619\r
620 //\r
621 // Make sure Language is in the set of Supported Languages\r
622 //\r
623 while (*SupportedLanguages != 0) {\r
624 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
625\r
626 //\r
627 // Search the Unicode String Table for the matching Language specifier\r
628 //\r
629 while (UnicodeStringTable->Language != NULL) {\r
630 if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) {\r
631\r
632 //\r
633 // A matching string was found, so return it\r
634 //\r
635 *UnicodeString = UnicodeStringTable->UnicodeString;\r
636 return EFI_SUCCESS;\r
637 }\r
638\r
639 UnicodeStringTable++;\r
640 }\r
641\r
642 return EFI_UNSUPPORTED;\r
643 }\r
644\r
645 SupportedLanguages += 3;\r
646 }\r
647\r
648 return EFI_UNSUPPORTED;\r
649}\r
650\r
651\r
652\r
653/**\r
654 This function looks up a Unicode string in UnicodeStringTable.\r
655\r
656 If Language is a member of SupportedLanguages and a Unicode string is found in\r
657 UnicodeStringTable that matches the language code specified by Language, then\r
658 it is returned in UnicodeString.\r
659\r
660 @param Language A pointer to an ASCII string containing the ISO 639-2 or the\r
661 RFC 4646 language code for the Unicode string to look up and\r
662 return. If Iso639Language is TRUE, then this ASCII string is\r
663 not assumed to be Null-terminated, and only the first three\r
664 characters are used. If Iso639Language is FALSE, then this ASCII\r
665 string must be Null-terminated. \r
666 @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains a\r
667 set of ISO 639-2 or RFC 4646 language codes that the Unicode\r
668 string table supports. Language must be a member of this set.\r
669 If Iso639Language is TRUE, then this string contains one or more\r
670 ISO 639-2 language codes with no separator characters. If Iso639Language\r
671 is FALSE, then is string contains one or more RFC 4646 language\r
672 codes separated by ';'.\r
673 @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE\r
674 is defined in "Related Definitions".\r
675 @param UnicodeString A pointer to the Null-terminated Unicode string from UnicodeStringTable\r
676 that matches the language specified by Language.\r
677 @param Iso639Language Specifies the supported language code format. If it is TRUE, then\r
678 Language and SupportedLanguages follow ISO 639-2 language code format.\r
679 Otherwise, they follow RFC 4646 language code format.\r
680\r
681\r
682 @retval EFI_SUCCESS The Unicode string that matches the language specified by Language\r
683 was found in the table of Unicode strings UnicodeStringTable, and\r
684 it was returned in UnicodeString.\r
685 @retval EFI_INVALID_PARAMETER Language is NULL. \r
686 @retval EFI_INVALID_PARAMETER UnicodeString is NULL. \r
687 @retval EFI_UNSUPPORTED SupportedLanguages is NULL. \r
688 @retval EFI_UNSUPPORTED UnicodeStringTable is NULL. \r
689 @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages. \r
690 @retval EFI_UNSUPPORTED The language specified by Language is not supported by UnicodeStringTable.\r
691\r
692**/\r
693EFI_STATUS\r
694EFIAPI\r
695LookupUnicodeString2 (\r
696 IN CONST CHAR8 *Language,\r
697 IN CONST CHAR8 *SupportedLanguages,\r
698 IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable,\r
699 OUT CHAR16 **UnicodeString,\r
700 IN BOOLEAN Iso639Language\r
701 )\r
702{\r
703 BOOLEAN Found;\r
704 UINTN Index;\r
705 CHAR8 *LanguageString;\r
706\r
707 //\r
708 // Make sure the parameters are valid\r
709 //\r
710 if (Language == NULL || UnicodeString == NULL) {\r
711 return EFI_INVALID_PARAMETER;\r
712 }\r
713\r
714 //\r
715 // If there are no supported languages, or the Unicode String Table is empty, then the\r
716 // Unicode String specified by Language is not supported by this Unicode String Table\r
717 //\r
718 if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {\r
719 return EFI_UNSUPPORTED;\r
720 }\r
721\r
722 //\r
723 // Make sure Language is in the set of Supported Languages\r
724 //\r
725 Found = FALSE;\r
726 while (*SupportedLanguages != 0) {\r
727 if (Iso639Language) {\r
728 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
729 Found = TRUE;\r
730 break;\r
731 }\r
732 SupportedLanguages += 3;\r
733 } else {\r
734 for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);\r
735 if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) {\r
736 Found = TRUE;\r
737 break;\r
738 }\r
739 SupportedLanguages += Index;\r
740 for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);\r
741 }\r
742 }\r
743\r
744 //\r
745 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED\r
746 //\r
747 if (!Found) {\r
748 return EFI_UNSUPPORTED;\r
749 }\r
750\r
751 //\r
752 // Search the Unicode String Table for the matching Language specifier\r
753 //\r
754 while (UnicodeStringTable->Language != NULL) {\r
755 LanguageString = UnicodeStringTable->Language;\r
756 while (0 != *LanguageString) {\r
757 for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);\r
758 if (AsciiStrnCmp(LanguageString, Language, Index) == 0) {\r
759 *UnicodeString = UnicodeStringTable->UnicodeString;\r
760 return EFI_SUCCESS;\r
761 }\r
762 LanguageString += Index;\r
763 for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] == ';'; Index++);\r
764 }\r
765 UnicodeStringTable++;\r
766 }\r
767\r
768 return EFI_UNSUPPORTED;\r
769}\r
770\r
771\r
772/**\r
773 This function adds a Unicode string to UnicodeStringTable.\r
774\r
775 If Language is a member of SupportedLanguages then UnicodeString is added to \r
776 UnicodeStringTable. New buffers are allocated for both Language and \r
777 UnicodeString. The contents of Language and UnicodeString are copied into \r
778 these new buffers. These buffers are automatically freed when \r
779 FreeUnicodeStringTable() is called.\r
780\r
781 @param Language A pointer to the ISO 639-2 language code for the Unicode \r
782 string to add.\r
783 @param SupportedLanguages A pointer to the set of ISO 639-2 language codes\r
784 that the Unicode string table supports.\r
785 Language must be a member of this set.\r
786 @param UnicodeStringTable A pointer to the table of Unicode strings.\r
787 @param UnicodeString A pointer to the Unicode string to add.\r
788\r
789 @retval EFI_SUCCESS The Unicode string that matches the language \r
790 specified by Language was found in the table of \r
791 Unicode strings UnicodeStringTable, and it was \r
792 returned in UnicodeString.\r
793 @retval EFI_INVALID_PARAMETER Language is NULL.\r
794 @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
795 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.\r
796 @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
797 @retval EFI_ALREADY_STARTED A Unicode string with language Language is \r
798 already present in UnicodeStringTable.\r
799 @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another \r
800 Unicode string to UnicodeStringTable.\r
801 @retval EFI_UNSUPPORTED The language specified by Language is not a \r
802 member of SupportedLanguages.\r
803\r
804**/\r
805EFI_STATUS\r
806EFIAPI\r
807AddUnicodeString (\r
808 IN CONST CHAR8 *Language,\r
809 IN CONST CHAR8 *SupportedLanguages,\r
810 IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable,\r
811 IN CONST CHAR16 *UnicodeString\r
812 )\r
813{\r
814 UINTN NumberOfEntries;\r
815 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;\r
816 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;\r
817 UINTN UnicodeStringLength;\r
818\r
819 //\r
820 // Make sure the parameter are valid\r
821 //\r
822 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {\r
823 return EFI_INVALID_PARAMETER;\r
824 }\r
825\r
826 //\r
827 // If there are no supported languages, then a Unicode String can not be added\r
828 //\r
829 if (SupportedLanguages == NULL) {\r
830 return EFI_UNSUPPORTED;\r
831 }\r
832\r
833 //\r
834 // If the Unicode String is empty, then a Unicode String can not be added\r
835 //\r
836 if (UnicodeString[0] == 0) {\r
837 return EFI_INVALID_PARAMETER;\r
838 }\r
839\r
840 //\r
841 // Make sure Language is a member of SupportedLanguages\r
842 //\r
843 while (*SupportedLanguages != 0) {\r
844 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
845\r
846 //\r
847 // Determine the size of the Unicode String Table by looking for a NULL Language entry\r
848 //\r
849 NumberOfEntries = 0;\r
850 if (*UnicodeStringTable != NULL) {\r
851 OldUnicodeStringTable = *UnicodeStringTable;\r
852 while (OldUnicodeStringTable->Language != NULL) {\r
853 if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) {\r
854 return EFI_ALREADY_STARTED;\r
855 }\r
856\r
857 OldUnicodeStringTable++;\r
858 NumberOfEntries++;\r
859 }\r
860 }\r
861\r
862 //\r
863 // Allocate space for a new Unicode String Table. It must hold the current number of\r
864 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table\r
865 // marker\r
866 //\r
867 NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));\r
868 if (NewUnicodeStringTable == NULL) {\r
869 return EFI_OUT_OF_RESOURCES;\r
870 }\r
871\r
872 //\r
873 // If the current Unicode String Table contains any entries, then copy them to the\r
874 // newly allocated Unicode String Table.\r
875 //\r
876 if (*UnicodeStringTable != NULL) {\r
877 CopyMem (\r
878 NewUnicodeStringTable,\r
879 *UnicodeStringTable,\r
880 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)\r
881 );\r
882 }\r
883\r
884 //\r
885 // Allocate space for a copy of the Language specifier\r
886 //\r
887 NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language);\r
888 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {\r
889 gBS->FreePool (NewUnicodeStringTable);\r
890 return EFI_OUT_OF_RESOURCES;\r
891 }\r
892\r
893 //\r
894 // Compute the length of the Unicode String\r
895 //\r
896 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++)\r
897 ;\r
898\r
899 //\r
900 // Allocate space for a copy of the Unicode String\r
901 //\r
902 NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (\r
903 (UnicodeStringLength + 1) * sizeof (CHAR16),\r
904 UnicodeString\r
905 );\r
906 if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {\r
907 gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);\r
908 gBS->FreePool (NewUnicodeStringTable);\r
909 return EFI_OUT_OF_RESOURCES;\r
910 }\r
911\r
912 //\r
913 // Mark the end of the Unicode String Table\r
914 //\r
915 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;\r
916 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;\r
917\r
918 //\r
919 // Free the old Unicode String Table\r
920 //\r
921 if (*UnicodeStringTable != NULL) {\r
922 gBS->FreePool (*UnicodeStringTable);\r
923 }\r
924\r
925 //\r
926 // Point UnicodeStringTable at the newly allocated Unicode String Table\r
927 //\r
928 *UnicodeStringTable = NewUnicodeStringTable;\r
929\r
930 return EFI_SUCCESS;\r
931 }\r
932\r
933 SupportedLanguages += 3;\r
934 }\r
935\r
936 return EFI_UNSUPPORTED;\r
937}\r
938\r
939\r
940/**\r
941 This function adds the Null-terminated Unicode string specified by UnicodeString\r
942 to UnicodeStringTable.\r
943\r
944 If Language is a member of SupportedLanguages then UnicodeString is added to\r
945 UnicodeStringTable. New buffers are allocated for both Language and UnicodeString.\r
946 The contents of Language and UnicodeString are copied into these new buffers.\r
947 These buffers are automatically freed when EfiLibFreeUnicodeStringTable() is called.\r
948\r
949 @param Language A pointer to an ASCII string containing the ISO 639-2 or\r
950 the RFC 4646 language code for the Unicode string to add.\r
951 If Iso639Language is TRUE, then this ASCII string is not\r
952 assumed to be Null-terminated, and only the first three\r
953 chacters are used. If Iso639Language is FALSE, then this\r
954 ASCII string must be Null-terminated.\r
955 @param SupportedLanguages A pointer to a Null-terminated ASCII string that contains\r
956 a set of ISO 639-2 or RFC 4646 language codes that the Unicode\r
957 string table supports. Language must be a member of this set.\r
958 If Iso639Language is TRUE, then this string contains one or more\r
959 ISO 639-2 language codes with no separator characters.\r
960 If Iso639Language is FALSE, then is string contains one or more\r
961 RFC 4646 language codes separated by ';'.\r
962 @param UnicodeStringTable A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE\r
963 is defined in "Related Definitions".\r
964 @param UnicodeString A pointer to the Unicode string to add. \r
965 @param Iso639Language Specifies the supported language code format. If it is TRUE,\r
966 then Language and SupportedLanguages follow ISO 639-2 language code format.\r
967 Otherwise, they follow RFC 4646 language code format.\r
968\r
969 @retval EFI_SUCCESS The Unicode string that matches the language specified by\r
970 Language was found in the table of Unicode strings UnicodeStringTable,\r
971 and it was returned in UnicodeString. \r
972 @retval EFI_INVALID_PARAMETER Language is NULL. \r
973 @retval EFI_INVALID_PARAMETER UnicodeString is NULL. \r
974 @retval EFI_INVALID_PARAMETER UnicodeString is an empty string. \r
975 @retval EFI_UNSUPPORTED SupportedLanguages is NULL. \r
976 @retval EFI_ALREADY_STARTED A Unicode string with language Language is already present in\r
977 UnicodeStringTable. \r
978 @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another Unicode string UnicodeStringTable. \r
979 @retval EFI_UNSUPPORTED The language specified by Language is not a member of SupportedLanguages.\r
980\r
981**/\r
982EFI_STATUS\r
983EFIAPI\r
984AddUnicodeString2 (\r
985 IN CONST CHAR8 *Language,\r
986 IN CONST CHAR8 *SupportedLanguages,\r
987 IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable,\r
988 IN CONST CHAR16 *UnicodeString,\r
989 IN BOOLEAN Iso639Language\r
990 )\r
991{\r
992 UINTN NumberOfEntries;\r
993 EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;\r
994 EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;\r
995 UINTN UnicodeStringLength;\r
996 BOOLEAN Found;\r
997 UINTN Index;\r
998 CHAR8 *LanguageString;\r
999\r
1000 //\r
1001 // Make sure the parameter are valid\r
1002 //\r
1003 if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {\r
1004 return EFI_INVALID_PARAMETER;\r
1005 }\r
1006\r
1007 //\r
1008 // If there are no supported languages, then a Unicode String can not be added\r
1009 //\r
1010 if (SupportedLanguages == NULL) {\r
1011 return EFI_UNSUPPORTED;\r
1012 }\r
1013\r
1014 //\r
1015 // If the Unicode String is empty, then a Unicode String can not be added\r
1016 //\r
1017 if (UnicodeString[0] == 0) {\r
1018 return EFI_INVALID_PARAMETER;\r
1019 }\r
1020\r
1021 //\r
1022 // Make sure Language is a member of SupportedLanguages\r
1023 //\r
1024 Found = FALSE;\r
1025 while (*SupportedLanguages != 0) {\r
1026 if (Iso639Language) {\r
1027 if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
1028 Found = TRUE;\r
1029 break;\r
1030 }\r
1031 SupportedLanguages += 3;\r
1032 } else {\r
1033 for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);\r
1034 if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {\r
1035 Found = TRUE;\r
1036 break;\r
1037 }\r
1038 SupportedLanguages += Index;\r
1039 for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);\r
1040 }\r
1041 }\r
1042\r
1043 //\r
1044 // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED\r
1045 //\r
1046 if (!Found) {\r
1047 return EFI_UNSUPPORTED;\r
1048 }\r
1049\r
1050 //\r
1051 // Determine the size of the Unicode String Table by looking for a NULL Language entry\r
1052 //\r
1053 NumberOfEntries = 0;\r
1054 if (*UnicodeStringTable != NULL) {\r
1055 OldUnicodeStringTable = *UnicodeStringTable;\r
1056 while (OldUnicodeStringTable->Language != NULL) {\r
1057 LanguageString = OldUnicodeStringTable->Language;\r
1058\r
1059 while (*LanguageString != 0) {\r
1060 for (Index = 0; LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);\r
1061\r
1062 if (AsciiStrnCmp (Language, LanguageString, Index) == 0) { \r
1063 return EFI_ALREADY_STARTED;\r
1064 }\r
1065 LanguageString += Index;\r
1066 for (; *LanguageString != 0 && *LanguageString == ';'; LanguageString++);\r
1067 }\r
1068 OldUnicodeStringTable++;\r
1069 NumberOfEntries++;\r
1070 }\r
1071 }\r
1072\r
1073 //\r
1074 // Allocate space for a new Unicode String Table. It must hold the current number of\r
1075 // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table\r
1076 // marker\r
1077 //\r
1078 NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));\r
1079 if (NewUnicodeStringTable == NULL) {\r
1080 return EFI_OUT_OF_RESOURCES;\r
1081 }\r
1082\r
1083 //\r
1084 // If the current Unicode String Table contains any entries, then copy them to the\r
1085 // newly allocated Unicode String Table.\r
1086 //\r
1087 if (*UnicodeStringTable != NULL) {\r
1088 CopyMem (\r
1089 NewUnicodeStringTable,\r
1090 *UnicodeStringTable,\r
1091 NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)\r
1092 );\r
1093 }\r
1094\r
1095 //\r
1096 // Allocate space for a copy of the Language specifier\r
1097 //\r
1098 NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (AsciiStrSize(Language), Language);\r
1099 if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {\r
1100 gBS->FreePool (NewUnicodeStringTable);\r
1101 return EFI_OUT_OF_RESOURCES;\r
1102 }\r
1103\r
1104 //\r
1105 // Compute the length of the Unicode String\r
1106 //\r
1107 for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++);\r
1108\r
1109 //\r
1110 // Allocate space for a copy of the Unicode String\r
1111 //\r
1112 NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (StrSize (UnicodeString), UnicodeString);\r
1113 if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {\r
1114 gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);\r
1115 gBS->FreePool (NewUnicodeStringTable);\r
1116 return EFI_OUT_OF_RESOURCES;\r
1117 }\r
1118\r
1119 //\r
1120 // Mark the end of the Unicode String Table\r
1121 //\r
1122 NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;\r
1123 NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;\r
1124\r
1125 //\r
1126 // Free the old Unicode String Table\r
1127 //\r
1128 if (*UnicodeStringTable != NULL) {\r
1129 gBS->FreePool (*UnicodeStringTable);\r
1130 }\r
1131\r
1132 //\r
1133 // Point UnicodeStringTable at the newly allocated Unicode String Table\r
1134 //\r
1135 *UnicodeStringTable = NewUnicodeStringTable;\r
1136\r
1137 return EFI_SUCCESS;\r
1138}\r
1139\r
1140/**\r
1141 This function frees the table of Unicode strings in UnicodeStringTable.\r
1142\r
1143 If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.\r
1144 Otherwise, each language code, and each Unicode string in the Unicode string \r
1145 table are freed, and EFI_SUCCESS is returned.\r
1146\r
1147 @param UnicodeStringTable A pointer to the table of Unicode strings.\r
1148\r
1149 @retval EFI_SUCCESS The Unicode string table was freed.\r
1150\r
1151**/\r
1152EFI_STATUS\r
1153EFIAPI\r
1154FreeUnicodeStringTable (\r
1155 IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable\r
1156 )\r
1157{\r
1158 UINTN Index;\r
1159\r
1160 //\r
1161 // If the Unicode String Table is NULL, then it is already freed\r
1162 //\r
1163 if (UnicodeStringTable == NULL) {\r
1164 return EFI_SUCCESS;\r
1165 }\r
1166\r
1167 //\r
1168 // Loop through the Unicode String Table until we reach the end of table marker\r
1169 //\r
1170 for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) {\r
1171\r
1172 //\r
1173 // Free the Language string from the Unicode String Table\r
1174 //\r
1175 gBS->FreePool (UnicodeStringTable[Index].Language);\r
1176\r
1177 //\r
1178 // Free the Unicode String from the Unicode String Table\r
1179 //\r
1180 if (UnicodeStringTable[Index].UnicodeString != NULL) {\r
1181 gBS->FreePool (UnicodeStringTable[Index].UnicodeString);\r
1182 }\r
1183 }\r
1184\r
1185 //\r
1186 // Free the Unicode String Table itself\r
1187 //\r
1188 gBS->FreePool (UnicodeStringTable);\r
1189\r
1190 return EFI_SUCCESS;\r
1191}\r
1192\r
1193/**\r
1194 Returns a pointer to an allocated buffer that contains the contents of a \r
1195 variable retrieved through the UEFI Runtime Service GetVariable(). The \r
1196 returned buffer is allocated using AllocatePool(). The caller is responsible\r
1197 for freeing this buffer with FreePool().\r
1198\r
1199 If Name is NULL, then ASSERT().\r
1200 If Guid is NULL, then ASSERT().\r
1201\r
1202 @param[in] Name Pointer to a Null-terminated Unicode string.\r
1203 @param[in] Guid Pointer to an EFI_GUID structure\r
1204\r
1205 @retval NULL The variable could not be retrieved.\r
1206 @retval NULL There are not enough resources available for the variable contents.\r
1207 @retval Other A pointer to allocated buffer containing the variable contents.\r
1208\r
1209**/\r
1210VOID *\r
1211EFIAPI\r
1212GetVariable (\r
1213 IN CONST CHAR16 *Name,\r
1214 IN CONST EFI_GUID *Guid\r
1215 )\r
1216{\r
1217 EFI_STATUS Status;\r
1218 UINTN Size;\r
1219 VOID *Value;\r
1220\r
1221 ASSERT (Name != NULL);\r
1222 ASSERT (Guid != NULL);\r
1223\r
1224 //\r
1225 // Try to get the variable size.\r
1226 //\r
1227 Value = NULL;\r
1228 Size = 0;\r
1229 Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value);\r
1230 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1231 return NULL;\r
1232 }\r
1233\r
1234 //\r
1235 // Allocate buffer to get the variable.\r
1236 //\r
1237 Value = AllocatePool (Size);\r
1238 if (Value == NULL) {\r
1239 return NULL;\r
1240 }\r
1241\r
1242 //\r
1243 // Get the variable data.\r
1244 //\r
1245 Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value);\r
1246 if (EFI_ERROR (Status)) {\r
1247 FreePool(Value);\r
1248 return NULL;\r
1249 }\r
1250\r
1251 return Value;\r
1252}\r
1253\r
1254\r
1255/**\r
1256 Returns a pointer to an allocated buffer that contains the contents of a \r
1257 variable retrieved through the UEFI Runtime Service GetVariable(). This \r
1258 function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables.\r
1259 The returned buffer is allocated using AllocatePool(). The caller is \r
1260 responsible for freeing this buffer with FreePool().\r
1261\r
1262 If Name is NULL, then ASSERT().\r
1263\r
1264 @param[in] Name Pointer to a Null-terminated Unicode string.\r
1265\r
1266 @retval NULL The variable could not be retrieved.\r
1267 @retval NULL There are not enough resources available for the variable contents.\r
1268 @retval Other A pointer to allocated buffer containing the variable contents.\r
1269\r
1270**/\r
1271VOID *\r
1272EFIAPI\r
1273GetEfiGlobalVariable (\r
1274 IN CONST CHAR16 *Name\r
1275 )\r
1276{\r
1277 return GetVariable (Name, &gEfiGlobalVariableGuid);\r
1278}\r
1279\r
1280\r
1281/**\r
1282 Returns a pointer to an allocated buffer that contains the best matching language \r
1283 from a set of supported languages. \r
1284 \r
1285 This function supports both ISO 639-2 and RFC 4646 language codes, but language \r
1286 code types may not be mixed in a single call to this function. The language \r
1287 code returned is allocated using AllocatePool(). The caller is responsible for \r
1288 freeing the allocated buffer using FreePool(). This function supports a variable\r
1289 argument list that allows the caller to pass in a prioritized list of language \r
1290 codes to test against all the language codes in SupportedLanguages. \r
1291\r
1292 If SupportedLanguages is NULL, then ASSERT().\r
1293\r
1294 @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that\r
1295 contains a set of language codes in the format \r
1296 specified by Iso639Language.\r
1297 @param[in] Iso639Language If TRUE, then all language codes are assumed to be\r
1298 in ISO 639-2 format. If FALSE, then all language\r
1299 codes are assumed to be in RFC 4646 language format\r
1300 @param[in] ... A variable argument list that contains pointers to \r
1301 Null-terminated ASCII strings that contain one or more\r
1302 language codes in the format specified by Iso639Language.\r
1303 The first language code from each of these language\r
1304 code lists is used to determine if it is an exact or\r
1305 close match to any of the language codes in \r
1306 SupportedLanguages. Close matches only apply to RFC 4646\r
1307 language codes, and the matching algorithm from RFC 4647\r
1308 is used to determine if a close match is present. If \r
1309 an exact or close match is found, then the matching\r
1310 language code from SupportedLanguages is returned. If\r
1311 no matches are found, then the next variable argument\r
1312 parameter is evaluated. The variable argument list \r
1313 is terminated by a NULL.\r
1314\r
1315 @retval NULL The best matching language could not be found in SupportedLanguages.\r
1316 @retval NULL There are not enough resources available to return the best matching \r
1317 language.\r
1318 @retval Other A pointer to a Null-terminated ASCII string that is the best matching \r
1319 language in SupportedLanguages.\r
1320\r
1321**/\r
1322CHAR8 *\r
1323EFIAPI\r
1324GetBestLanguage (\r
1325 IN CONST CHAR8 *SupportedLanguages, \r
1326 IN BOOLEAN Iso639Language,\r
1327 ...\r
1328 )\r
1329{\r
1330 VA_LIST Args;\r
1331 CHAR8 *Language;\r
1332 UINTN CompareLength;\r
1333 UINTN LanguageLength;\r
1334 CONST CHAR8 *Supported;\r
1335 CHAR8 *BestLanguage;\r
1336\r
1337 ASSERT (SupportedLanguages != NULL);\r
1338\r
1339 VA_START (Args, Iso639Language);\r
1340 while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {\r
1341 //\r
1342 // Default to ISO 639-2 mode\r
1343 //\r
1344 CompareLength = 3;\r
1345 LanguageLength = MIN (3, AsciiStrLen (Language));\r
1346\r
1347 //\r
1348 // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language\r
1349 //\r
1350 if (!Iso639Language) {\r
1351 for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);\r
1352 }\r
1353\r
1354 //\r
1355 // Trim back the length of Language used until it is empty\r
1356 //\r
1357 while (LanguageLength > 0) {\r
1358 //\r
1359 // Loop through all language codes in SupportedLanguages\r
1360 //\r
1361 for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {\r
1362 //\r
1363 // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages\r
1364 //\r
1365 if (!Iso639Language) {\r
1366 //\r
1367 // Skip ';' characters in Supported\r
1368 //\r
1369 for (; *Supported != '\0' && *Supported == ';'; Supported++);\r
1370 //\r
1371 // Determine the length of the next language code in Supported\r
1372 //\r
1373 for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);\r
1374 //\r
1375 // If Language is longer than the Supported, then skip to the next language\r
1376 //\r
1377 if (LanguageLength > CompareLength) {\r
1378 continue;\r
1379 }\r
1380 }\r
1381 //\r
1382 // See if the first LanguageLength characters in Supported match Language\r
1383 //\r
1384 if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {\r
1385 VA_END (Args);\r
1386 //\r
1387 // Allocate, copy, and return the best matching language code from SupportedLanguages\r
1388 //\r
1389 BestLanguage = AllocateZeroPool (CompareLength + 1);\r
1390 if (BestLanguage == NULL) {\r
1391 return NULL;\r
1392 }\r
1393 return CopyMem (BestLanguage, Supported, CompareLength);\r
1394 }\r
1395 }\r
1396\r
1397 if (Iso639Language) {\r
1398 //\r
1399 // If ISO 639 mode, then each language can only be tested once\r
1400 //\r
1401 LanguageLength = 0;\r
1402 } else {\r
1403 //\r
1404 // If RFC 4646 mode, then trim Language from the right to the next '-' character \r
1405 //\r
1406 for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);\r
1407 }\r
1408 }\r
1409 }\r
1410 VA_END (Args);\r
1411\r
1412 //\r
1413 // No matches were found \r
1414 //\r
1415 return NULL;\r
1416}\r
1417\r
1418/**\r
1419 An empty function to pass error checking of CreateEventEx ().\r
1420\r
1421 This empty function ensures that EVT_NOTIFY_SIGNAL_ALL is error\r
1422 checked correctly since it is now mapped into CreateEventEx() in UEFI 2.0.\r
1423\r
1424 @param Event Event whose notification function is being invoked.\r
1425 @param Context Pointer to the notification function's context,\r
1426 which is implementation-dependent.\r
1427\r
1428**/\r
1429VOID\r
1430EFIAPI\r
1431InternalEmptyFunction (\r
1432 IN EFI_EVENT Event,\r
1433 IN VOID *Context\r
1434 )\r
1435{\r
1436}\r