]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c
Port DriverSample.inf, HiiDatabase.inf and SetupBrowser.inf
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / HiiDataBaseDxe / Package.c
diff --git a/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c b/IntelFrameworkModulePkg/Universal/HiiDataBaseDxe/Package.c
new file mode 100644 (file)
index 0000000..91f5a3a
--- /dev/null
@@ -0,0 +1,678 @@
+/*++\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