summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c')
-rw-r--r--EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c677
1 files changed, 677 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c
new file mode 100644
index 0000000..3e9e536
--- /dev/null
+++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c
@@ -0,0 +1,677 @@
+/*++
+
+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.
+
+Module Name:
+
+ Package.c
+
+Abstract:
+
+ This file contains the package processing code to the HII database.
+
+--*/
+
+
+#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] != EFI_IFR_END_FORM_SET_OP;) {
+ if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
+ //
+ // Cache the guid for this formset
+ //
+ CopyMem (&Guid, &((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] != EFI_IFR_END_FORM_SET_OP;) {
+ if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
+ //
+ // Cache the guid for this formset
+ //
+ CopyMem (&Guid, &((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 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;
+ EFI_WIDE_GLYPH *WideGlyph;
+
+ 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; ((EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != EFI_IFR_FORM_SET_OP;) {
+ Count = Count + ((EFI_IFR_OP_HEADER *) &Location[Count])->Length;
+ }
+ //
+ // Copy to local variable
+ //
+ CopyMem (&Guid, &((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 = EFI_IFR_FORM_SET_OP;
+ FormSetStub.FormSet.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET);
+ //
+ // Dummy string
+ //
+ FormSetStub.FormSet.FormSetTitle = 0x02;
+ CopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID));
+
+ FormSetStub.EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP;
+ FormSetStub.EndFormSet.Header.Length = (UINT8) sizeof (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 = 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;
+ WideGlyph = (EFI_WIDE_GLYPH *) Local;
+ 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;
+ WideGlyph = (EFI_WIDE_GLYPH *) Local;
+ 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 (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 (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 (EFI_KEY_DESCRIPTOR)
+ );
+ }
+ } else {
+ //
+ // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
+ //
+ ZeroMem (GlobalData->SystemKeyboardLayout, sizeof (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 (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 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;
+ UINTN Count;
+
+ 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 (Count = 0; 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
+ //
+ gBS->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;
+ gBS->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;
+}