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   Returns the current TPL.
    309 
    310   This function returns the current TPL.  There is no EFI service to directly
    311   retrieve the current TPL. Instead, the RaiseTPL() function is used to raise
    312   the TPL to TPL_HIGH_LEVEL.  This will return the current TPL.  The TPL level
    313   can then immediately be restored back to the current TPL level with a call
    314   to RestoreTPL().
    315 
    316   @return The current TPL.
    317 
    318 **/
    319 EFI_TPL
    320 EFIAPI
    321 EfiGetCurrentTpl (
    322   VOID
    323   )
    324 {
    325   EFI_TPL Tpl;
    326 
    327   Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
    328   gBS->RestoreTPL (Tpl);
    329 
    330   return Tpl;
    331 }
    332 
    333 
    334 /**
    335   Initializes a basic mutual exclusion lock.
    336 
    337   This function initializes a basic mutual exclusion lock to the released state
    338   and returns the lock.  Each lock provides mutual exclusion access at its task
    339   priority level.  Since there is no preemption or multiprocessor support in EFI,
    340   acquiring the lock only consists of raising to the locks TPL.
    341   If Lock is NULL, then ASSERT().
    342   If Priority is not a valid TPL value, then ASSERT().
    343 
    344   @param  Lock       A pointer to the lock data structure to initialize.
    345   @param  Priority   EFI TPL is associated with the lock.
    346 
    347   @return The lock.
    348 
    349 **/
    350 EFI_LOCK *
    351 EFIAPI
    352 EfiInitializeLock (
    353   IN OUT EFI_LOCK  *Lock,
    354   IN EFI_TPL        Priority
    355   )
    356 {
    357   ASSERT (Lock != NULL);
    358   ASSERT (Priority <= TPL_HIGH_LEVEL);
    359 
    360   Lock->Tpl       = Priority;
    361   Lock->OwnerTpl  = TPL_APPLICATION;
    362   Lock->Lock      = EfiLockReleased ;
    363   return Lock;
    364 }
    365 
    366 /**
    367   Acquires ownership of a lock.
    368 
    369   This function raises the system's current task priority level to the task
    370   priority level of the mutual exclusion lock.  Then, it places the lock in the
    371   acquired state.
    372   If Lock is NULL, then ASSERT().
    373   If Lock is not initialized, then ASSERT().
    374   If Lock is already in the acquired state, then ASSERT().
    375 
    376   @param  Lock              A pointer to the lock to acquire.
    377 
    378 **/
    379 VOID
    380 EFIAPI
    381 EfiAcquireLock (
    382   IN EFI_LOCK  *Lock
    383   )
    384 {
    385   ASSERT (Lock != NULL);
    386   ASSERT (Lock->Lock == EfiLockReleased);
    387 
    388   Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);
    389   Lock->Lock     = EfiLockAcquired;
    390 }
    391 
    392 /**
    393   Acquires ownership of a lock.
    394 
    395   This function raises the system's current task priority level to the task priority
    396   level of the mutual exclusion lock.  Then, it attempts to place the lock in the acquired state.
    397   If the lock is already in the acquired state, then EFI_ACCESS_DENIED is returned.
    398   Otherwise, EFI_SUCCESS is returned.
    399   If Lock is NULL, then ASSERT().
    400   If Lock is not initialized, then ASSERT().
    401 
    402   @param  Lock              A pointer to the lock to acquire.
    403 
    404   @retval EFI_SUCCESS       The lock was acquired.
    405   @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
    406 
    407 **/
    408 EFI_STATUS
    409 EFIAPI
    410 EfiAcquireLockOrFail (
    411   IN EFI_LOCK  *Lock
    412   )
    413 {
    414 
    415   ASSERT (Lock != NULL);
    416   ASSERT (Lock->Lock != EfiLockUninitialized);
    417 
    418   if (Lock->Lock == EfiLockAcquired) {
    419     //
    420     // Lock is already owned, so bail out
    421     //
    422     return EFI_ACCESS_DENIED;
    423   }
    424 
    425   Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);
    426 
    427   Lock->Lock = EfiLockAcquired;
    428 
    429   return EFI_SUCCESS;
    430 }
    431 
    432 /**
    433   Releases ownership of a lock.
    434 
    435   This function transitions a mutual exclusion lock from the acquired state to
    436   the released state, and restores the system's task priority level to its
    437   previous level.
    438   If Lock is NULL, then ASSERT().
    439   If Lock is not initialized, then ASSERT().
    440   If Lock is already in the released state, then ASSERT().
    441 
    442   @param  Lock  A pointer to the lock to release.
    443 
    444 **/
    445 VOID
    446 EFIAPI
    447 EfiReleaseLock (
    448   IN EFI_LOCK  *Lock
    449   )
    450 {
    451   EFI_TPL Tpl;
    452 
    453   ASSERT (Lock != NULL);
    454   ASSERT (Lock->Lock == EfiLockAcquired);
    455 
    456   Tpl = Lock->OwnerTpl;
    457 
    458   Lock->Lock = EfiLockReleased;
    459 
    460   gBS->RestoreTPL (Tpl);
    461 }
    462 
    463 /**
    464   Tests whether a controller handle is being managed by a specific driver.
    465 
    466   This function tests whether the driver specified by DriverBindingHandle is
    467   currently managing the controller specified by ControllerHandle.  This test
    468   is performed by evaluating if the the protocol specified by ProtocolGuid is
    469   present on ControllerHandle and is was opened by DriverBindingHandle with an
    470   attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
    471   If ProtocolGuid is NULL, then ASSERT().
    472 
    473   @param  ControllerHandle     A handle for a controller to test.
    474   @param  DriverBindingHandle  Specifies the driver binding handle for the
    475                                driver.
    476   @param  ProtocolGuid         Specifies the protocol that the driver specified
    477                                by DriverBindingHandle opens in its Start()
    478                                function.
    479 
    480   @retval EFI_SUCCESS          ControllerHandle is managed by the driver
    481                                specified by DriverBindingHandle.
    482   @retval EFI_UNSUPPORTED      ControllerHandle is not managed by the driver
    483                                specified by DriverBindingHandle.
    484 
    485 **/
    486 EFI_STATUS
    487 EFIAPI
    488 EfiTestManagedDevice (
    489   IN CONST EFI_HANDLE       ControllerHandle,
    490   IN CONST EFI_HANDLE       DriverBindingHandle,
    491   IN CONST EFI_GUID         *ProtocolGuid
    492   )
    493 {
    494   EFI_STATUS     Status;
    495   VOID           *ManagedInterface;
    496 
    497   ASSERT (ProtocolGuid != NULL);
    498 
    499   Status = gBS->OpenProtocol (
    500                   ControllerHandle,
    501                   (EFI_GUID *) ProtocolGuid,
    502                   &ManagedInterface,
    503                   DriverBindingHandle,
    504                   ControllerHandle,
    505                   EFI_OPEN_PROTOCOL_BY_DRIVER
    506                   );
    507   if (!EFI_ERROR (Status)) {
    508     gBS->CloseProtocol (
    509            ControllerHandle,
    510            (EFI_GUID *) ProtocolGuid,
    511            DriverBindingHandle,
    512            ControllerHandle
    513            );
    514     return EFI_UNSUPPORTED;
    515   }
    516 
    517   if (Status != EFI_ALREADY_STARTED) {
    518     return EFI_UNSUPPORTED;
    519   }
    520 
    521   return EFI_SUCCESS;
    522 }
    523 
    524 /**
    525   Tests whether a child handle is a child device of the controller.
    526 
    527   This function tests whether ChildHandle is one of the children of
    528   ControllerHandle.  This test is performed by checking to see if the protocol
    529   specified by ProtocolGuid is present on ControllerHandle and opened by
    530   ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    531   If ProtocolGuid is NULL, then ASSERT().
    532 
    533   @param  ControllerHandle     A handle for a (parent) controller to test.
    534   @param  ChildHandle          A child handle to test.
    535   @param  ProtocolGuid         Supplies the protocol that the child controller
    536                                opens on its parent controller.
    537 
    538   @retval EFI_SUCCESS          ChildHandle is a child of the ControllerHandle.
    539   @retval EFI_UNSUPPORTED      ChildHandle is not a child of the
    540                                ControllerHandle.
    541 
    542 **/
    543 EFI_STATUS
    544 EFIAPI
    545 EfiTestChildHandle (
    546   IN CONST EFI_HANDLE       ControllerHandle,
    547   IN CONST EFI_HANDLE       ChildHandle,
    548   IN CONST EFI_GUID         *ProtocolGuid
    549   )
    550 {
    551   EFI_STATUS                            Status;
    552   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY   *OpenInfoBuffer;
    553   UINTN                                 EntryCount;
    554   UINTN                                 Index;
    555 
    556   ASSERT (ProtocolGuid != NULL);
    557 
    558   //
    559   // Retrieve the list of agents that are consuming the specific protocol
    560   // on ControllerHandle.
    561   //
    562   Status = gBS->OpenProtocolInformation (
    563                   ControllerHandle,
    564                   (EFI_GUID *) ProtocolGuid,
    565                   &OpenInfoBuffer,
    566                   &EntryCount
    567                   );
    568   if (EFI_ERROR (Status)) {
    569     return EFI_UNSUPPORTED;
    570   }
    571 
    572   //
    573   // Inspect if ChildHandle is one of the agents.
    574   //
    575   Status = EFI_UNSUPPORTED;
    576   for (Index = 0; Index < EntryCount; Index++) {
    577     if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&
    578         (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
    579       Status = EFI_SUCCESS;
    580       break;
    581     }
    582   }
    583 
    584   FreePool (OpenInfoBuffer);
    585   return Status;
    586 }
    587 
    588 /**
    589   This function looks up a Unicode string in UnicodeStringTable.
    590 
    591   If Language is a member of SupportedLanguages and a Unicode string is found in
    592   UnicodeStringTable that matches the language code specified by Language, then it
    593   is returned in UnicodeString.
    594 
    595   @param  Language                A pointer to the ISO 639-2 language code for the
    596                                   Unicode string to look up and return.
    597   @param  SupportedLanguages      A pointer to the set of ISO 639-2 language codes
    598                                   that the Unicode string table supports.  Language
    599                                   must be a member of this set.
    600   @param  UnicodeStringTable      A pointer to the table of Unicode strings.
    601   @param  UnicodeString           A pointer to the Unicode string from UnicodeStringTable
    602                                   that matches the language specified by Language.
    603 
    604   @retval EFI_SUCCESS             The Unicode string that matches the language
    605                                   specified by Language was found
    606                                   in the table of Unicode strings UnicodeStringTable,
    607                                   and it was returned in UnicodeString.
    608   @retval EFI_INVALID_PARAMETER   Language is NULL.
    609   @retval EFI_INVALID_PARAMETER   UnicodeString is NULL.
    610   @retval EFI_UNSUPPORTED         SupportedLanguages is NULL.
    611   @retval EFI_UNSUPPORTED         UnicodeStringTable is NULL.
    612   @retval EFI_UNSUPPORTED         The language specified by Language is not a
    613                                   member of SupportedLanguages.
    614   @retval EFI_UNSUPPORTED         The language specified by Language is not
    615                                   supported by UnicodeStringTable.
    616 
    617 **/
    618 EFI_STATUS
    619 EFIAPI
    620 LookupUnicodeString (
    621   IN CONST CHAR8                     *Language,
    622   IN CONST CHAR8                     *SupportedLanguages,
    623   IN CONST EFI_UNICODE_STRING_TABLE  *UnicodeStringTable,
    624   OUT CHAR16                         **UnicodeString
    625   )
    626 {
    627   //
    628   // Make sure the parameters are valid
    629   //
    630   if (Language == NULL || UnicodeString == NULL) {
    631     return EFI_INVALID_PARAMETER;
    632   }
    633 
    634   //
    635   // If there are no supported languages, or the Unicode String Table is empty, then the
    636   // Unicode String specified by Language is not supported by this Unicode String Table
    637   //
    638   if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
    639     return EFI_UNSUPPORTED;
    640   }
    641 
    642   //
    643   // Make sure Language is in the set of Supported Languages
    644   //
    645   while (*SupportedLanguages != 0) {
    646     if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
    647 
    648       //
    649       // Search the Unicode String Table for the matching Language specifier
    650       //
    651       while (UnicodeStringTable->Language != NULL) {
    652         if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) {
    653 
    654           //
    655           // A matching string was found, so return it
    656           //
    657           *UnicodeString = UnicodeStringTable->UnicodeString;
    658           return EFI_SUCCESS;
    659         }
    660 
    661         UnicodeStringTable++;
    662       }
    663 
    664       return EFI_UNSUPPORTED;
    665     }
    666 
    667     SupportedLanguages += 3;
    668   }
    669 
    670   return EFI_UNSUPPORTED;
    671 }
    672 
    673 
    674 
    675 /**
    676   This function looks up a Unicode string in UnicodeStringTable.
    677 
    678   If Language is a member of SupportedLanguages and a Unicode string is found in
    679   UnicodeStringTable that matches the language code specified by Language, then
    680   it is returned in UnicodeString.
    681 
    682   @param  Language             A pointer to an ASCII string containing the ISO 639-2 or the
    683                                RFC 4646 language code for the Unicode string to look up and
    684                                return. If Iso639Language is TRUE, then this ASCII string is
    685                                not assumed to be Null-terminated, and only the first three
    686                                characters are used. If Iso639Language is FALSE, then this ASCII
    687                                string must be Null-terminated.
    688   @param  SupportedLanguages   A pointer to a Null-terminated ASCII string that contains a
    689                                set of ISO 639-2 or RFC 4646 language codes that the Unicode
    690                                string table supports.  Language must be a member of this set.
    691                                If Iso639Language is TRUE, then this string contains one or more
    692                                ISO 639-2 language codes with no separator characters. If Iso639Language
    693                                is FALSE, then is string contains one or more RFC 4646 language
    694                                codes separated by ';'.
    695   @param  UnicodeStringTable   A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE
    696                                is defined in "Related Definitions".
    697   @param  UnicodeString        A pointer to the Null-terminated Unicode string from UnicodeStringTable
    698                                that matches the language specified by Language.
    699   @param  Iso639Language       Specifies the supported language code format. If it is TRUE, then
    700                                Language and SupportedLanguages follow ISO 639-2 language code format.
    701                                Otherwise, they follow RFC 4646 language code format.
    702 
    703 
    704   @retval  EFI_SUCCESS            The Unicode string that matches the language specified by Language
    705                                   was found in the table of Unicode strings UnicodeStringTable, and
    706                                   it was returned in UnicodeString.
    707   @retval  EFI_INVALID_PARAMETER  Language is NULL.
    708   @retval  EFI_INVALID_PARAMETER  UnicodeString is NULL.
    709   @retval  EFI_UNSUPPORTED        SupportedLanguages is NULL.
    710   @retval  EFI_UNSUPPORTED        UnicodeStringTable is NULL.
    711   @retval  EFI_UNSUPPORTED        The language specified by Language is not a member of SupportedLanguages.
    712   @retval  EFI_UNSUPPORTED        The language specified by Language is not supported by UnicodeStringTable.
    713 
    714 **/
    715 EFI_STATUS
    716 EFIAPI
    717 LookupUnicodeString2 (
    718   IN CONST CHAR8                     *Language,
    719   IN CONST CHAR8                     *SupportedLanguages,
    720   IN CONST EFI_UNICODE_STRING_TABLE  *UnicodeStringTable,
    721   OUT CHAR16                         **UnicodeString,
    722   IN BOOLEAN                         Iso639Language
    723   )
    724 {
    725   BOOLEAN   Found;
    726   UINTN     Index;
    727   CHAR8     *LanguageString;
    728 
    729   //
    730   // Make sure the parameters are valid
    731   //
    732   if (Language == NULL || UnicodeString == NULL) {
    733     return EFI_INVALID_PARAMETER;
    734   }
    735 
    736   //
    737   // If there are no supported languages, or the Unicode String Table is empty, then the
    738   // Unicode String specified by Language is not supported by this Unicode String Table
    739   //
    740   if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
    741     return EFI_UNSUPPORTED;
    742   }
    743 
    744   //
    745   // Make sure Language is in the set of Supported Languages
    746   //
    747   Found = FALSE;
    748   while (*SupportedLanguages != 0) {
    749     if (Iso639Language) {
    750       if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
    751         Found = TRUE;
    752         break;
    753       }
    754       SupportedLanguages += 3;
    755     } else {
    756       for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);
    757       if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) {
    758         Found = TRUE;
    759         break;
    760       }
    761       SupportedLanguages += Index;
    762       for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);
    763     }
    764   }
    765 
    766   //
    767   // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
    768   //
    769   if (!Found) {
    770     return EFI_UNSUPPORTED;
    771   }
    772 
    773   //
    774   // Search the Unicode String Table for the matching Language specifier
    775   //
    776   while (UnicodeStringTable->Language != NULL) {
    777     LanguageString = UnicodeStringTable->Language;
    778     while (0 != *LanguageString) {
    779       for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);
    780       if (AsciiStrnCmp(LanguageString, Language, Index) == 0) {
    781         *UnicodeString = UnicodeStringTable->UnicodeString;
    782         return EFI_SUCCESS;
    783       }
    784       LanguageString += Index;
    785       for (Index = 0 ;LanguageString[Index] != 0 && LanguageString[Index] == ';'; Index++);
    786     }
    787     UnicodeStringTable++;
    788   }
    789 
    790   return EFI_UNSUPPORTED;
    791 }
    792 
    793 
    794 /**
    795   This function adds a Unicode string to UnicodeStringTable.
    796 
    797   If Language is a member of SupportedLanguages then UnicodeString is added to
    798   UnicodeStringTable.  New buffers are allocated for both Language and
    799   UnicodeString.  The contents of Language and UnicodeString are copied into
    800   these new buffers.  These buffers are automatically freed when
    801   FreeUnicodeStringTable() is called.
    802 
    803   @param  Language                A pointer to the ISO 639-2 language code for the Unicode
    804                                   string to add.
    805   @param  SupportedLanguages      A pointer to the set of ISO 639-2 language codes
    806                                   that the Unicode string table supports.
    807                                   Language must be a member of this set.
    808   @param  UnicodeStringTable      A pointer to the table of Unicode strings.
    809   @param  UnicodeString           A pointer to the Unicode string to add.
    810 
    811   @retval EFI_SUCCESS             The Unicode string that matches the language
    812                                   specified by Language was found in the table of
    813                                   Unicode strings UnicodeStringTable, and it was
    814                                   returned in UnicodeString.
    815   @retval EFI_INVALID_PARAMETER   Language is NULL.
    816   @retval EFI_INVALID_PARAMETER   UnicodeString is NULL.
    817   @retval EFI_INVALID_PARAMETER   UnicodeString is an empty string.
    818   @retval EFI_UNSUPPORTED         SupportedLanguages is NULL.
    819   @retval EFI_ALREADY_STARTED     A Unicode string with language Language is
    820                                   already present in UnicodeStringTable.
    821   @retval EFI_OUT_OF_RESOURCES    There is not enough memory to add another
    822                                   Unicode string to UnicodeStringTable.
    823   @retval EFI_UNSUPPORTED         The language specified by Language is not a
    824                                   member of SupportedLanguages.
    825 
    826 **/
    827 EFI_STATUS
    828 EFIAPI
    829 AddUnicodeString (
    830   IN CONST CHAR8               *Language,
    831   IN CONST CHAR8               *SupportedLanguages,
    832   IN EFI_UNICODE_STRING_TABLE  **UnicodeStringTable,
    833   IN CONST CHAR16              *UnicodeString
    834   )
    835 {
    836   UINTN                     NumberOfEntries;
    837   EFI_UNICODE_STRING_TABLE  *OldUnicodeStringTable;
    838   EFI_UNICODE_STRING_TABLE  *NewUnicodeStringTable;
    839   UINTN                     UnicodeStringLength;
    840 
    841   //
    842   // Make sure the parameter are valid
    843   //
    844   if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {
    845     return EFI_INVALID_PARAMETER;
    846   }
    847 
    848   //
    849   // If there are no supported languages, then a Unicode String can not be added
    850   //
    851   if (SupportedLanguages == NULL) {
    852     return EFI_UNSUPPORTED;
    853   }
    854 
    855   //
    856   // If the Unicode String is empty, then a Unicode String can not be added
    857   //
    858   if (UnicodeString[0] == 0) {
    859     return EFI_INVALID_PARAMETER;
    860   }
    861 
    862   //
    863   // Make sure Language is a member of SupportedLanguages
    864   //
    865   while (*SupportedLanguages != 0) {
    866     if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
    867 
    868       //
    869       // Determine the size of the Unicode String Table by looking for a NULL Language entry
    870       //
    871       NumberOfEntries = 0;
    872       if (*UnicodeStringTable != NULL) {
    873         OldUnicodeStringTable = *UnicodeStringTable;
    874         while (OldUnicodeStringTable->Language != NULL) {
    875           if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) {
    876             return EFI_ALREADY_STARTED;
    877           }
    878 
    879           OldUnicodeStringTable++;
    880           NumberOfEntries++;
    881         }
    882       }
    883 
    884       //
    885       // Allocate space for a new Unicode String Table.  It must hold the current number of
    886       // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
    887       // marker
    888       //
    889       NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));
    890       if (NewUnicodeStringTable == NULL) {
    891         return EFI_OUT_OF_RESOURCES;
    892       }
    893 
    894       //
    895       // If the current Unicode String Table contains any entries, then copy them to the
    896       // newly allocated Unicode String Table.
    897       //
    898       if (*UnicodeStringTable != NULL) {
    899         CopyMem (
    900            NewUnicodeStringTable,
    901            *UnicodeStringTable,
    902            NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)
    903            );
    904       }
    905 
    906       //
    907       // Allocate space for a copy of the Language specifier
    908       //
    909       NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language);
    910       if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {
    911         FreePool (NewUnicodeStringTable);
    912         return EFI_OUT_OF_RESOURCES;
    913       }
    914 
    915       //
    916       // Compute the length of the Unicode String
    917       //
    918       for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++)
    919         ;
    920 
    921       //
    922       // Allocate space for a copy of the Unicode String
    923       //
    924       NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (
    925                                                               (UnicodeStringLength + 1) * sizeof (CHAR16),
    926                                                               UnicodeString
    927                                                               );
    928       if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {
    929         FreePool (NewUnicodeStringTable[NumberOfEntries].Language);
    930         FreePool (NewUnicodeStringTable);
    931         return EFI_OUT_OF_RESOURCES;
    932       }
    933 
    934       //
    935       // Mark the end of the Unicode String Table
    936       //
    937       NewUnicodeStringTable[NumberOfEntries + 1].Language       = NULL;
    938       NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString  = NULL;
    939 
    940       //
    941       // Free the old Unicode String Table
    942       //
    943       if (*UnicodeStringTable != NULL) {
    944         FreePool (*UnicodeStringTable);
    945       }
    946 
    947       //
    948       // Point UnicodeStringTable at the newly allocated Unicode String Table
    949       //
    950       *UnicodeStringTable = NewUnicodeStringTable;
    951 
    952       return EFI_SUCCESS;
    953     }
    954 
    955     SupportedLanguages += 3;
    956   }
    957 
    958   return EFI_UNSUPPORTED;
    959 }
    960 
    961 
    962 /**
    963   This function adds the Null-terminated Unicode string specified by UnicodeString
    964   to UnicodeStringTable.
    965 
    966   If Language is a member of SupportedLanguages then UnicodeString is added to
    967   UnicodeStringTable.  New buffers are allocated for both Language and UnicodeString.
    968   The contents of Language and UnicodeString are copied into these new buffers.
    969   These buffers are automatically freed when EfiLibFreeUnicodeStringTable() is called.
    970 
    971   @param  Language            A pointer to an ASCII string containing the ISO 639-2 or
    972                               the RFC 4646 language code for the Unicode string to add.
    973                               If Iso639Language is TRUE, then this ASCII string is not
    974                               assumed to be Null-terminated, and only the first three
    975                               chacters are used. If Iso639Language is FALSE, then this
    976                               ASCII string must be Null-terminated.
    977   @param  SupportedLanguages  A pointer to a Null-terminated ASCII string that contains
    978                               a set of ISO 639-2 or RFC 4646 language codes that the Unicode
    979                               string table supports.  Language must be a member of this set.
    980                               If Iso639Language is TRUE, then this string contains one or more
    981                               ISO 639-2 language codes with no separator characters.
    982                               If Iso639Language is FALSE, then is string contains one or more
    983                               RFC 4646 language codes separated by ';'.
    984   @param  UnicodeStringTable  A pointer to the table of Unicode strings. Type EFI_UNICODE_STRING_TABLE
    985                               is defined in "Related Definitions".
    986   @param  UnicodeString       A pointer to the Unicode string to add.
    987   @param  Iso639Language      Specifies the supported language code format. If it is TRUE,
    988                               then Language and SupportedLanguages follow ISO 639-2 language code format.
    989                               Otherwise, they follow RFC 4646 language code format.
    990 
    991   @retval EFI_SUCCESS            The Unicode string that matches the language specified by
    992                                  Language was found in the table of Unicode strings UnicodeStringTable,
    993                                  and it was returned in UnicodeString.
    994   @retval EFI_INVALID_PARAMETER  Language is NULL.
    995   @retval EFI_INVALID_PARAMETER  UnicodeString is NULL.
    996   @retval EFI_INVALID_PARAMETER  UnicodeString is an empty string.
    997   @retval EFI_UNSUPPORTED        SupportedLanguages is NULL.
    998   @retval EFI_ALREADY_STARTED    A Unicode string with language Language is already present in
    999                                  UnicodeStringTable.
   1000   @retval EFI_OUT_OF_RESOURCES   There is not enough memory to add another Unicode string UnicodeStringTable.
   1001   @retval EFI_UNSUPPORTED        The language specified by Language is not a member of SupportedLanguages.
   1002 
   1003 **/
   1004 EFI_STATUS
   1005 EFIAPI
   1006 AddUnicodeString2 (
   1007   IN CONST CHAR8               *Language,
   1008   IN CONST CHAR8               *SupportedLanguages,
   1009   IN EFI_UNICODE_STRING_TABLE  **UnicodeStringTable,
   1010   IN CONST CHAR16              *UnicodeString,
   1011   IN BOOLEAN                   Iso639Language
   1012   )
   1013 {
   1014   UINTN                     NumberOfEntries;
   1015   EFI_UNICODE_STRING_TABLE  *OldUnicodeStringTable;
   1016   EFI_UNICODE_STRING_TABLE  *NewUnicodeStringTable;
   1017   UINTN                     UnicodeStringLength;
   1018   BOOLEAN                   Found;
   1019   UINTN                     Index;
   1020   CHAR8                     *LanguageString;
   1021 
   1022   //
   1023   // Make sure the parameter are valid
   1024   //
   1025   if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {
   1026     return EFI_INVALID_PARAMETER;
   1027   }
   1028 
   1029   //
   1030   // If there are no supported languages, then a Unicode String can not be added
   1031   //
   1032   if (SupportedLanguages == NULL) {
   1033     return EFI_UNSUPPORTED;
   1034   }
   1035 
   1036   //
   1037   // If the Unicode String is empty, then a Unicode String can not be added
   1038   //
   1039   if (UnicodeString[0] == 0) {
   1040     return EFI_INVALID_PARAMETER;
   1041   }
   1042 
   1043   //
   1044   // Make sure Language is a member of SupportedLanguages
   1045   //
   1046   Found = FALSE;
   1047   while (*SupportedLanguages != 0) {
   1048     if (Iso639Language) {
   1049       if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
   1050         Found = TRUE;
   1051         break;
   1052       }
   1053       SupportedLanguages += 3;
   1054     } else {
   1055       for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);
   1056       if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {
   1057         Found = TRUE;
   1058         break;
   1059       }
   1060       SupportedLanguages += Index;
   1061       for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);
   1062     }
   1063   }
   1064 
   1065   //
   1066   // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
   1067   //
   1068   if (!Found) {
   1069     return EFI_UNSUPPORTED;
   1070   }
   1071 
   1072   //
   1073   // Determine the size of the Unicode String Table by looking for a NULL Language entry
   1074   //
   1075   NumberOfEntries = 0;
   1076   if (*UnicodeStringTable != NULL) {
   1077     OldUnicodeStringTable = *UnicodeStringTable;
   1078     while (OldUnicodeStringTable->Language != NULL) {
   1079       LanguageString = OldUnicodeStringTable->Language;
   1080 
   1081       while (*LanguageString != 0) {
   1082         for (Index = 0; LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);
   1083 
   1084         if (AsciiStrnCmp (Language, LanguageString, Index) == 0) {
   1085           return EFI_ALREADY_STARTED;
   1086         }
   1087         LanguageString += Index;
   1088         for (; *LanguageString != 0 && *LanguageString == ';'; LanguageString++);
   1089       }
   1090       OldUnicodeStringTable++;
   1091       NumberOfEntries++;
   1092     }
   1093   }
   1094 
   1095   //
   1096   // Allocate space for a new Unicode String Table.  It must hold the current number of
   1097   // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
   1098   // marker
   1099   //
   1100   NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));
   1101   if (NewUnicodeStringTable == NULL) {
   1102     return EFI_OUT_OF_RESOURCES;
   1103   }
   1104 
   1105   //
   1106   // If the current Unicode String Table contains any entries, then copy them to the
   1107   // newly allocated Unicode String Table.
   1108   //
   1109   if (*UnicodeStringTable != NULL) {
   1110     CopyMem (
   1111       NewUnicodeStringTable,
   1112       *UnicodeStringTable,
   1113       NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)
   1114       );
   1115   }
   1116 
   1117   //
   1118   // Allocate space for a copy of the Language specifier
   1119   //
   1120   NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (AsciiStrSize(Language), Language);
   1121   if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {
   1122     FreePool (NewUnicodeStringTable);
   1123     return EFI_OUT_OF_RESOURCES;
   1124   }
   1125 
   1126   //
   1127   // Compute the length of the Unicode String
   1128   //
   1129   for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++);
   1130 
   1131   //
   1132   // Allocate space for a copy of the Unicode String
   1133   //
   1134   NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (StrSize (UnicodeString), UnicodeString);
   1135   if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {
   1136     FreePool (NewUnicodeStringTable[NumberOfEntries].Language);
   1137     FreePool (NewUnicodeStringTable);
   1138     return EFI_OUT_OF_RESOURCES;
   1139   }
   1140 
   1141   //
   1142   // Mark the end of the Unicode String Table
   1143   //
   1144   NewUnicodeStringTable[NumberOfEntries + 1].Language       = NULL;
   1145   NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString  = NULL;
   1146 
   1147   //
   1148   // Free the old Unicode String Table
   1149   //
   1150   if (*UnicodeStringTable != NULL) {
   1151     FreePool (*UnicodeStringTable);
   1152   }
   1153 
   1154   //
   1155   // Point UnicodeStringTable at the newly allocated Unicode String Table
   1156   //
   1157   *UnicodeStringTable = NewUnicodeStringTable;
   1158 
   1159   return EFI_SUCCESS;
   1160 }
   1161 
   1162 /**
   1163   This function frees the table of Unicode strings in UnicodeStringTable.
   1164 
   1165   If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.
   1166   Otherwise, each language code, and each Unicode string in the Unicode string
   1167   table are freed, and EFI_SUCCESS is returned.
   1168 
   1169   @param  UnicodeStringTable  A pointer to the table of Unicode strings.
   1170 
   1171   @retval EFI_SUCCESS         The Unicode string table was freed.
   1172 
   1173 **/
   1174 EFI_STATUS
   1175 EFIAPI
   1176 FreeUnicodeStringTable (
   1177   IN EFI_UNICODE_STRING_TABLE  *UnicodeStringTable
   1178   )
   1179 {
   1180   UINTN Index;
   1181 
   1182   //
   1183   // If the Unicode String Table is NULL, then it is already freed
   1184   //
   1185   if (UnicodeStringTable == NULL) {
   1186     return EFI_SUCCESS;
   1187   }
   1188 
   1189   //
   1190   // Loop through the Unicode String Table until we reach the end of table marker
   1191   //
   1192   for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) {
   1193 
   1194     //
   1195     // Free the Language string from the Unicode String Table
   1196     //
   1197     FreePool (UnicodeStringTable[Index].Language);
   1198 
   1199     //
   1200     // Free the Unicode String from the Unicode String Table
   1201     //
   1202     if (UnicodeStringTable[Index].UnicodeString != NULL) {
   1203       FreePool (UnicodeStringTable[Index].UnicodeString);
   1204     }
   1205   }
   1206 
   1207   //
   1208   // Free the Unicode String Table itself
   1209   //
   1210   FreePool (UnicodeStringTable);
   1211 
   1212   return EFI_SUCCESS;
   1213 }
   1214 
   1215 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
   1216 
   1217 /**
   1218   [ATTENTION] This function will be deprecated for security reason.
   1219 
   1220   Returns a pointer to an allocated buffer that contains the contents of a
   1221   variable retrieved through the UEFI Runtime Service GetVariable().  The
   1222   returned buffer is allocated using AllocatePool().  The caller is responsible
   1223   for freeing this buffer with FreePool().
   1224 
   1225   If Name is NULL, then ASSERT().
   1226   If Guid is NULL, then ASSERT().
   1227 
   1228   @param[in]  Name  The pointer to a Null-terminated Unicode string.
   1229   @param[in]  Guid  The pointer to an EFI_GUID structure
   1230 
   1231   @retval NULL   The variable could not be retrieved.
   1232   @retval NULL   There are not enough resources available for the variable contents.
   1233   @retval Other  A pointer to allocated buffer containing the variable contents.
   1234 
   1235 **/
   1236 VOID *
   1237 EFIAPI
   1238 GetVariable (
   1239   IN CONST CHAR16    *Name,
   1240   IN CONST EFI_GUID  *Guid
   1241   )
   1242 {
   1243   EFI_STATUS  Status;
   1244   UINTN       Size;
   1245   VOID        *Value;
   1246 
   1247   ASSERT (Name != NULL);
   1248   ASSERT (Guid != NULL);
   1249 
   1250   //
   1251   // Try to get the variable size.
   1252   //
   1253   Value = NULL;
   1254   Size = 0;
   1255   Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value);
   1256   if (Status != EFI_BUFFER_TOO_SMALL) {
   1257     return NULL;
   1258   }
   1259 
   1260   //
   1261   // Allocate buffer to get the variable.
   1262   //
   1263   Value = AllocatePool (Size);
   1264   if (Value == NULL) {
   1265     return NULL;
   1266   }
   1267 
   1268   //
   1269   // Get the variable data.
   1270   //
   1271   Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value);
   1272   if (EFI_ERROR (Status)) {
   1273     FreePool(Value);
   1274     return NULL;
   1275   }
   1276 
   1277   return Value;
   1278 }
   1279 
   1280 /**
   1281   [ATTENTION] This function will be deprecated for security reason.
   1282 
   1283   Returns a pointer to an allocated buffer that contains the contents of a
   1284   variable retrieved through the UEFI Runtime Service GetVariable().  This
   1285   function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables.
   1286   The returned buffer is allocated using AllocatePool().  The caller is
   1287   responsible for freeing this buffer with FreePool().
   1288 
   1289   If Name is NULL, then ASSERT().
   1290 
   1291   @param[in]  Name  The pointer to a Null-terminated Unicode string.
   1292 
   1293   @retval NULL   The variable could not be retrieved.
   1294   @retval NULL   There are not enough resources available for the variable contents.
   1295   @retval Other  A pointer to allocated buffer containing the variable contents.
   1296 
   1297 **/
   1298 VOID *
   1299 EFIAPI
   1300 GetEfiGlobalVariable (
   1301   IN CONST CHAR16  *Name
   1302   )
   1303 {
   1304   return GetVariable (Name, &gEfiGlobalVariableGuid);
   1305 }
   1306 #endif
   1307 
   1308 /**
   1309   Returns the status whether get the variable success. The function retrieves
   1310   variable  through the UEFI Runtime Service GetVariable().  The
   1311   returned buffer is allocated using AllocatePool().  The caller is responsible
   1312   for freeing this buffer with FreePool().
   1313 
   1314   If Name  is NULL, then ASSERT().
   1315   If Guid  is NULL, then ASSERT().
   1316   If Value is NULL, then ASSERT().
   1317 
   1318   @param[in]  Name  The pointer to a Null-terminated Unicode string.
   1319   @param[in]  Guid  The pointer to an EFI_GUID structure
   1320   @param[out] Value The buffer point saved the variable info.
   1321   @param[out] Size  The buffer size of the variable.
   1322 
   1323   @return EFI_OUT_OF_RESOURCES      Allocate buffer failed.
   1324   @return EFI_SUCCESS               Find the specified variable.
   1325   @return Others Errors             Return errors from call to gRT->GetVariable.
   1326 
   1327 **/
   1328 EFI_STATUS
   1329 EFIAPI
   1330 GetVariable2 (
   1331   IN CONST CHAR16    *Name,
   1332   IN CONST EFI_GUID  *Guid,
   1333   OUT VOID           **Value,
   1334   OUT UINTN          *Size OPTIONAL
   1335   )
   1336 {
   1337   EFI_STATUS  Status;
   1338   UINTN       BufferSize;
   1339 
   1340   ASSERT (Name != NULL && Guid != NULL && Value != NULL);
   1341 
   1342   //
   1343   // Try to get the variable size.
   1344   //
   1345   BufferSize = 0;
   1346   *Value     = NULL;
   1347   if (Size != NULL) {
   1348     *Size  = 0;
   1349   }
   1350 
   1351   Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);
   1352   if (Status != EFI_BUFFER_TOO_SMALL) {
   1353     return Status;
   1354   }
   1355 
   1356   //
   1357   // Allocate buffer to get the variable.
   1358   //
   1359   *Value = AllocatePool (BufferSize);
   1360   ASSERT (*Value != NULL);
   1361   if (*Value == NULL) {
   1362     return EFI_OUT_OF_RESOURCES;
   1363   }
   1364 
   1365   //
   1366   // Get the variable data.
   1367   //
   1368   Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);
   1369   if (EFI_ERROR (Status)) {
   1370     FreePool(*Value);
   1371     *Value = NULL;
   1372   }
   1373 
   1374   if (Size != NULL) {
   1375     *Size = BufferSize;
   1376   }
   1377 
   1378   return Status;
   1379 }
   1380 
   1381 /**
   1382   Returns a pointer to an allocated buffer that contains the contents of a
   1383   variable retrieved through the UEFI Runtime Service GetVariable().  This
   1384   function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables.
   1385   The returned buffer is allocated using AllocatePool().  The caller is
   1386   responsible for freeing this buffer with FreePool().
   1387 
   1388   If Name is NULL, then ASSERT().
   1389   If Value is NULL, then ASSERT().
   1390 
   1391   @param[in]  Name  The pointer to a Null-terminated Unicode string.
   1392   @param[out] Value The buffer point saved the variable info.
   1393   @param[out] Size  The buffer size of the variable.
   1394 
   1395   @return EFI_OUT_OF_RESOURCES      Allocate buffer failed.
   1396   @return EFI_SUCCESS               Find the specified variable.
   1397   @return Others Errors             Return errors from call to gRT->GetVariable.
   1398 
   1399 **/
   1400 EFI_STATUS
   1401 EFIAPI
   1402 GetEfiGlobalVariable2 (
   1403   IN CONST CHAR16    *Name,
   1404   OUT VOID           **Value,
   1405   OUT UINTN          *Size OPTIONAL
   1406   )
   1407 {
   1408   return GetVariable2 (Name, &gEfiGlobalVariableGuid, Value, Size);
   1409 }
   1410 
   1411 /**
   1412   Returns a pointer to an allocated buffer that contains the best matching language
   1413   from a set of supported languages.
   1414 
   1415   This function supports both ISO 639-2 and RFC 4646 language codes, but language
   1416   code types may not be mixed in a single call to this function.  The language
   1417   code returned is allocated using AllocatePool().  The caller is responsible for
   1418   freeing the allocated buffer using FreePool().  This function supports a variable
   1419   argument list that allows the caller to pass in a prioritized list of language
   1420   codes to test against all the language codes in SupportedLanguages.
   1421 
   1422   If SupportedLanguages is NULL, then ASSERT().
   1423 
   1424   @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that
   1425                                   contains a set of language codes in the format
   1426                                   specified by Iso639Language.
   1427   @param[in]  Iso639Language      If TRUE, then all language codes are assumed to be
   1428                                   in ISO 639-2 format.  If FALSE, then all language
   1429                                   codes are assumed to be in RFC 4646 language format
   1430   @param[in]  ...                 A variable argument list that contains pointers to
   1431                                   Null-terminated ASCII strings that contain one or more
   1432                                   language codes in the format specified by Iso639Language.
   1433                                   The first language code from each of these language
   1434                                   code lists is used to determine if it is an exact or
   1435                                   close match to any of the language codes in
   1436                                   SupportedLanguages.  Close matches only apply to RFC 4646
   1437                                   language codes, and the matching algorithm from RFC 4647
   1438                                   is used to determine if a close match is present.  If
   1439                                   an exact or close match is found, then the matching
   1440                                   language code from SupportedLanguages is returned.  If
   1441                                   no matches are found, then the next variable argument
   1442                                   parameter is evaluated.  The variable argument list
   1443                                   is terminated by a NULL.
   1444 
   1445   @retval NULL   The best matching language could not be found in SupportedLanguages.
   1446   @retval NULL   There are not enough resources available to return the best matching
   1447                  language.
   1448   @retval Other  A pointer to a Null-terminated ASCII string that is the best matching
   1449                  language in SupportedLanguages.
   1450 
   1451 **/
   1452 CHAR8 *
   1453 EFIAPI
   1454 GetBestLanguage (
   1455   IN CONST CHAR8  *SupportedLanguages,
   1456   IN BOOLEAN      Iso639Language,
   1457   ...
   1458   )
   1459 {
   1460   VA_LIST      Args;
   1461   CHAR8        *Language;
   1462   UINTN        CompareLength;
   1463   UINTN        LanguageLength;
   1464   CONST CHAR8  *Supported;
   1465   CHAR8        *BestLanguage;
   1466 
   1467   ASSERT (SupportedLanguages != NULL);
   1468 
   1469   VA_START (Args, Iso639Language);
   1470   while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {
   1471     //
   1472     // Default to ISO 639-2 mode
   1473     //
   1474     CompareLength  = 3;
   1475     LanguageLength = MIN (3, AsciiStrLen (Language));
   1476 
   1477     //
   1478     // If in RFC 4646 mode, then determine the length of the first RFC 4646 language code in Language
   1479     //
   1480     if (!Iso639Language) {
   1481       for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++);
   1482     }
   1483 
   1484     //
   1485     // Trim back the length of Language used until it is empty
   1486     //
   1487     while (LanguageLength > 0) {
   1488       //
   1489       // Loop through all language codes in SupportedLanguages
   1490       //
   1491       for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) {
   1492         //
   1493         // In RFC 4646 mode, then Loop through all language codes in SupportedLanguages
   1494         //
   1495         if (!Iso639Language) {
   1496           //
   1497           // Skip ';' characters in Supported
   1498           //
   1499           for (; *Supported != '\0' && *Supported == ';'; Supported++);
   1500           //
   1501           // Determine the length of the next language code in Supported
   1502           //
   1503           for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++);
   1504           //
   1505           // If Language is longer than the Supported, then skip to the next language
   1506           //
   1507           if (LanguageLength > CompareLength) {
   1508             continue;
   1509           }
   1510         }
   1511         //
   1512         // See if the first LanguageLength characters in Supported match Language
   1513         //
   1514         if (AsciiStrnCmp (Supported, Language, LanguageLength) == 0) {
   1515           VA_END (Args);
   1516           //
   1517           // Allocate, copy, and return the best matching language code from SupportedLanguages
   1518           //
   1519           BestLanguage = AllocateZeroPool (CompareLength + 1);
   1520           if (BestLanguage == NULL) {
   1521             return NULL;
   1522           }
   1523           return CopyMem (BestLanguage, Supported, CompareLength);
   1524         }
   1525       }
   1526 
   1527       if (Iso639Language) {
   1528         //
   1529         // If ISO 639 mode, then each language can only be tested once
   1530         //
   1531         LanguageLength = 0;
   1532       } else {
   1533         //
   1534         // If RFC 4646 mode, then trim Language from the right to the next '-' character
   1535         //
   1536         for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);
   1537       }
   1538     }
   1539   }
   1540   VA_END (Args);
   1541 
   1542   //
   1543   // No matches were found
   1544   //
   1545   return NULL;
   1546 }
   1547 
   1548