mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			651 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			651 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | ||
|   Mde UEFI library functions.
 | ||
| 
 | ||
|   Copyright (c) 2006, Intel Corporation<BR>
 | ||
|   All rights reserved. This program and the accompanying materials                          
 | ||
|   are licensed and made available under the terms and conditions of the BSD License         
 | ||
|   which accompanies this distribution.  The full text of the license may be found at        
 | ||
|   http://opensource.org/licenses/bsd-license.php                                            
 | ||
| 
 | ||
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | ||
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | ||
| 
 | ||
|   Module Name:  UefiLib.c
 | ||
| 
 | ||
| **/
 | ||
| 
 | ||
| /**
 | ||
|   Compare whether two names of languages are identical.
 | ||
| 
 | ||
|   @param  Language1 Name of language 1.
 | ||
|   @param  Language2 Name of language 2.
 | ||
| 
 | ||
|   @retval TRUE      Language 1 and language 2 are the same.
 | ||
|   @retval FALSE     Language 1 and language 2 are not the same.
 | ||
| 
 | ||
| **/
 | ||
| BOOLEAN
 | ||
| CompareIso639LanguageCode (
 | ||
|   IN CONST CHAR8  *Language1,
 | ||
|   IN CONST CHAR8  *Language2
 | ||
|   )
 | ||
| {
 | ||
|   return (BOOLEAN) (ReadUnaligned24 ((CONST UINT32 *) Language1) == ReadUnaligned24 ((CONST UINT32 *) Language2));
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function searches the list of configuration tables stored in the EFI System 
 | ||
|   Table for a table with a GUID that matches TableGuid.  If a match is found, 
 | ||
|   then a pointer to the configuration table is returned in Table, and EFI_SUCCESS 
 | ||
|   is returned.  If a matching GUID is not found, then EFI_NOT_FOUND is returned.
 | ||
| 
 | ||
|   @param  TableGuid       Pointer to table's GUID type..
 | ||
|   @param  Table           Pointer to the table associated with TableGuid in the EFI System Table.
 | ||
| 
 | ||
|   @retval EFI_SUCCESS     A configuration table matching TableGuid was found.
 | ||
|   @retval EFI_NOT_FOUND   A configuration table matching TableGuid could not be found.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| EfiGetSystemConfigurationTable (  
 | ||
|   IN  EFI_GUID  *TableGuid,
 | ||
|   OUT VOID      **Table
 | ||
|   )
 | ||
| {
 | ||
|   EFI_SYSTEM_TABLE  *SystemTable;
 | ||
|   UINTN             Index;
 | ||
| 
 | ||
|   ASSERT (TableGuid != NULL);
 | ||
|   ASSERT (Table != NULL);
 | ||
| 
 | ||
|   SystemTable = gST;
 | ||
|   *Table = NULL;
 | ||
|   for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
 | ||
|     if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) {
 | ||
|       *Table = SystemTable->ConfigurationTable[Index].VendorTable;
 | ||
|       return EFI_SUCCESS;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   return EFI_NOT_FOUND;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function causes the notification function to be executed for every protocol 
 | ||
|   of type ProtocolGuid instance that exists in the system when this function is 
 | ||
|   invoked.  In addition, every time a protocol of type ProtocolGuid instance is 
 | ||
|   installed or reinstalled, the notification function is also executed.
 | ||
| 
 | ||
|   @param  ProtocolGuid    Supplies GUID of the protocol upon whose installation the event is fired.
 | ||
|   @param  NotifyTpl       Supplies the task priority level of the event notifications.
 | ||
|   @param  NotifyFunction  Supplies the function to notify when the event is signaled.
 | ||
|   @param  NotifyContext   The context parameter to pass to NotifyFunction.
 | ||
|   @param  Registration    A pointer to a memory location to receive the registration value.
 | ||
| 
 | ||
|   @return The notification event that was created. 
 | ||
| 
 | ||
| **/
 | ||
| EFI_EVENT
 | ||
| EFIAPI
 | ||
| EfiCreateProtocolNotifyEvent(
 | ||
|   IN  EFI_GUID          *ProtocolGuid,
 | ||
|   IN  EFI_TPL           NotifyTpl,
 | ||
|   IN  EFI_EVENT_NOTIFY  NotifyFunction,
 | ||
|   IN  VOID              *NotifyContext,  OPTIONAL
 | ||
|   OUT VOID              *Registration
 | ||
|   )
 | ||
| {
 | ||
|   EFI_STATUS  Status;
 | ||
|   EFI_EVENT   Event;
 | ||
| 
 | ||
|   //
 | ||
|   // Create the event
 | ||
|   //
 | ||
| 
 | ||
|   Status = gBS->CreateEvent (
 | ||
|                   EFI_EVENT_NOTIFY_SIGNAL,
 | ||
|                   NotifyTpl,
 | ||
|                   NotifyFunction,
 | ||
|                   NotifyContext,
 | ||
|                   &Event
 | ||
|                   );
 | ||
|   ASSERT_EFI_ERROR (Status);
 | ||
| 
 | ||
|   //
 | ||
|   // Register for protocol notifactions on this event
 | ||
|   //
 | ||
| 
 | ||
|   Status = gBS->RegisterProtocolNotify (
 | ||
|                   ProtocolGuid,
 | ||
|                   Event,
 | ||
|                   Registration
 | ||
|                   );
 | ||
| 
 | ||
|   ASSERT_EFI_ERROR (Status);
 | ||
| 
 | ||
|   //
 | ||
|   // Kick the event so we will perform an initial pass of
 | ||
|   // current installed drivers
 | ||
|   //
 | ||
| 
 | ||
|   gBS->SignalEvent (Event);
 | ||
|   return Event;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext.
 | ||
|   This event is signaled with EfiNamedEventSignal().  This provide the ability for 
 | ||
|   one or more listeners on the same event named by the GUID specified by Name.
 | ||
| 
 | ||
|   @param  Name                  Supplies GUID name of the event.
 | ||
|   @param  NotifyTpl             Supplies the task priority level of the event notifications.
 | ||
|   @param  NotifyFunction        Supplies the function to notify when the event is signaled.
 | ||
|   @param  NotifyContext         The context parameter to pass to NotifyFunction. 
 | ||
|   @param  Registration          A pointer to a memory location to receive the registration value.
 | ||
| 
 | ||
|   @retval EFI_SUCCESS           A named event was created.
 | ||
|   @retval EFI_OUT_OF_RESOURCES  There are not enough resource to create the named event.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| EfiNamedEventListen (
 | ||
|   IN CONST EFI_GUID    *Name,
 | ||
|   IN EFI_TPL           NotifyTpl,
 | ||
|   IN EFI_EVENT_NOTIFY  NotifyFunction,
 | ||
|   IN CONST VOID        *NotifyContext,  OPTIONAL
 | ||
|   OUT VOID             *Registration    OPTIONAL
 | ||
|   )
 | ||
| {
 | ||
|   EFI_STATUS  Status;
 | ||
|   EFI_EVENT   Event;
 | ||
|   VOID        *RegistrationLocal;
 | ||
| 
 | ||
|   //
 | ||
|   // Create event
 | ||
|   //
 | ||
|   Status = gBS->CreateEvent (
 | ||
|                   EFI_EVENT_NOTIFY_SIGNAL,
 | ||
|                   NotifyTpl,
 | ||
|                   NotifyFunction,
 | ||
|                   (VOID *) NotifyContext,
 | ||
|                   &Event
 | ||
|                   );
 | ||
|   ASSERT_EFI_ERROR (Status);
 | ||
| 
 | ||
|   //
 | ||
|   // The Registration is not optional to RegisterProtocolNotify().
 | ||
|   // To make it optional to EfiNamedEventListen(), may need to substitute with a local.
 | ||
|   //
 | ||
|   if (Registration != NULL) {
 | ||
|     RegistrationLocal = Registration;
 | ||
|   } else {
 | ||
|     RegistrationLocal = &RegistrationLocal;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // Register for an installation of protocol interface
 | ||
|   //
 | ||
| 
 | ||
|   Status = gBS->RegisterProtocolNotify (
 | ||
|                   (EFI_GUID *) Name,
 | ||
|                   Event,
 | ||
|                   RegistrationLocal
 | ||
|                   );
 | ||
|   ASSERT_EFI_ERROR (Status);
 | ||
| 
 | ||
|   return EFI_SUCCESS;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function signals the named event specified by Name.  The named event must 
 | ||
|   have been created with EfiNamedEventListen().
 | ||
| 
 | ||
|   @param  Name                  Supplies GUID name of the event.
 | ||
| 
 | ||
|   @retval EFI_SUCCESS           A named event was signaled.
 | ||
|   @retval EFI_OUT_OF_RESOURCES  There are not enough resource to signal the named event.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| EfiNamedEventSignal (
 | ||
|   IN CONST EFI_GUID  *Name
 | ||
|   )
 | ||
| {
 | ||
|   EFI_STATUS  Status;
 | ||
|   EFI_HANDLE  Handle;
 | ||
| 
 | ||
|   Handle = NULL;
 | ||
|   Status = gBS->InstallProtocolInterface (
 | ||
|                   &Handle,
 | ||
|                   (EFI_GUID *) Name,
 | ||
|                   EFI_NATIVE_INTERFACE,
 | ||
|                   NULL
 | ||
|                   );
 | ||
|   ASSERT_EFI_ERROR (Status);
 | ||
| 
 | ||
|   Status = gBS->UninstallProtocolInterface (
 | ||
|                   Handle,
 | ||
|                   (EFI_GUID *) Name,
 | ||
|                   NULL
 | ||
|                   );
 | ||
|   ASSERT_EFI_ERROR (Status);
 | ||
| 
 | ||
|   return EFI_SUCCESS;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|   This function initializes a basic mutual exclusion lock to the released state 
 | ||
|   and returns the lock.  Each lock provides mutual exclusion access at its task 
 | ||
|   priority level.  Since there is no preemption or multiprocessor support in EFI,
 | ||
|   acquiring the lock only consists of raising to the locks TPL.
 | ||
| 
 | ||
|   @param  Lock       A pointer to the lock data structure to initialize.
 | ||
|   @param  Priority   EFI TPL associated with the lock.
 | ||
| 
 | ||
|   @return The lock.
 | ||
| 
 | ||
| **/
 | ||
| EFI_LOCK *
 | ||
| EFIAPI
 | ||
| EfiInitializeLock (
 | ||
|   IN OUT EFI_LOCK  *Lock,
 | ||
|   IN EFI_TPL        Priority
 | ||
|   )
 | ||
| {
 | ||
|   ASSERT (Lock != NULL);
 | ||
|   ASSERT (Priority <= EFI_TPL_HIGH_LEVEL);
 | ||
| 
 | ||
|   Lock->Tpl       = Priority;
 | ||
|   Lock->OwnerTpl  = EFI_TPL_APPLICATION;
 | ||
|   Lock->Lock      = EfiLockReleased ;
 | ||
|   return Lock;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function raises the system<65><6D>s current task priority level to the task 
 | ||
|   priority level of the mutual exclusion lock.  Then, it places the lock in the 
 | ||
|   acquired state.
 | ||
| 
 | ||
|   @param  Priority  The task priority level of the lock.
 | ||
| 
 | ||
| **/
 | ||
| VOID
 | ||
| EFIAPI
 | ||
| EfiAcquireLock (
 | ||
|   IN EFI_LOCK  *Lock
 | ||
|   )
 | ||
| {
 | ||
|   ASSERT (Lock != NULL);
 | ||
|   ASSERT (Lock->Lock == EfiLockReleased);
 | ||
| 
 | ||
|   Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);
 | ||
|   Lock->Lock     = EfiLockAcquired;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function raises the system<65><6D>s current task priority level to the task 
 | ||
|   priority level of the mutual exclusion lock.  Then, it attempts to place the 
 | ||
|   lock in the acquired state.
 | ||
| 
 | ||
|   @param  Lock              A pointer to the lock to acquire.
 | ||
| 
 | ||
|   @retval EFI_SUCCESS       The lock was acquired.
 | ||
|   @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| EfiAcquireLockOrFail (
 | ||
|   IN EFI_LOCK  *Lock
 | ||
|   )
 | ||
| {
 | ||
| 
 | ||
|   ASSERT (Lock != NULL);
 | ||
|   ASSERT (Lock->Lock != EfiLockUninitialized);
 | ||
| 
 | ||
|   if (Lock->Lock == EfiLockAcquired) {
 | ||
|     //
 | ||
|     // Lock is already owned, so bail out
 | ||
|     //
 | ||
|     return EFI_ACCESS_DENIED;
 | ||
|   }
 | ||
| 
 | ||
|   Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl);
 | ||
| 
 | ||
|   Lock->Lock = EfiLockAcquired;
 | ||
| 
 | ||
|   return EFI_SUCCESS;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function transitions a mutual exclusion lock from the acquired state to 
 | ||
|   the released state, and restores the system<65><6D>s task priority level to its 
 | ||
|   previous level.
 | ||
| 
 | ||
|   @param  Lock  A pointer to the lock to release.
 | ||
| 
 | ||
| **/
 | ||
| VOID
 | ||
| EFIAPI
 | ||
| EfiReleaseLock (
 | ||
|   IN EFI_LOCK  *Lock
 | ||
|   )
 | ||
| {
 | ||
|   EFI_TPL Tpl;
 | ||
| 
 | ||
|   ASSERT (Lock != NULL);
 | ||
|   ASSERT (Lock->Lock == EfiLockAcquired);
 | ||
| 
 | ||
|   Tpl = Lock->OwnerTpl;
 | ||
|   
 | ||
|   Lock->Lock = EfiLockReleased;
 | ||
| 
 | ||
|   gBS->RestoreTPL (Tpl);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function looks up a Unicode string in UnicodeStringTable.  If Language is 
 | ||
|   a member of SupportedLanguages and a Unicode string is found in UnicodeStringTable
 | ||
|   that matches the language code specified by Language, then it is returned in 
 | ||
|   UnicodeString.
 | ||
| 
 | ||
|   @param  Language                A pointer to the ISO 639-2 language code for the 
 | ||
|                                   Unicode string to look up and return.
 | ||
|   @param  SupportedLanguages      A pointer to the set of ISO 639-2 language codes 
 | ||
|                                   that the Unicode string table supports.  Language 
 | ||
|                                   must be a member of this set.
 | ||
|   @param  UnicodeStringTable      A pointer to the table of Unicode strings.
 | ||
|   @param  UnicodeString           A pointer to the Unicode string from UnicodeStringTable
 | ||
|                                   that matches the language specified by Language.
 | ||
| 
 | ||
|   @retval  EFI_SUCCESS            The Unicode string that matches the language 
 | ||
|                                   specified by Language was found
 | ||
|                                   in the table of Unicoide strings UnicodeStringTable, 
 | ||
|                                   and it was returned in UnicodeString.
 | ||
|   @retval  EFI_INVALID_PARAMETER  Language is NULL.
 | ||
|   @retval  EFI_INVALID_PARAMETER  UnicodeString is NULL.
 | ||
|   @retval  EFI_UNSUPPORTED        SupportedLanguages is NULL.
 | ||
|   @retval  EFI_UNSUPPORTED        UnicodeStringTable is NULL.
 | ||
|   @retval  EFI_UNSUPPORTED        The language specified by Language is not a 
 | ||
|                                   member of SupportedLanguages.
 | ||
|   @retval  EFI_UNSUPPORTED        The language specified by Language is not 
 | ||
|                                   supported by UnicodeStringTable.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| LookupUnicodeString (
 | ||
|   IN CONST CHAR8                     *Language,
 | ||
|   IN CONST CHAR8                     *SupportedLanguages,
 | ||
|   IN CONST EFI_UNICODE_STRING_TABLE  *UnicodeStringTable,
 | ||
|   OUT CHAR16                         **UnicodeString
 | ||
|   )
 | ||
| {
 | ||
|   //
 | ||
|   // Make sure the parameters are valid
 | ||
|   //
 | ||
|   if (Language == NULL || UnicodeString == NULL) {
 | ||
|     return EFI_INVALID_PARAMETER;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // If there are no supported languages, or the Unicode String Table is empty, then the
 | ||
|   // Unicode String specified by Language is not supported by this Unicode String Table
 | ||
|   //
 | ||
|   if (SupportedLanguages == NULL || UnicodeStringTable == NULL) {
 | ||
|     return EFI_UNSUPPORTED;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // Make sure Language is in the set of Supported Languages
 | ||
|   //
 | ||
|   while (*SupportedLanguages != 0) {
 | ||
|     if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
 | ||
| 
 | ||
|       //
 | ||
|       // Search the Unicode String Table for the matching Language specifier
 | ||
|       //
 | ||
|       while (UnicodeStringTable->Language != NULL) {
 | ||
|         if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) {
 | ||
| 
 | ||
|           //
 | ||
|           // A matching string was found, so return it
 | ||
|           //
 | ||
|           *UnicodeString = UnicodeStringTable->UnicodeString;
 | ||
|           return EFI_SUCCESS;
 | ||
|         }
 | ||
| 
 | ||
|         UnicodeStringTable++;
 | ||
|       }
 | ||
| 
 | ||
|       return EFI_UNSUPPORTED;
 | ||
|     }
 | ||
| 
 | ||
|     SupportedLanguages += 3;
 | ||
|   }
 | ||
| 
 | ||
|   return EFI_UNSUPPORTED;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function adds a Unicode string to UnicodeStringTable.
 | ||
|   If Language is a member of SupportedLanguages then UnicodeString is added to 
 | ||
|   UnicodeStringTable.  New buffers are allocated for both Language and 
 | ||
|   UnicodeString.  The contents of Language and UnicodeString are copied into 
 | ||
|   these new buffers.  These buffers are automatically freed when 
 | ||
|   FreeUnicodeStringTable() is called.
 | ||
| 
 | ||
|   @param  Language                A pointer to the ISO 639-2 language code for the Unicode 
 | ||
|                                   string to add.
 | ||
|   @param  SupportedLanguages      A pointer to the set of ISO 639-2 language codes
 | ||
|                                   that the Unicode string table supports.
 | ||
|                                   Language must be a member of this set.
 | ||
|   @param  UnicodeStringTable      A pointer to the table of Unicode strings.
 | ||
|   @param  UnicodeString           A pointer to the Unicode string to add.
 | ||
| 
 | ||
|   @retval EFI_SUCCESS             The Unicode string that matches the language 
 | ||
|                                   specified by Language was found in the table of 
 | ||
|                                   Unicode strings UnicodeStringTable, and it was 
 | ||
|                                   returned in UnicodeString.
 | ||
|   @retval EFI_INVALID_PARAMETER   Language is NULL.
 | ||
|   @retval EFI_INVALID_PARAMETER   UnicodeString is NULL.
 | ||
|   @retval EFI_INVALID_PARAMETER   UnicodeString is an empty string.
 | ||
|   @retval EFI_UNSUPPORTED         SupportedLanguages is NULL.
 | ||
|   @retval EFI_ALREADY_STARTED     A Unicode string with language Language is 
 | ||
|                                   already present in UnicodeStringTable.
 | ||
|   @retval EFI_OUT_OF_RESOURCES    There is not enough memory to add another 
 | ||
|                                   Unicode string to UnicodeStringTable.
 | ||
|   @retval EFI_UNSUPPORTED         The language specified by Language is not a 
 | ||
|                                   member of SupportedLanguages.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| AddUnicodeString (
 | ||
|   IN CONST CHAR8               *Language,
 | ||
|   IN CONST CHAR8               *SupportedLanguages,
 | ||
|   IN EFI_UNICODE_STRING_TABLE  **UnicodeStringTable,
 | ||
|   IN CONST CHAR16              *UnicodeString
 | ||
|   )
 | ||
| {
 | ||
|   UINTN                     NumberOfEntries;
 | ||
|   EFI_UNICODE_STRING_TABLE  *OldUnicodeStringTable;
 | ||
|   EFI_UNICODE_STRING_TABLE  *NewUnicodeStringTable;
 | ||
|   UINTN                     UnicodeStringLength;
 | ||
| 
 | ||
|   //
 | ||
|   // Make sure the parameter are valid
 | ||
|   //
 | ||
|   if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {
 | ||
|     return EFI_INVALID_PARAMETER;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // If there are no supported languages, then a Unicode String can not be added
 | ||
|   //
 | ||
|   if (SupportedLanguages == NULL) {
 | ||
|     return EFI_UNSUPPORTED;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // If the Unicode String is empty, then a Unicode String can not be added
 | ||
|   //
 | ||
|   if (UnicodeString[0] == 0) {
 | ||
|     return EFI_INVALID_PARAMETER;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // Make sure Language is a member of SupportedLanguages
 | ||
|   //
 | ||
|   while (*SupportedLanguages != 0) {
 | ||
|     if (CompareIso639LanguageCode (Language, SupportedLanguages)) {
 | ||
| 
 | ||
|       //
 | ||
|       // Determine the size of the Unicode String Table by looking for a NULL Language entry
 | ||
|       //
 | ||
|       NumberOfEntries = 0;
 | ||
|       if (*UnicodeStringTable != NULL) {
 | ||
|         OldUnicodeStringTable = *UnicodeStringTable;
 | ||
|         while (OldUnicodeStringTable->Language != NULL) {
 | ||
|           if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) {
 | ||
|             return EFI_ALREADY_STARTED;
 | ||
|           }
 | ||
| 
 | ||
|           OldUnicodeStringTable++;
 | ||
|           NumberOfEntries++;
 | ||
|         }
 | ||
|       }
 | ||
| 
 | ||
|       //
 | ||
|       // Allocate space for a new Unicode String Table.  It must hold the current number of
 | ||
|       // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table
 | ||
|       // marker
 | ||
|       //
 | ||
|       NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));
 | ||
|       if (NewUnicodeStringTable == NULL) {
 | ||
|         return EFI_OUT_OF_RESOURCES;
 | ||
|       }
 | ||
| 
 | ||
|       //
 | ||
|       // If the current Unicode String Table contains any entries, then copy them to the
 | ||
|       // newly allocated Unicode String Table.
 | ||
|       //
 | ||
|       if (*UnicodeStringTable != NULL) {
 | ||
|         CopyMem (
 | ||
|            NewUnicodeStringTable,
 | ||
|            *UnicodeStringTable,
 | ||
|            NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)
 | ||
|            );
 | ||
|       }
 | ||
| 
 | ||
|       //
 | ||
|       // Allocate space for a copy of the Language specifier
 | ||
|       //
 | ||
|       NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language);
 | ||
|       if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {
 | ||
|         gBS->FreePool (NewUnicodeStringTable);
 | ||
|         return EFI_OUT_OF_RESOURCES;
 | ||
|       }
 | ||
| 
 | ||
|       //
 | ||
|       // Compute the length of the Unicode String
 | ||
|       //
 | ||
|       for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++)
 | ||
|         ;
 | ||
| 
 | ||
|       //
 | ||
|       // Allocate space for a copy of the Unicode String
 | ||
|       //
 | ||
|       NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (
 | ||
|                                                               (UnicodeStringLength + 1) * sizeof (CHAR16),
 | ||
|                                                               UnicodeString
 | ||
|                                                               );
 | ||
|       if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {
 | ||
|         gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);
 | ||
|         gBS->FreePool (NewUnicodeStringTable);
 | ||
|         return EFI_OUT_OF_RESOURCES;
 | ||
|       }
 | ||
| 
 | ||
|       //
 | ||
|       // Mark the end of the Unicode String Table
 | ||
|       //
 | ||
|       NewUnicodeStringTable[NumberOfEntries + 1].Language       = NULL;
 | ||
|       NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString  = NULL;
 | ||
| 
 | ||
|       //
 | ||
|       // Free the old Unicode String Table
 | ||
|       //
 | ||
|       if (*UnicodeStringTable != NULL) {
 | ||
|         gBS->FreePool (*UnicodeStringTable);
 | ||
|       }
 | ||
| 
 | ||
|       //
 | ||
|       // Point UnicodeStringTable at the newly allocated Unicode String Table
 | ||
|       //
 | ||
|       *UnicodeStringTable = NewUnicodeStringTable;
 | ||
| 
 | ||
|       return EFI_SUCCESS;
 | ||
|     }
 | ||
| 
 | ||
|     SupportedLanguages += 3;
 | ||
|   }
 | ||
| 
 | ||
|   return EFI_UNSUPPORTED;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|   This function frees the table of Unicode strings in UnicodeStringTable.
 | ||
|   If UnicodeStringTable is NULL, then EFI_SUCCESS is returned.
 | ||
|   Otherwise, each language code, and each Unicode string in the Unicode string 
 | ||
|   table are freed, and EFI_SUCCESS is returned.
 | ||
| 
 | ||
|   @param  UnicodeStringTable  A pointer to the table of Unicode strings.
 | ||
| 
 | ||
|   @retval EFI_SUCCESS         The Unicode string table was freed.
 | ||
| 
 | ||
| **/
 | ||
| EFI_STATUS
 | ||
| EFIAPI
 | ||
| FreeUnicodeStringTable (
 | ||
|   IN EFI_UNICODE_STRING_TABLE  *UnicodeStringTable
 | ||
|   )
 | ||
| {
 | ||
|   UINTN Index;
 | ||
| 
 | ||
|   //
 | ||
|   // If the Unicode String Table is NULL, then it is already freed
 | ||
|   //
 | ||
|   if (UnicodeStringTable == NULL) {
 | ||
|     return EFI_SUCCESS;
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // Loop through the Unicode String Table until we reach the end of table marker
 | ||
|   //
 | ||
|   for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) {
 | ||
| 
 | ||
|     //
 | ||
|     // Free the Language string from the Unicode String Table
 | ||
|     //
 | ||
|     gBS->FreePool (UnicodeStringTable[Index].Language);
 | ||
| 
 | ||
|     //
 | ||
|     // Free the Unicode String from the Unicode String Table
 | ||
|     //
 | ||
|     if (UnicodeStringTable[Index].UnicodeString != NULL) {
 | ||
|       gBS->FreePool (UnicodeStringTable[Index].UnicodeString);
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   //
 | ||
|   // Free the Unicode String Table itself
 | ||
|   //
 | ||
|   gBS->FreePool (UnicodeStringTable);
 | ||
| 
 | ||
|   return EFI_SUCCESS;
 | ||
| }
 |