diff options
Diffstat (limited to 'IntelFrameworkPkg/Library/FrameworkUefiLib/UefiLib.c')
-rw-r--r-- | IntelFrameworkPkg/Library/FrameworkUefiLib/UefiLib.c | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/IntelFrameworkPkg/Library/FrameworkUefiLib/UefiLib.c b/IntelFrameworkPkg/Library/FrameworkUefiLib/UefiLib.c new file mode 100644 index 0000000..af88f63 --- /dev/null +++ b/IntelFrameworkPkg/Library/FrameworkUefiLib/UefiLib.c @@ -0,0 +1,813 @@ +/** @file
+ Mde UEFI library functions.
+
+ Copyright (c) 2006 - 2007, 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
+
+**/
+
+#include "FrameworkUefiLib.h"
+
+/**
+ 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.
+
+**/
+STATIC
+BOOLEAN
+CompareIso639LanguageCode (
+ IN CONST CHAR8 *Language1,
+ IN CONST CHAR8 *Language2
+ )
+{
+ UINT32 Name1;
+ UINT32 Name2;
+
+ Name1 = ReadUnaligned24 ((CONST UINT32 *) Language1);
+ Name2 = ReadUnaligned24 ((CONST UINT32 *) Language2);
+
+ return (BOOLEAN) (Name1 == Name2);
+}
+
+/**
+ 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 (
+ EVT_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 (
+ EVT_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;
+}
+
+/**
+ Returns the current TPL.
+
+ This function returns the current TPL. There is no EFI service to directly
+ retrieve the current TPL. Instead, the RaiseTPL() function is used to raise
+ the TPL to TPL_HIGH_LEVEL. This will return the current TPL. The TPL level
+ can then immediately be restored back to the current TPL level with a call
+ to RestoreTPL().
+
+ @param VOID
+
+ @retvale EFI_TPL The current TPL.
+
+**/
+EFI_TPL
+EFIAPI
+EfiGetCurrentTpl (
+ VOID
+ )
+{
+ EFI_TPL Tpl;
+
+ Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+ gBS->RestoreTPL (Tpl);
+
+ return Tpl;
+}
+
+
+/**
+ 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 <= TPL_HIGH_LEVEL);
+
+ Lock->Tpl = Priority;
+ Lock->OwnerTpl = TPL_APPLICATION;
+ Lock->Lock = EfiLockReleased ;
+ return Lock;
+}
+
+/**
+ This function raises the system'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'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'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);
+}
+
+/**
+ Tests whether a controller handle is being managed by a specific driver.
+
+ This function tests whether the driver specified by DriverBindingHandle is
+ currently managing the controller specified by ControllerHandle. This test
+ is performed by evaluating if the the protocol specified by ProtocolGuid is
+ present on ControllerHandle and is was opened by DriverBindingHandle with an
+ attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
+ If ProtocolGuid is NULL, then ASSERT().
+
+ @param ControllerHandle A handle for a controller to test.
+ @param DriverBindingHandle Specifies the driver binding handle for the
+ driver.
+ @param ProtocolGuid Specifies the protocol that the driver specified
+ by DriverBindingHandle opens in its Start()
+ function.
+
+ @retval EFI_SUCCESS ControllerHandle is managed by the driver
+ specifed by DriverBindingHandle.
+ @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
+ specifed by DriverBindingHandle.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiTestManagedDevice (
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN CONST EFI_HANDLE DriverBindingHandle,
+ IN CONST EFI_GUID *ProtocolGuid
+ )
+{
+ EFI_STATUS Status;
+ VOID *ManagedInterface;
+
+ ASSERT (ProtocolGuid != NULL);
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ (EFI_GUID *) ProtocolGuid,
+ &ManagedInterface,
+ DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ (EFI_GUID *) ProtocolGuid,
+ DriverBindingHandle,
+ ControllerHandle
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Tests whether a child handle is a child device of the controller.
+
+ This function tests whether ChildHandle is one of the children of
+ ControllerHandle. This test is performed by checking to see if the protocol
+ specified by ProtocolGuid is present on ControllerHandle and opened by
+ ChildHandle with an attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+ If ProtocolGuid is NULL, then ASSERT().
+
+ @param ControllerHandle A handle for a (parent) controller to test.
+ @param ChildHandle A child handle to test.
+ @param ConsumsedGuid Supplies the protocol that the child controller
+ opens on its parent controller.
+
+ @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
+ @retval EFI_UNSUPPORTED ChildHandle is not a child of the
+ ControllerHandle.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiTestChildHandle (
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN CONST EFI_HANDLE ChildHandle,
+ IN CONST EFI_GUID *ProtocolGuid
+ )
+{
+ EFI_STATUS Status;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
+ UINTN EntryCount;
+ UINTN Index;
+
+ ASSERT (ProtocolGuid != NULL);
+
+ //
+ // Retrieve the list of agents that are consuming the specific protocol
+ // on ControllerHandle.
+ //
+ Status = gBS->OpenProtocolInformation (
+ ControllerHandle,
+ (EFI_GUID *) ProtocolGuid,
+ &OpenInfoBuffer,
+ &EntryCount
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Inspect if ChildHandle is one of the agents.
+ //
+ Status = EFI_UNSUPPORTED;
+ for (Index = 0; Index < EntryCount; Index++) {
+ if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&
+ (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+
+ FreePool (OpenInfoBuffer);
+ return Status;
+}
+
+/**
+ 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;
+}
+
|