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