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