| /**@file | |
| This file contains the keyboard processing code to the HII database. | |
| Copyright (c) 2006, Intel Corporation | |
| 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. | |
| **/ | |
| #include "HiiDatabase.h" | |
| EFI_STATUS | |
| GetPackSize ( | |
| IN VOID *Pack, | |
| OUT UINTN *PackSize, | |
| OUT UINT32 *NumberOfTokens | |
| ) | |
| /*++ | |
| Routine Description: | |
| Determines the passed in Pack's size and returns the value. | |
| Arguments: | |
| Returns: | |
| --*/ | |
| { | |
| EFI_HII_STRING_PACK *StringPack; | |
| UINT16 Type; | |
| UINT32 Length; | |
| *PackSize = 0; | |
| Type = EFI_HII_IFR; | |
| if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) { | |
| // | |
| // The header contains the full IFR length | |
| // | |
| CopyMem (&Length, &((EFI_HII_PACK_HEADER *) Pack)->Length, sizeof (Length)); | |
| *PackSize = (UINTN) Length; | |
| return EFI_SUCCESS; | |
| } | |
| Type = EFI_HII_STRING; | |
| if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) { | |
| // | |
| // The header contains the STRING package length | |
| // The assumption is that the strings for all languages | |
| // are a contiguous block of data and there is a series of | |
| // these package instances which will terminate with a NULL package | |
| // instance. | |
| // | |
| StringPack = (EFI_HII_STRING_PACK *) Pack; | |
| // | |
| // There may be multiple instances packed together of strings | |
| // so we must walk the self describing structures until we encounter | |
| // the NULL structure to determine the full size. | |
| // | |
| CopyMem (&Length, &StringPack->Header.Length, sizeof (Length)); | |
| if (NumberOfTokens != NULL) { | |
| CopyMem (NumberOfTokens, &StringPack->NumStringPointers, sizeof (UINT32)); | |
| } | |
| while (Length != 0) { | |
| *PackSize = *PackSize + Length; | |
| StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) StringPack + Length); | |
| CopyMem (&Length, &StringPack->Header.Length, sizeof (Length)); | |
| } | |
| // | |
| // Encountered a length of 0, so let's add the space for the NULL terminator | |
| // pack's length and call it done. | |
| // | |
| *PackSize = *PackSize + sizeof (EFI_HII_STRING_PACK); | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // We only determine the size of the non-global Package types. | |
| // If neither IFR or STRING data were found, return an error | |
| // | |
| return EFI_NOT_FOUND; | |
| } | |
| EFI_STATUS | |
| ValidatePack ( | |
| IN EFI_HII_PROTOCOL *This, | |
| IN EFI_HII_PACKAGE_INSTANCE *PackageInstance, | |
| OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance, | |
| OUT UINT32 *TotalStringCount | |
| ) | |
| /*++ | |
| Routine Description: | |
| Verifies that the package instance is using the correct handle for string operations. | |
| Arguments: | |
| Returns: | |
| --*/ | |
| { | |
| EFI_HII_DATA *HiiData; | |
| EFI_HII_HANDLE_DATABASE *HandleDatabase; | |
| EFI_HII_PACKAGE_INSTANCE *HandlePackageInstance; | |
| UINT8 *RawData; | |
| EFI_GUID Guid; | |
| EFI_HII_IFR_PACK *FormPack; | |
| UINTN Index; | |
| if (This == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| HiiData = EFI_HII_DATA_FROM_THIS (This); | |
| HandleDatabase = HiiData->DatabaseHead; | |
| ZeroMem (&Guid, sizeof (EFI_GUID)); | |
| *StringPackageInstance = PackageInstance; | |
| // | |
| // Based on if there is IFR data in this package instance, determine | |
| // what the location is of the beginning of the string data. | |
| // | |
| if (PackageInstance->IfrSize > 0) { | |
| FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); | |
| } else { | |
| // | |
| // If there is no IFR data assume the caller knows what they are doing. | |
| // | |
| return EFI_SUCCESS; | |
| } | |
| RawData = (UINT8 *) FormPack; | |
| for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) { | |
| if (RawData[Index] == FRAMEWORK_EFI_IFR_FORM_SET_OP) { | |
| // | |
| // Cache the guid for this formset | |
| // | |
| CopyMem (&Guid, &((FRAMEWORK_EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); | |
| break; | |
| } | |
| Index = RawData[Index + 1] + Index; | |
| } | |
| // | |
| // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are | |
| // different, we should return the correct handle for the caller to use for strings. | |
| // | |
| if ((PackageInstance->StringSize == 0) && (!CompareGuid (&Guid, &PackageInstance->Guid))) { | |
| // | |
| // Search the database for a handle that matches the PackageInstance->Guid | |
| // | |
| for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { | |
| // | |
| // Get Ifrdata and extract the Guid for it | |
| // | |
| HandlePackageInstance = HandleDatabase->Buffer; | |
| ASSERT (HandlePackageInstance->IfrSize != 0); | |
| FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&HandlePackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); | |
| RawData = (UINT8 *) FormPack; | |
| for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) { | |
| if (RawData[Index] == FRAMEWORK_EFI_IFR_FORM_SET_OP) { | |
| // | |
| // Cache the guid for this formset | |
| // | |
| CopyMem (&Guid, &((FRAMEWORK_EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); | |
| break; | |
| } | |
| Index = RawData[Index + 1] + Index; | |
| } | |
| // | |
| // If the Guid from the new handle matches the original Guid referenced in the original package data | |
| // return the appropriate package instance data to use. | |
| // | |
| if (CompareGuid (&Guid, &PackageInstance->Guid)) { | |
| if (TotalStringCount != NULL) { | |
| *TotalStringCount = HandleDatabase->NumberOfTokens; | |
| } | |
| *StringPackageInstance = HandlePackageInstance; | |
| } | |
| } | |
| // | |
| // end for | |
| // | |
| } else { | |
| return EFI_SUCCESS; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| HiiNewPack ( | |
| IN EFI_HII_PROTOCOL *This, | |
| IN EFI_HII_PACKAGES *Packages, | |
| OUT FRAMEWORK_EFI_HII_HANDLE *Handle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Extracts the various packs from a package list. | |
| Arguments: | |
| This - Pointer of HII protocol. | |
| Packages - Pointer of HII packages. | |
| Handle - Handle value to be returned. | |
| Returns: | |
| EFI_SUCCESS - Pacakges has added to HII database successfully. | |
| EFI_INVALID_PARAMETER - Invalid parameter. | |
| --*/ | |
| { | |
| EFI_HII_PACKAGE_INSTANCE *PackageInstance; | |
| EFI_HII_DATA *HiiData; | |
| EFI_HII_HANDLE_DATABASE *HandleDatabase; | |
| EFI_HII_HANDLE_DATABASE *Database; | |
| EFI_HII_PACK_HEADER *PackageHeader; | |
| EFI_HII_GLOBAL_DATA *GlobalData; | |
| EFI_HII_IFR_PACK *IfrPack; | |
| EFI_HII_STRING_PACK *StringPack; | |
| EFI_HII_FONT_PACK *FontPack; | |
| EFI_HII_KEYBOARD_PACK *KeyboardPack; | |
| EFI_STATUS Status; | |
| UINTN IfrSize; | |
| UINTN StringSize; | |
| UINTN TotalStringSize; | |
| UINTN InstanceSize; | |
| UINTN Count; | |
| UINTN Index; | |
| UINT16 Member; | |
| EFI_GUID Guid; | |
| EFI_FORM_SET_STUB FormSetStub; | |
| UINT8 *Location; | |
| UINT16 Unicode; | |
| UINT16 NumWideGlyphs; | |
| UINT16 NumNarrowGlyphs; | |
| UINT32 NumberOfTokens; | |
| UINT32 TotalTokenNumber; | |
| UINT8 *Local; | |
| EFI_NARROW_GLYPH *NarrowGlyph; | |
| if (Packages->NumberOfPackages == 0 || This == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| HiiData = EFI_HII_DATA_FROM_THIS (This); | |
| GlobalData = HiiData->GlobalData; | |
| Database = HiiData->DatabaseHead; | |
| PackageInstance = NULL; | |
| IfrPack = NULL; | |
| StringPack = NULL; | |
| InstanceSize = 0; | |
| IfrSize = 0; | |
| StringSize = 0; | |
| TotalStringSize = 0; | |
| NumberOfTokens = 0; | |
| TotalTokenNumber = 0; | |
| // | |
| // Search through the passed in Packages for the IfrPack and any StringPack. | |
| // | |
| for (Index = 0; Index < Packages->NumberOfPackages; Index++) { | |
| PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *)); | |
| switch (PackageHeader->Type) { | |
| case EFI_HII_IFR: | |
| // | |
| // There shoule be only one Ifr package. | |
| // | |
| ASSERT (IfrPack == NULL); | |
| IfrPack = (EFI_HII_IFR_PACK *) PackageHeader; | |
| break; | |
| case EFI_HII_STRING: | |
| StringPack = (EFI_HII_STRING_PACK *) PackageHeader; | |
| // | |
| // Sending me a String Package. Get its size. | |
| // | |
| Status = GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens); | |
| ASSERT (!EFI_ERROR (Status)); | |
| // | |
| // The size which GetPackSize() returns include the null terminator. So if multiple | |
| // string packages are passed in, merge all these packages, and only pad one null terminator. | |
| // | |
| if (TotalStringSize > 0) { | |
| TotalStringSize -= sizeof (EFI_HII_STRING_PACK); | |
| } | |
| TotalStringSize += StringSize; | |
| TotalTokenNumber += NumberOfTokens; | |
| break; | |
| } | |
| } | |
| // | |
| // If sending a StringPack without an IfrPack, you must include a GuidId | |
| // | |
| if ((StringPack != NULL) && (IfrPack == NULL)) { | |
| if (Packages->GuidId == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } | |
| // | |
| // If passing in an IfrPack and a GuidId is provided, ensure they are the same value. | |
| // | |
| if ((IfrPack != NULL) && (Packages->GuidId != NULL)) { | |
| Location = ((UINT8 *) IfrPack); | |
| Location = (UINT8 *) (((UINTN) Location) + sizeof (EFI_HII_PACK_HEADER)); | |
| // | |
| // Advance to the Form Set Op-code | |
| // | |
| for (Count = 0; ((FRAMEWORK_EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != FRAMEWORK_EFI_IFR_FORM_SET_OP;) { | |
| Count = Count + ((FRAMEWORK_EFI_IFR_OP_HEADER *) &Location[Count])->Length; | |
| } | |
| // | |
| // Copy to local variable | |
| // | |
| CopyMem (&Guid, &((FRAMEWORK_EFI_IFR_FORM_SET *) &Location[Count])->Guid, sizeof (EFI_GUID)); | |
| // | |
| // Check to see if IfrPack->Guid != GuidId | |
| // | |
| if (!CompareGuid (&Guid, Packages->GuidId)) { | |
| // | |
| // If a string package is present, the GUIDs should have agreed. Return an error | |
| // | |
| if (StringPack != NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } | |
| } | |
| // | |
| // If someone is passing in a string only, create a dummy IfrPack with a Guid | |
| // to enable future searching of this data. | |
| // | |
| if ((IfrPack == NULL) && (StringPack != NULL)) { | |
| ZeroMem (&FormSetStub, sizeof (FormSetStub)); | |
| FormSetStub.Header.Type = EFI_HII_IFR; | |
| FormSetStub.Header.Length = sizeof (EFI_FORM_SET_STUB); | |
| FormSetStub.FormSet.Header.OpCode = FRAMEWORK_EFI_IFR_FORM_SET_OP; | |
| FormSetStub.FormSet.Header.Length = (UINT8) sizeof (FRAMEWORK_EFI_IFR_FORM_SET); | |
| // | |
| // Dummy string | |
| // | |
| FormSetStub.FormSet.FormSetTitle = 0x02; | |
| CopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID)); | |
| FormSetStub.EndFormSet.Header.OpCode = FRAMEWORK_EFI_IFR_END_FORM_SET_OP; | |
| FormSetStub.EndFormSet.Header.Length = (UINT8) sizeof (FRAMEWORK_EFI_IFR_END_FORM_SET); | |
| IfrPack = (EFI_HII_IFR_PACK *) &FormSetStub; | |
| } | |
| if (IfrPack != NULL) { | |
| // | |
| // Sending me an IFR Package. Get its size. | |
| // | |
| Status = GetPackSize ((VOID *) IfrPack, &IfrSize, NULL); | |
| ASSERT (!EFI_ERROR (Status)); | |
| } | |
| // | |
| // Prepare the internal package instace buffer to store package data. | |
| // | |
| InstanceSize = IfrSize + TotalStringSize; | |
| if (InstanceSize != 0) { | |
| PackageInstance = AllocateZeroPool (InstanceSize + sizeof (EFI_HII_PACKAGE_INSTANCE)); | |
| ASSERT (PackageInstance); | |
| // | |
| // If there is no DatabaseHead allocated - allocate one | |
| // | |
| if (HiiData->DatabaseHead == NULL) { | |
| HiiData->DatabaseHead = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE)); | |
| ASSERT (HiiData->DatabaseHead); | |
| } | |
| // | |
| // If the head is being used (Handle is non-zero), allocate next Database and | |
| // add it to the linked-list | |
| // | |
| if (HiiData->DatabaseHead->Handle != 0) { | |
| HandleDatabase = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE)); | |
| ASSERT (HandleDatabase); | |
| for (; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) | |
| ; | |
| // | |
| // We are sitting on the Database entry which contains the null Next pointer. Fix it. | |
| // | |
| Database->NextHandleDatabase = HandleDatabase; | |
| } | |
| Database = HiiData->DatabaseHead; | |
| // | |
| // Initialize this instance data | |
| // | |
| for (*Handle = 1; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) { | |
| // | |
| // Since the first Database instance will have a passed back handle of 1, we will continue | |
| // down the linked list of entries until we encounter the end of the linked list. Each time | |
| // we go down one level deeper, increment the handle value that will be passed back. | |
| // | |
| if (Database->Handle >= *Handle) { | |
| *Handle = (FRAMEWORK_EFI_HII_HANDLE ) (Database->Handle + 1); | |
| } | |
| } | |
| PackageInstance->Handle = *Handle; | |
| PackageInstance->IfrSize = IfrSize; | |
| PackageInstance->StringSize = TotalStringSize; | |
| if (Packages->GuidId != NULL) { | |
| CopyMem (&PackageInstance->Guid, Packages->GuidId, sizeof (EFI_GUID)); | |
| } | |
| Database->Buffer = PackageInstance; | |
| Database->Handle = PackageInstance->Handle; | |
| Database->NumberOfTokens = TotalTokenNumber; | |
| Database->NextHandleDatabase = NULL; | |
| } | |
| // | |
| // Copy the Ifr package data into package instance. | |
| // | |
| if (IfrSize > 0) { | |
| CopyMem (&PackageInstance->IfrData, IfrPack, IfrSize); | |
| } | |
| // | |
| // Main loop to store package data into HII database. | |
| // | |
| StringSize = 0; | |
| TotalStringSize = 0; | |
| for (Index = 0; Index < Packages->NumberOfPackages; Index++) { | |
| PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *)); | |
| switch (PackageHeader->Type) { | |
| case EFI_HII_STRING: | |
| StringPack = (EFI_HII_STRING_PACK *) PackageHeader; | |
| // | |
| // The size which GetPackSize() returns include the null terminator. So if multiple | |
| // string packages are passed in, merge all these packages, and only pad one null terminator. | |
| // | |
| if (TotalStringSize > 0) { | |
| TotalStringSize -= sizeof (EFI_HII_STRING_PACK); | |
| } | |
| GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens); | |
| CopyMem ((CHAR8 *) (&PackageInstance->IfrData) + IfrSize + TotalStringSize, StringPack, StringSize); | |
| TotalStringSize += StringSize; | |
| break; | |
| case EFI_HII_HANDLES: | |
| CopyMem (&PackageInstance->HandlePack, PackageHeader, sizeof (EFI_HII_HANDLE_PACK)); | |
| break; | |
| case EFI_HII_FONT: | |
| FontPack = (EFI_HII_FONT_PACK *) PackageHeader; | |
| // | |
| // Add whatever narrow glyphs were passed to us if undefined | |
| // | |
| CopyMem (&NumNarrowGlyphs, &FontPack->NumberOfNarrowGlyphs, sizeof (UINT16)); | |
| for (Count = 0; Count <= NumNarrowGlyphs; Count++) { | |
| Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + (sizeof (EFI_NARROW_GLYPH)) * Count; | |
| NarrowGlyph = (EFI_NARROW_GLYPH *) Local; | |
| CopyMem (&Member, &NarrowGlyph->UnicodeWeight, sizeof (UINT16)); | |
| // | |
| // If the glyph is already defined, do not overwrite it. It is what it is. | |
| // | |
| CopyMem (&Unicode, &GlobalData->NarrowGlyphs[Member].UnicodeWeight, sizeof (UINT16)); | |
| if (Unicode == 0) { | |
| CopyMem (&GlobalData->NarrowGlyphs[Member], Local, sizeof (EFI_NARROW_GLYPH)); | |
| } | |
| } | |
| // | |
| // Add whatever wide glyphs were passed to us if undefined | |
| // | |
| CopyMem (&NumWideGlyphs, &FontPack->NumberOfWideGlyphs, sizeof (UINT16)); | |
| for (Count = 0; Count <= NumWideGlyphs; Count++) { | |
| Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + | |
| (sizeof (EFI_NARROW_GLYPH)) * | |
| NumNarrowGlyphs; | |
| CopyMem ( | |
| &Member, | |
| (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count), | |
| sizeof (UINT16) | |
| ); | |
| // | |
| // If the glyph is already defined, do not overwrite it. It is what it is. | |
| // | |
| CopyMem (&Unicode, &GlobalData->WideGlyphs[Member].UnicodeWeight, sizeof (UINT16)); | |
| if (Unicode == 0) { | |
| Local = (UINT8*)(&FontPack->NumberOfWideGlyphs + sizeof(UINT8)) + (sizeof(EFI_NARROW_GLYPH)) * NumNarrowGlyphs; | |
| CopyMem ( | |
| &GlobalData->WideGlyphs[Member], | |
| (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count), | |
| sizeof (EFI_WIDE_GLYPH) | |
| ); | |
| } | |
| } | |
| break; | |
| case EFI_HII_KEYBOARD: | |
| KeyboardPack = (EFI_HII_KEYBOARD_PACK *) PackageHeader; | |
| // | |
| // Sending me a Keyboard Package | |
| // | |
| if (KeyboardPack->DescriptorCount > 105) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| // | |
| // If someone updates the Descriptors with a count of 0, blow aware the overrides. | |
| // | |
| if (KeyboardPack->DescriptorCount == 0) { | |
| ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (FRAMEWORK_EFI_KEY_DESCRIPTOR) * 106); | |
| } | |
| if (KeyboardPack->DescriptorCount < 106 && KeyboardPack->DescriptorCount > 0) { | |
| // | |
| // If SystemKeyboard was updated already, then steer changes to the override database | |
| // | |
| if (GlobalData->SystemKeyboardUpdate) { | |
| ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (FRAMEWORK_EFI_KEY_DESCRIPTOR) * 106); | |
| for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) { | |
| CopyMem (&Member, &KeyboardPack->Descriptor[Count].Key, sizeof (UINT16)); | |
| CopyMem ( | |
| &GlobalData->OverrideKeyboardLayout[Member], | |
| &KeyboardPack->Descriptor[Count], | |
| sizeof (FRAMEWORK_EFI_KEY_DESCRIPTOR) | |
| ); | |
| } | |
| } else { | |
| // | |
| // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database. | |
| // | |
| ZeroMem (GlobalData->SystemKeyboardLayout, sizeof (FRAMEWORK_EFI_KEY_DESCRIPTOR) * 106); | |
| for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) { | |
| CopyMem (&Member, &KeyboardPack->Descriptor->Key, sizeof (UINT16)); | |
| CopyMem ( | |
| &GlobalData->SystemKeyboardLayout[Member], | |
| &KeyboardPack->Descriptor[Count], | |
| sizeof (FRAMEWORK_EFI_KEY_DESCRIPTOR) | |
| ); | |
| } | |
| // | |
| // Just updated the system keyboard database, reflect that in the global flag. | |
| // | |
| GlobalData->SystemKeyboardUpdate = TRUE; | |
| } | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| EFI_STATUS | |
| EFIAPI | |
| HiiRemovePack ( | |
| IN EFI_HII_PROTOCOL *This, | |
| IN FRAMEWORK_EFI_HII_HANDLE Handle | |
| ) | |
| /*++ | |
| Routine Description: | |
| Removes the various packs from a Handle | |
| Arguments: | |
| Returns: | |
| --*/ | |
| { | |
| EFI_HII_PACKAGE_INSTANCE *PackageInstance; | |
| EFI_HII_DATA *HiiData; | |
| EFI_HII_HANDLE_DATABASE *HandleDatabase; | |
| EFI_HII_HANDLE_DATABASE *PreviousHandleDatabase; | |
| if (This == NULL || Handle == 0) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| HiiData = EFI_HII_DATA_FROM_THIS (This); | |
| HandleDatabase = HiiData->DatabaseHead; | |
| PackageInstance = NULL; | |
| // | |
| // Initialize the Previous with the Head of the Database | |
| // | |
| PreviousHandleDatabase = HandleDatabase; | |
| for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { | |
| // | |
| // Match the numeric value with the database entry - if matched, | |
| // free the package instance and apply fix-up to database linked list | |
| // | |
| if (Handle == HandleDatabase->Handle) { | |
| PackageInstance = HandleDatabase->Buffer; | |
| // | |
| // Free the Package Instance | |
| // | |
| FreePool (PackageInstance); | |
| // | |
| // If this was the only Handle in the database | |
| // | |
| if (HiiData->DatabaseHead == HandleDatabase) { | |
| HiiData->DatabaseHead = NULL; | |
| } | |
| // | |
| // Make the parent->Next point to the current->Next | |
| // | |
| PreviousHandleDatabase->NextHandleDatabase = HandleDatabase->NextHandleDatabase; | |
| FreePool (HandleDatabase); | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is | |
| // | |
| PreviousHandleDatabase = HandleDatabase; | |
| } | |
| // | |
| // No handle was found - error condition | |
| // | |
| if (PackageInstance == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| return EFI_SUCCESS; | |
| } |