hikey: Add UEFI sources for reference

UEFI needs to be built outside Android build system.
Please follow the instructions in README.

The sources correspond to:
https://github.com/96boards/edk2/commit/14eae0c12e71fd33c4c0fc51e4475e8db02566cf
https://github.com/96boards/arm-trusted-firmware/commit/e9b4909dcd75fc4ae7041cfb83d28ab9adb7afdf
https://github.com/96boards/l-loader/commit/6b784ad5c4ab00e2b1c6f53cd5f74054e5d00a78
https://git.linaro.org/uefi/uefi-tools.git/commit/abe618f8ab72034fff1ce46c9c006a2c6bd40a7e

Change-Id: Ieeefdb63e673e0c8e64e0a1f02c7bddc63b2c7fb
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/uefi/linaro-edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/uefi/linaro-edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
new file mode 100644
index 0000000..70c0385
--- /dev/null
+++ b/uefi/linaro-edk2/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
@@ -0,0 +1,3860 @@
+/** @file

+Implementation for EFI_HII_DATABASE_PROTOCOL.

+

+Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>

+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"

+

+/**

+  This function generates a HII_DATABASE_RECORD node and adds into hii database.

+  This is a internal function.

+

+  @param  Private                hii database private structure

+  @param  DatabaseNode           HII_DATABASE_RECORD node which is used to store a

+                                 package list

+

+  @retval EFI_SUCCESS            A database record is generated successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 database contents.

+  @retval EFI_INVALID_PARAMETER  Private is NULL or DatabaseRecord is NULL.

+

+**/

+EFI_STATUS

+GenerateHiiDatabaseRecord (

+  IN  HII_DATABASE_PRIVATE_DATA *Private,

+  OUT HII_DATABASE_RECORD       **DatabaseNode

+  )

+{

+  HII_DATABASE_RECORD                *DatabaseRecord;

+  HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;

+  HII_HANDLE                         *HiiHandle;

+

+  if (Private == NULL || DatabaseNode == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  DatabaseRecord = (HII_DATABASE_RECORD *) AllocateZeroPool (sizeof (HII_DATABASE_RECORD));

+  if (DatabaseRecord == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;

+

+  DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));

+  if (DatabaseRecord->PackageList == NULL) {

+    FreePool (DatabaseRecord);

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  PackageList = DatabaseRecord->PackageList;

+

+  InitializeListHead (&PackageList->GuidPkgHdr);

+  InitializeListHead (&PackageList->FormPkgHdr);

+  InitializeListHead (&PackageList->KeyboardLayoutHdr);

+  InitializeListHead (&PackageList->StringPkgHdr);

+  InitializeListHead (&PackageList->FontPkgHdr);

+  InitializeListHead (&PackageList->SimpleFontPkgHdr);

+  PackageList->ImagePkg      = NULL;

+  PackageList->DevicePathPkg = NULL;

+

+  //

+  // Create a new hii handle

+  //

+  HiiHandle = (HII_HANDLE *) AllocateZeroPool (sizeof (HII_HANDLE));

+  if (HiiHandle == NULL) {

+    FreePool (DatabaseRecord->PackageList);

+    FreePool (DatabaseRecord);

+    return EFI_OUT_OF_RESOURCES;

+  }

+  HiiHandle->Signature = HII_HANDLE_SIGNATURE;

+  //

+  // Backup the number of Hii handles

+  //

+  Private->HiiHandleCount++;

+  HiiHandle->Key = (UINTN) Private->HiiHandleCount;

+  //

+  // Insert the handle to hii handle list of the whole database.

+  //

+  InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);

+

+  DatabaseRecord->Handle = (EFI_HII_HANDLE) HiiHandle;

+

+  //

+  // Insert the Package List node to Package List link of the whole database.

+  //

+  InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);

+

+  *DatabaseNode = DatabaseRecord;

+

+  return EFI_SUCCESS;

+

+}

+

+

+/**

+  This function checks whether a handle is a valid EFI_HII_HANDLE

+  This is a internal function.

+

+  @param  Handle                 Pointer to a EFI_HII_HANDLE

+

+  @retval TRUE                   Valid

+  @retval FALSE                  Invalid

+

+**/

+BOOLEAN

+IsHiiHandleValid (

+  EFI_HII_HANDLE Handle

+  )

+{

+  HII_HANDLE    *HiiHandle;

+

+  HiiHandle = (HII_HANDLE *) Handle;

+

+  if (HiiHandle == NULL) {

+    return FALSE;

+  }

+

+  if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {

+    return FALSE;

+  }

+

+  return TRUE;

+}

+

+

+/**

+  This function invokes the matching registered function.

+  This is a internal function.

+

+  @param  Private                HII Database driver private structure.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageInstance        Points to the package referred to by the

+                                 notification.

+  @param  PackageType            Package type

+  @param  Handle                 The handle of the package list which contains the

+                                 specified package.

+

+  @retval EFI_SUCCESS            Already checked all registered function and

+                                 invoked  if matched.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+InvokeRegisteredFunction (

+  IN HII_DATABASE_PRIVATE_DATA    *Private,

+  IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,

+  IN VOID                         *PackageInstance,

+  IN UINT8                        PackageType,

+  IN EFI_HII_HANDLE               Handle

+  )

+{

+  HII_DATABASE_NOTIFY             *Notify;

+  LIST_ENTRY                      *Link;

+  EFI_HII_PACKAGE_HEADER          *Package;

+  UINT8                           *Buffer;

+  UINT32                          BufferSize;

+  UINT32                          HeaderSize;

+  UINT32                          ImageBlockSize;

+  UINT32                          PaletteInfoSize;

+

+  if (Private == NULL || (NotifyType & 0xF) == 0 || PackageInstance == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (!IsHiiHandleValid (Handle)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Buffer  = NULL;

+  Package = NULL;

+

+  //

+  // Convert the incoming package from hii database storage format to UEFI

+  // storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.

+  //

+  switch (PackageType) {

+  case EFI_HII_PACKAGE_TYPE_GUID:

+    Package = (EFI_HII_PACKAGE_HEADER *) (((HII_GUID_PACKAGE_INSTANCE *) PackageInstance)->GuidPkg);

+    break;

+

+  case EFI_HII_PACKAGE_FORMS:

+    BufferSize = ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr.Length;

+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);

+    ASSERT (Buffer != NULL);

+    CopyMem (

+      Buffer,

+      &((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->FormPkgHdr,

+      sizeof (EFI_HII_PACKAGE_HEADER)

+      );

+    CopyMem (

+      Buffer + sizeof (EFI_HII_PACKAGE_HEADER),

+      ((HII_IFR_PACKAGE_INSTANCE *) PackageInstance)->IfrData,

+      BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)

+      );

+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;

+    break;

+

+  case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:

+    Package = (EFI_HII_PACKAGE_HEADER *) (((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *) PackageInstance)->KeyboardPkg);

+    break;

+

+  case EFI_HII_PACKAGE_STRINGS:

+    BufferSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->Header.Length;

+    HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr->HdrSize;

+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);

+    ASSERT (Buffer != NULL);

+    CopyMem (

+      Buffer,

+      ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringPkgHdr,

+      HeaderSize

+      );

+    CopyMem (

+      Buffer + HeaderSize,

+      ((HII_STRING_PACKAGE_INSTANCE *) PackageInstance)->StringBlock,

+      BufferSize - HeaderSize

+      );

+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;

+    break;

+

+  case EFI_HII_PACKAGE_FONTS:

+    BufferSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->Header.Length;

+    HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr->HdrSize;

+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);

+    ASSERT (Buffer != NULL);

+    CopyMem (

+      Buffer,

+      ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->FontPkgHdr,

+      HeaderSize

+      );

+    CopyMem (

+      Buffer + HeaderSize,

+      ((HII_FONT_PACKAGE_INSTANCE *) PackageInstance)->GlyphBlock,

+      BufferSize - HeaderSize

+      );

+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;

+    break;

+

+  case EFI_HII_PACKAGE_IMAGES:

+    BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr.Header.Length;

+    HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);

+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);

+    ASSERT (Buffer != NULL);

+

+    CopyMem (

+      Buffer,

+      &((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImagePkgHdr,

+      HeaderSize

+      );

+    CopyMem (

+      Buffer + sizeof (EFI_HII_PACKAGE_HEADER),

+      &HeaderSize,

+      sizeof (UINT32)

+      );

+

+    ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlockSize;

+    if (ImageBlockSize != 0) {

+      CopyMem (

+        Buffer + HeaderSize,

+        ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->ImageBlock,

+        ImageBlockSize

+        );

+    }

+

+    PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteInfoSize;

+    if (PaletteInfoSize != 0) {

+      CopyMem (

+        Buffer + HeaderSize + ImageBlockSize,

+        ((HII_IMAGE_PACKAGE_INSTANCE *) PackageInstance)->PaletteBlock,

+        PaletteInfoSize

+        );

+      HeaderSize += ImageBlockSize;

+      CopyMem (

+        Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),

+        &HeaderSize,

+        sizeof (UINT32)

+        );

+    }

+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;

+    break;

+

+  case EFI_HII_PACKAGE_SIMPLE_FONTS:

+    BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr->Header.Length;

+    Buffer = (UINT8 *) AllocateZeroPool (BufferSize);

+    ASSERT (Buffer != NULL);

+    CopyMem (

+      Buffer,

+      ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *) PackageInstance)->SimpleFontPkgHdr,

+      BufferSize

+      );

+    Package = (EFI_HII_PACKAGE_HEADER *) Buffer;

+    break;

+

+  case EFI_HII_PACKAGE_DEVICE_PATH:

+    Package = (EFI_HII_PACKAGE_HEADER *) PackageInstance;

+    break;

+

+  default:

+    return EFI_INVALID_PARAMETER;

+  }

+

+  for (Link = Private->DatabaseNotifyList.ForwardLink;

+       Link != &Private->DatabaseNotifyList;

+       Link = Link->ForwardLink

+      ) {

+    Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);

+    if (Notify->NotifyType == NotifyType && Notify->PackageType == PackageType) {

+      //

+      // Check in case PackageGuid is not NULL when Package is GUID package

+      //

+      if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {

+        Notify->PackageGuid = NULL;

+      }

+      //

+      // Status of Registered Function is unknown so did not check it

+      //

+      Notify->PackageNotifyFn (

+        Notify->PackageType,

+        Notify->PackageGuid,

+        Package,

+        Handle,

+        NotifyType

+        );

+    }

+  }

+

+  if (Buffer != NULL) {

+    FreePool (Buffer);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function insert a GUID package to a package list node.

+  This is a internal function.

+

+  @param  PackageHdr             Pointer to a buffer stored with GUID package

+                                 information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created GUID pacakge

+

+  @retval EFI_SUCCESS            Guid Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Guid package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+InsertGuidPackage (

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT    HII_GUID_PACKAGE_INSTANCE          **Package

+  )

+{

+  HII_GUID_PACKAGE_INSTANCE            *GuidPackage;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+

+  if (PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  //

+  // Create a GUID package node

+  //

+  GuidPackage = (HII_GUID_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));

+  if (GuidPackage == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  GuidPackage->GuidPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);

+  if (GuidPackage->GuidPkg == NULL) {

+    FreePool (GuidPackage);

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;

+  CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);

+  InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);

+  *Package = GuidPackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += PackageHeader.Length;

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function exports GUID packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            Guid Packages are exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportGuidPackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  HII_GUID_PACKAGE_INSTANCE            *GuidPackage;

+  LIST_ENTRY                           *Link;

+  UINTN                                PackageLength;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+  EFI_STATUS                           Status;

+

+  if (PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = 0;

+  Status        = EFI_SUCCESS;

+

+  for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {

+    GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);

+    CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));

+    PackageLength += PackageHeader.Length;

+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+                 (VOID *) GuidPackage,

+                 EFI_HII_PACKAGE_TYPE_GUID,

+                 Handle

+                 );

+      ASSERT_EFI_ERROR (Status);

+      CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);

+      Buffer = (UINT8 *) Buffer + PackageHeader.Length;

+    }

+  }

+

+  *ResultSize += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes all GUID packages from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed GUID packages.

+  @param  PackageList            Pointer to a package list that contains removing

+                                 packages.

+

+  @retval EFI_SUCCESS            GUID Package(s) is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveGuidPackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  LIST_ENTRY                           *ListHead;

+  HII_GUID_PACKAGE_INSTANCE            *Package;

+  EFI_STATUS                           Status;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+

+  ListHead = &PackageList->GuidPkgHdr;

+

+  while (!IsListEmpty (ListHead)) {

+    Package = CR (

+                ListHead->ForwardLink,

+                HII_GUID_PACKAGE_INSTANCE,

+                GuidEntry,

+                HII_GUID_PACKAGE_SIGNATURE

+                );

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_TYPE_GUID,

+               Handle

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    RemoveEntryList (&Package->GuidEntry);

+    CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));

+    PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;

+    FreePool (Package->GuidPkg);

+    FreePool (Package);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function insert a Form package to a package list node.

+  This is a internal function.

+

+  @param  PackageHdr             Pointer to a buffer stored with Form package

+                                 information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created Form package

+

+  @retval EFI_SUCCESS            Form Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Form package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+InsertFormPackage (

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT    HII_IFR_PACKAGE_INSTANCE           **Package

+  )

+{

+  HII_IFR_PACKAGE_INSTANCE *FormPackage;

+  EFI_HII_PACKAGE_HEADER   PackageHeader;

+

+  if (PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Get the length of the package, including package header itself

+  //

+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  //

+  // Create a Form package node

+  //

+  FormPackage = (HII_IFR_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));

+  if (FormPackage == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  FormPackage->IfrData = (UINT8 *) AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));

+  if (FormPackage->IfrData == NULL) {

+    FreePool (FormPackage);

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;

+  //

+  // Copy Package Header

+  //

+  CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  //

+  // Copy Ifr contents

+  //

+  CopyMem (

+    FormPackage->IfrData,

+    (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),

+    PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)

+    );

+

+  InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);

+  *Package = FormPackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;

+  }

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function exports Form packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            Form Packages are exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportFormPackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  HII_IFR_PACKAGE_INSTANCE *FormPackage;

+  UINTN                    PackageLength;

+  LIST_ENTRY               *Link;

+  EFI_STATUS               Status;

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = 0;

+  Status        = EFI_SUCCESS;

+

+  //

+  // Export Form packages.

+  //

+  for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {

+    FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);

+    PackageLength += FormPackage->FormPkgHdr.Length;

+    if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {

+      //

+      // Invoke registered notification if exists

+      //

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+                 (VOID *) FormPackage,

+                 EFI_HII_PACKAGE_FORMS,

+                 Handle

+                 );

+      ASSERT_EFI_ERROR (Status);

+      //

+      // Copy the Form package content.

+      //

+      CopyMem (Buffer, (VOID *) (&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));

+      Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_PACKAGE_HEADER);

+      CopyMem (

+        Buffer,

+        (VOID *) FormPackage->IfrData,

+        FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)

+        );

+      Buffer = (UINT8 *) Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);

+    }

+  }

+

+  *ResultSize += PackageLength;

+

+  return EFI_SUCCESS;

+

+}

+

+

+/**

+  This function deletes all Form packages from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed Form packages.

+  @param  PackageList            Pointer to a package list that contains removing

+                                 packages.

+

+  @retval EFI_SUCCESS            Form Package(s) is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveFormPackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  LIST_ENTRY                      *ListHead;

+  HII_IFR_PACKAGE_INSTANCE        *Package;

+  EFI_STATUS                      Status;

+

+  ListHead = &PackageList->FormPkgHdr;

+

+  while (!IsListEmpty (ListHead)) {

+    Package = CR (

+                ListHead->ForwardLink,

+                HII_IFR_PACKAGE_INSTANCE,

+                IfrEntry,

+                HII_IFR_PACKAGE_SIGNATURE

+                );

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_FORMS,

+               Handle

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    RemoveEntryList (&Package->IfrEntry);

+    PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;

+    FreePool (Package->IfrData);

+    FreePool (Package);

+

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+

+/**

+  This function insert a String package to a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  PackageHdr             Pointer to a buffer stored with String package

+                                 information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created String package

+

+  @retval EFI_SUCCESS            String Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 String package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+  @retval EFI_UNSUPPORTED        A string package with the same language already

+                                 exists in current package list.

+

+**/

+EFI_STATUS

+InsertStringPackage (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT    HII_STRING_PACKAGE_INSTANCE        **Package

+  )

+{

+  HII_STRING_PACKAGE_INSTANCE *StringPackage;

+  UINT32                      HeaderSize;

+  EFI_STATUS                  Status;

+  EFI_HII_PACKAGE_HEADER      PackageHeader;

+  CHAR8                       *Language;

+  UINT32                      LanguageSize;

+  LIST_ENTRY                  *Link;

+

+  if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));

+  CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));

+

+  //

+  // It is illegal to have two string packages with same language within one packagelist

+  // since the stringid will be duplicate if so. Check it to avoid this potential issue.

+  //

+  LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);

+  Language = (CHAR8 *) AllocateZeroPool (LanguageSize);

+  if (Language == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+  AsciiStrCpy (Language, (CHAR8 *) PackageHdr + HeaderSize - LanguageSize);

+  for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {

+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);

+    if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {

+      FreePool (Language);

+      return EFI_UNSUPPORTED;

+    }

+  }

+  FreePool (Language);

+

+  //

+  // Create a String package node

+  //

+  StringPackage = (HII_STRING_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));

+  if (StringPackage == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+

+  StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);

+  if (StringPackage->StringPkgHdr == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+

+  StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);

+  if (StringPackage->StringBlock == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+

+  StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;

+  StringPackage->FontId    = 0;

+  InitializeListHead (&StringPackage->FontInfoList);

+

+  //

+  // Copy the String package header.

+  //

+  CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);

+

+  //

+  // Copy the String blocks

+  //

+  CopyMem (

+    StringPackage->StringBlock,

+    (UINT8 *) PackageHdr + HeaderSize,

+    PackageHeader.Length - HeaderSize

+    );

+

+  //

+  // Collect all font block info

+  //

+  Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID) (-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Insert to String package array

+  //

+  InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);

+  *Package = StringPackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;

+  }

+

+  return EFI_SUCCESS;

+

+Error:

+

+  if (StringPackage != NULL) {

+    if (StringPackage->StringBlock != NULL) {

+      FreePool (StringPackage->StringBlock);

+    }

+    if (StringPackage->StringPkgHdr != NULL) {

+      FreePool (StringPackage->StringPkgHdr);

+    }

+    FreePool (StringPackage);

+  }

+  return Status;

+

+}

+

+/**

+ Adjust all string packages in a single package list to have the same max string ID.

+ 

+ @param  PackageList        Pointer to a package list which will be adjusted.

+

+ @retval EFI_SUCCESS  Adjust all string packages successfully.

+ @retval others       Can't adjust string packges.

+

+**/

+EFI_STATUS

+AdjustStringPackage (

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+)

+{

+  LIST_ENTRY                  *Link;

+  HII_STRING_PACKAGE_INSTANCE *StringPackage;

+  UINT32                      Skip2BlockSize;

+  UINT32                      OldBlockSize;

+  UINT8                       *StringBlock;

+  UINT8                       *BlockPtr;

+  EFI_STRING_ID               MaxStringId;

+  UINT16                      SkipCount;

+

+  MaxStringId = 0;

+  for (Link = PackageList->StringPkgHdr.ForwardLink;

+       Link != &PackageList->StringPkgHdr;

+       Link = Link->ForwardLink

+      ) {

+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);

+    if (MaxStringId < StringPackage->MaxStringId) {

+      MaxStringId = StringPackage->MaxStringId;

+    }

+  }

+

+  for (Link = PackageList->StringPkgHdr.ForwardLink;

+       Link != &PackageList->StringPkgHdr;

+       Link = Link->ForwardLink

+      ) {

+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);

+    if (StringPackage->MaxStringId < MaxStringId) {

+      OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;

+      //

+      // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.

+      //

+      SkipCount      = (UINT16) (MaxStringId - StringPackage->MaxStringId);

+      Skip2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_SKIP2_BLOCK);

+

+      StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Skip2BlockSize);

+      if (StringBlock == NULL) {

+        return EFI_OUT_OF_RESOURCES;

+      }

+      //

+      // Copy original string blocks, except the EFI_HII_SIBT_END.

+      //

+      CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));

+      //

+      // Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks

+      //

+      BlockPtr  = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);

+      *BlockPtr = EFI_HII_SIBT_SKIP2;

+      CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));

+      BlockPtr  += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);

+

+      //

+      // Append a EFI_HII_SIBT_END block to the end.

+      //

+      *BlockPtr = EFI_HII_SIBT_END;

+      FreePool (StringPackage->StringBlock);

+      StringPackage->StringBlock = StringBlock;

+      StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;

+      PackageList->PackageListHdr.PackageLength += Skip2BlockSize;

+      StringPackage->MaxStringId = MaxStringId;

+    }

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  This function exports String packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            String Packages are exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportStringPackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  LIST_ENTRY                  *Link;

+  UINTN                       PackageLength;

+  EFI_STATUS                  Status;

+  HII_STRING_PACKAGE_INSTANCE *StringPackage;

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = 0;

+  Status        = EFI_SUCCESS;

+

+  for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {

+    StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);

+    PackageLength += StringPackage->StringPkgHdr->Header.Length;

+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {

+      //

+      // Invoke registered notification function with EXPORT_PACK notify type

+      //

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+                 (VOID *) StringPackage,

+                 EFI_HII_PACKAGE_STRINGS,

+                 Handle

+                 );

+      ASSERT_EFI_ERROR (Status);

+      //

+      // Copy String package header

+      //

+      CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);

+      Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->HdrSize;

+

+      //

+      // Copy String blocks information

+      //

+      CopyMem (

+        Buffer,

+        StringPackage->StringBlock,

+        StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize

+        );

+      Buffer = (UINT8 *) Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;

+    }

+  }

+

+  *ResultSize += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes all String packages from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed String packages.

+  @param  PackageList            Pointer to a package list that contains removing

+                                 packages.

+

+  @retval EFI_SUCCESS            String Package(s) is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveStringPackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  LIST_ENTRY                      *ListHead;

+  HII_STRING_PACKAGE_INSTANCE     *Package;

+  HII_FONT_INFO                   *FontInfo;

+  EFI_STATUS                      Status;

+

+  ListHead = &PackageList->StringPkgHdr;

+

+  while (!IsListEmpty (ListHead)) {

+    Package = CR (

+                ListHead->ForwardLink,

+                HII_STRING_PACKAGE_INSTANCE,

+                StringEntry,

+                HII_STRING_PACKAGE_SIGNATURE

+                );

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_STRINGS,

+               Handle

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    RemoveEntryList (&Package->StringEntry);

+    PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;

+    FreePool (Package->StringBlock);

+    FreePool (Package->StringPkgHdr);

+    //

+    // Delete font information

+    //

+    while (!IsListEmpty (&Package->FontInfoList)) {

+      FontInfo = CR (

+                   Package->FontInfoList.ForwardLink,

+                   HII_FONT_INFO,

+                   Entry,

+                   HII_FONT_INFO_SIGNATURE

+                   );

+      RemoveEntryList (&FontInfo->Entry);

+      FreePool (FontInfo);

+    }

+

+    FreePool (Package);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function insert a Font package to a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  PackageHdr             Pointer to a buffer stored with Font package

+                                 information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created Font package

+

+  @retval EFI_SUCCESS            Font Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Font package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+  @retval EFI_UNSUPPORTED        A font package with same EFI_FONT_INFO already

+                                 exists in current hii database.

+

+**/

+EFI_STATUS

+InsertFontPackage (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT    HII_FONT_PACKAGE_INSTANCE          **Package

+  )

+{

+  HII_FONT_PACKAGE_INSTANCE *FontPackage;

+  EFI_HII_FONT_PACKAGE_HDR  *FontPkgHdr;

+  UINT32                    HeaderSize;

+  EFI_STATUS                Status;

+  EFI_HII_PACKAGE_HEADER    PackageHeader;

+  EFI_FONT_INFO             *FontInfo;

+  UINT32                    FontInfoSize;

+  HII_GLOBAL_FONT_INFO      *GlobalFont;

+

+  if (Private == NULL || PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));

+  CopyMem (&HeaderSize, (UINT8 *) PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));

+

+  FontInfo    = NULL;

+  FontPackage = NULL;

+  GlobalFont  = NULL;

+

+  //

+  // It is illegal to have two font packages with same EFI_FONT_INFO within hii

+  // database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's

+  // attributes and identify a font uniquely.

+  //

+  FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *) AllocateZeroPool (HeaderSize);

+  if (FontPkgHdr == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  CopyMem (FontPkgHdr, PackageHdr, HeaderSize);

+

+  FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);

+  FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);

+  if (FontInfo == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  FontInfo->FontStyle = FontPkgHdr->FontStyle;

+  FontInfo->FontSize  = FontPkgHdr->Cell.Height;

+  StrCpy (FontInfo->FontName, FontPkgHdr->FontFamily);

+

+  if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {

+    Status = EFI_UNSUPPORTED;

+    goto Error;

+  }

+

+  //

+  // Create a Font package node

+  //

+  FontPackage = (HII_FONT_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));

+  if (FontPackage == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  FontPackage->Signature  = HII_FONT_PACKAGE_SIGNATURE;

+  FontPackage->FontPkgHdr = FontPkgHdr;

+  InitializeListHead (&FontPackage->GlyphInfoList);

+

+  FontPackage->GlyphBlock = (UINT8 *) AllocateZeroPool (PackageHeader.Length - HeaderSize);

+  if (FontPackage->GlyphBlock == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  CopyMem (FontPackage->GlyphBlock, (UINT8 *) PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);

+

+  //

+  // Collect all default character cell information and backup in GlyphInfoList.

+  //

+  Status = FindGlyphBlock (FontPackage, (CHAR16) (-1), NULL, NULL, NULL);

+  if (EFI_ERROR (Status)) {

+    goto Error;

+  }

+

+  //

+  // This font package describes an unique EFI_FONT_INFO. Backup it in global

+  // font info list.

+  //

+  GlobalFont = (HII_GLOBAL_FONT_INFO *) AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));

+  if (GlobalFont == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  GlobalFont->Signature    = HII_GLOBAL_FONT_INFO_SIGNATURE;

+  GlobalFont->FontPackage  = FontPackage;

+  GlobalFont->FontInfoSize = FontInfoSize;

+  GlobalFont->FontInfo     = FontInfo;

+  InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);

+

+  //

+  // Insert this font package to Font package array

+  //

+  InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);

+  *Package = FontPackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;

+  }

+

+  return EFI_SUCCESS;

+

+Error:

+

+  if (FontPkgHdr != NULL) {

+    FreePool (FontPkgHdr);

+  }

+  if (FontInfo != NULL) {

+    FreePool (FontInfo);

+  }

+  if (FontPackage != NULL) {

+    if (FontPackage->GlyphBlock != NULL) {

+      FreePool (FontPackage->GlyphBlock);

+    }

+    FreePool (FontPackage);

+  }

+  if (GlobalFont != NULL) {

+    FreePool (GlobalFont);

+  }

+

+  return Status;

+

+}

+

+

+/**

+  This function exports Font packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            Font Packages are exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportFontPackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  LIST_ENTRY                  *Link;

+  UINTN                       PackageLength;

+  EFI_STATUS                  Status;

+  HII_FONT_PACKAGE_INSTANCE   *Package;

+

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = 0;

+  Status        = EFI_SUCCESS;

+

+  for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {

+    Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);

+    PackageLength += Package->FontPkgHdr->Header.Length;

+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {

+      //

+      // Invoke registered notification function with EXPORT_PACK notify type

+      //

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+                 (VOID *) Package,

+                 EFI_HII_PACKAGE_FONTS,

+                 Handle

+                 );

+      ASSERT_EFI_ERROR (Status);

+      //

+      // Copy Font package header

+      //

+      CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);

+      Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->HdrSize;

+

+      //

+      // Copy Glyph blocks information

+      //

+      CopyMem (

+        Buffer,

+        Package->GlyphBlock,

+        Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize

+        );

+      Buffer = (UINT8 *) Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;

+    }

+  }

+

+  *ResultSize += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes all Font packages from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed Font packages.

+  @param  PackageList            Pointer to a package list that contains removing

+                                 packages.

+

+  @retval EFI_SUCCESS            Font Package(s) is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveFontPackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  LIST_ENTRY                      *ListHead;

+  HII_FONT_PACKAGE_INSTANCE       *Package;

+  EFI_STATUS                      Status;

+  HII_GLYPH_INFO                  *GlyphInfo;

+  LIST_ENTRY                      *Link;

+  HII_GLOBAL_FONT_INFO            *GlobalFont;

+

+  ListHead = &PackageList->FontPkgHdr;

+

+  while (!IsListEmpty (ListHead)) {

+    Package = CR (

+                ListHead->ForwardLink,

+                HII_FONT_PACKAGE_INSTANCE,

+                FontEntry,

+                HII_FONT_PACKAGE_SIGNATURE

+                );

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_FONTS,

+               Handle

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    RemoveEntryList (&Package->FontEntry);

+    PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;

+

+    if (Package->GlyphBlock != NULL) {

+      FreePool (Package->GlyphBlock);

+    }

+    FreePool (Package->FontPkgHdr);

+    //

+    // Delete default character cell information

+    //

+    while (!IsListEmpty (&Package->GlyphInfoList)) {

+      GlyphInfo = CR (

+                    Package->GlyphInfoList.ForwardLink,

+                    HII_GLYPH_INFO,

+                    Entry,

+                    HII_GLYPH_INFO_SIGNATURE

+                    );

+      RemoveEntryList (&GlyphInfo->Entry);

+      FreePool (GlyphInfo);

+    }

+

+    //

+    // Remove corresponding global font info

+    //

+    for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {

+      GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);

+      if (GlobalFont->FontPackage == Package) {

+        RemoveEntryList (&GlobalFont->Entry);

+        FreePool (GlobalFont->FontInfo);

+        FreePool (GlobalFont);

+        break;

+      }

+    }

+

+    FreePool (Package);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function insert a Image package to a package list node.

+  This is a internal function.

+

+  @param  PackageHdr             Pointer to a buffer stored with Image package

+                                 information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created Image package

+

+  @retval EFI_SUCCESS            Image Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Image package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+InsertImagePackage (

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT    HII_IMAGE_PACKAGE_INSTANCE         **Package

+  )

+{

+  HII_IMAGE_PACKAGE_INSTANCE        *ImagePackage;

+  UINT32                            PaletteSize;

+  UINT32                            ImageSize;

+  UINT16                            Index;

+  EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;

+  EFI_HII_IMAGE_PALETTE_INFO        *PaletteInfo;

+  UINT32                            PaletteInfoOffset;

+  UINT32                            ImageInfoOffset;

+  UINT16                            CurrentSize;

+

+  if (PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Less than one image package is allowed in one package list.

+  //

+  if (PackageList->ImagePkg != NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Create a Image package node

+  //

+  ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));

+  if (ImagePackage == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  //

+  // Copy the Image package header.

+  //

+  CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));

+

+  PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;

+  ImageInfoOffset   = ImagePackage->ImagePkgHdr.ImageInfoOffset;

+

+  //

+  // If PaletteInfoOffset is zero, there are no palettes in this image package.

+  //

+  PaletteSize                = 0;

+  ImagePackage->PaletteBlock = NULL;

+  if (PaletteInfoOffset != 0) {

+    PaletteHdr  = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *) ((UINT8 *) PackageHdr + PaletteInfoOffset);

+    PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);

+    PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteHdr + PaletteSize);

+

+    for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {

+      CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));

+      CurrentSize += sizeof (UINT16);

+      PaletteSize += (UINT32) CurrentSize;

+      PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *) ((UINT8 *) PaletteInfo + CurrentSize);

+    }

+

+    ImagePackage->PaletteBlock = (UINT8 *) AllocateZeroPool (PaletteSize);

+    if (ImagePackage->PaletteBlock == NULL) {

+      FreePool (ImagePackage);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    CopyMem (

+      ImagePackage->PaletteBlock,

+      (UINT8 *) PackageHdr + PaletteInfoOffset,

+      PaletteSize

+      );

+  }

+

+  //

+  // If ImageInfoOffset is zero, there are no images in this package.

+  //

+  ImageSize                = 0;

+  ImagePackage->ImageBlock = NULL;

+  if (ImageInfoOffset != 0) {

+    ImageSize = ImagePackage->ImagePkgHdr.Header.Length -

+                sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;

+    ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (ImageSize);

+    if (ImagePackage->ImageBlock == NULL) {

+      FreePool (ImagePackage->PaletteBlock);

+      FreePool (ImagePackage);

+      return EFI_OUT_OF_RESOURCES;

+    }

+    CopyMem (

+      ImagePackage->ImageBlock,

+      (UINT8 *) PackageHdr + ImageInfoOffset,

+      ImageSize

+      );

+  }

+

+  ImagePackage->ImageBlockSize  = ImageSize;

+  ImagePackage->PaletteInfoSize = PaletteSize;

+  PackageList->ImagePkg         = ImagePackage;

+  *Package                      = ImagePackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function exports Image packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            Image Packages are exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportImagePackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  UINTN                       PackageLength;

+  EFI_STATUS                  Status;

+  HII_IMAGE_PACKAGE_INSTANCE  *Package;

+

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Package = PackageList->ImagePkg;

+

+  if (Package == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  PackageLength = Package->ImagePkgHdr.Header.Length;

+

+  if (PackageLength + *ResultSize + UsedSize <= BufferSize) {

+    //

+    // Invoke registered notification function with EXPORT_PACK notify type

+    //

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_IMAGES,

+               Handle

+               );

+    ASSERT_EFI_ERROR (Status);

+    ASSERT (Package->ImagePkgHdr.Header.Length ==

+            sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize);

+    //

+    // Copy Image package header,

+    // then justify the offset for image info and palette info in the header.

+    //

+    CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));

+    Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);

+

+    //

+    // Copy Image blocks information

+    //

+    if (Package->ImageBlockSize != 0) {

+      CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);

+      Buffer = (UINT8 *) Buffer + Package->ImageBlockSize;

+    }

+    //

+    // Copy Palette information

+    //

+    if (Package->PaletteInfoSize != 0) {

+      CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);

+      Buffer = (UINT8 *) Buffer + Package->PaletteInfoSize;

+    }

+  }

+

+  *ResultSize += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes Image package from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed Image packages.

+  @param  PackageList            Package List which contains the to be  removed

+                                 Image package.

+

+  @retval EFI_SUCCESS            Image Package(s) is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveImagePackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  HII_IMAGE_PACKAGE_INSTANCE      *Package;

+  EFI_STATUS                      Status;

+

+  Package = PackageList->ImagePkg;

+

+  //

+  // Image package does not exist, return directly.

+  //

+  if (Package == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  Status = InvokeRegisteredFunction (

+             Private,

+             EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+             (VOID *) Package,

+             EFI_HII_PACKAGE_IMAGES,

+             Handle

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;

+

+  FreePool (Package->ImageBlock);

+  if (Package->PaletteBlock != NULL) {

+    FreePool (Package->PaletteBlock);

+  }

+  FreePool (Package);

+

+  PackageList->ImagePkg = NULL;

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function insert a Simple Font package to a package list node.

+  This is a internal function.

+

+  @param  PackageHdr             Pointer to a buffer stored with Simple Font

+                                 package information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created Simple Font package

+

+  @retval EFI_SUCCESS            Simple Font Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Simple Font package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+InsertSimpleFontPackage (

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE      **Package

+  )

+{

+  HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;

+  EFI_STATUS                       Status;

+  EFI_HII_PACKAGE_HEADER           Header;

+

+  if (PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Create a Simple Font package node

+  //

+  SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));

+  if (SimpleFontPackage == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;

+

+  //

+  // Copy the Simple Font package.

+  //

+  CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);

+  if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+

+  CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);

+

+  //

+  // Insert to Simple Font package array

+  //

+  InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);

+  *Package = SimpleFontPackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += Header.Length;

+  }

+

+  return EFI_SUCCESS;

+

+Error:

+

+  if (SimpleFontPackage != NULL) {

+    if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {

+      FreePool (SimpleFontPackage->SimpleFontPkgHdr);

+    }

+    FreePool (SimpleFontPackage);

+  }

+  return Status;

+}

+

+

+/**

+  This function exports SimpleFont packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            SimpleFont Packages are exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportSimpleFontPackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  LIST_ENTRY                        *Link;

+  UINTN                             PackageLength;

+  EFI_STATUS                        Status;

+  HII_SIMPLE_FONT_PACKAGE_INSTANCE  *Package;

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = 0;

+  Status        = EFI_SUCCESS;

+

+  for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {

+    Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);

+    PackageLength += Package->SimpleFontPkgHdr->Header.Length;

+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {

+      //

+      // Invoke registered notification function with EXPORT_PACK notify type

+      //

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+                 (VOID *) Package,

+                 EFI_HII_PACKAGE_SIMPLE_FONTS,

+                 Handle

+                 );

+      ASSERT_EFI_ERROR (Status);

+

+      //

+      // Copy SimpleFont package

+      //

+      CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);

+      Buffer = (UINT8 *) Buffer + Package->SimpleFontPkgHdr->Header.Length;

+    }

+  }

+

+  *ResultSize += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes all Simple Font packages from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed Simple Font packages.

+  @param  PackageList            Pointer to a package list that contains removing

+                                 packages.

+

+  @retval EFI_SUCCESS            Simple Font Package(s) is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveSimpleFontPackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  LIST_ENTRY                       *ListHead;

+  HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;

+  EFI_STATUS                       Status;

+

+  ListHead = &PackageList->SimpleFontPkgHdr;

+

+  while (!IsListEmpty (ListHead)) {

+    Package = CR (

+                ListHead->ForwardLink,

+                HII_SIMPLE_FONT_PACKAGE_INSTANCE,

+                SimpleFontEntry,

+                HII_S_FONT_PACKAGE_SIGNATURE

+                );

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_SIMPLE_FONTS,

+               Handle

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    RemoveEntryList (&Package->SimpleFontEntry);

+    PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;

+    FreePool (Package->SimpleFontPkgHdr);

+    FreePool (Package);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function insert a Device path package to a package list node.

+  This is a internal function.

+

+  @param  DevicePath             Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol

+                                 instance

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+

+  @retval EFI_SUCCESS            Device path Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Device path package.

+  @retval EFI_INVALID_PARAMETER  DevicePath is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+InsertDevicePathPackage (

+  IN     EFI_DEVICE_PATH_PROTOCOL           *DevicePath,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  UINT32                           PackageLength;

+  EFI_HII_PACKAGE_HEADER           Header;

+

+  if (DevicePath == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // Less than one device path package is allowed in one package list.

+  //

+  if (PackageList->DevicePathPkg != NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = (UINT32) GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);

+  PackageList->DevicePathPkg = (UINT8 *) AllocateZeroPool (PackageLength);

+  if (PackageList->DevicePathPkg == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  Header.Length = PackageLength;

+  Header.Type   = EFI_HII_PACKAGE_DEVICE_PATH;

+  CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));

+  CopyMem (

+    PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),

+    DevicePath,

+    PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)

+    );

+

+  //

+  // Since Device Path package is created by NewPackageList, either NEW_PACK

+  // or ADD_PACK should increase the length of package list.

+  //

+  PackageList->PackageListHdr.PackageLength += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function exports device path package to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            Device path Package is exported successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportDevicePathPackage (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  EFI_STATUS                       Status;

+  UINT8                            *Package;

+  EFI_HII_PACKAGE_HEADER           Header;

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Package = PackageList->DevicePathPkg;

+

+  if (Package == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  if (Header.Length + *ResultSize + UsedSize <= BufferSize) {

+    //

+    // Invoke registered notification function with EXPORT_PACK notify type

+    //

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_DEVICE_PATH,

+               Handle

+               );

+    ASSERT_EFI_ERROR (Status);

+

+    //

+    // Copy Device path package

+    //

+    CopyMem (Buffer, Package, Header.Length);

+  }

+

+  *ResultSize += Header.Length;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes Device Path package from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list.

+  @param  PackageList            Package List which contains the to be  removed

+                                 Device Path package.

+

+  @retval EFI_SUCCESS            Device Path Package is deleted successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveDevicePathPackage (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  EFI_STATUS                       Status;

+  UINT8                            *Package;

+  EFI_HII_PACKAGE_HEADER           Header;

+

+  Package = PackageList->DevicePathPkg;

+

+  //

+  // No device path, return directly.

+  //

+  if (Package == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  Status = InvokeRegisteredFunction (

+             Private,

+             EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+             (VOID *) Package,

+             EFI_HII_PACKAGE_DEVICE_PATH,

+             Handle

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));

+  PackageList->PackageListHdr.PackageLength -= Header.Length;

+

+  FreePool (Package);

+

+  PackageList->DevicePathPkg = NULL;

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function will insert a device path package to package list firstly then

+  invoke notification functions if any.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  NotifyType             The type of change concerning the database.

+  @param  DevicePath             Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol

+                                 instance

+  @param  DatabaseRecord         Pointer to a database record contains  a package

+                                 list which will be inserted to.

+

+  @retval EFI_SUCCESS            Device path Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Device path package.

+  @retval EFI_INVALID_PARAMETER  DevicePath is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+AddDevicePathPackage (

+  IN HII_DATABASE_PRIVATE_DATA        *Private,

+  IN EFI_HII_DATABASE_NOTIFY_TYPE     NotifyType,

+  IN EFI_DEVICE_PATH_PROTOCOL         *DevicePath,

+  IN OUT HII_DATABASE_RECORD          *DatabaseRecord

+  )

+{

+  EFI_STATUS                          Status;

+

+  if (DevicePath == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  ASSERT (Private != NULL);

+  ASSERT (DatabaseRecord != NULL);

+

+  //

+  // Create a device path package and insert to packagelist

+  //

+  Status = InsertDevicePathPackage (

+               DevicePath,

+               NotifyType,

+               DatabaseRecord->PackageList

+               );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return InvokeRegisteredFunction (

+            Private,

+            NotifyType,

+            (VOID *) DatabaseRecord->PackageList->DevicePathPkg,

+            EFI_HII_PACKAGE_DEVICE_PATH,

+            DatabaseRecord->Handle

+            );

+}

+

+

+/**

+  This function insert a Keyboard Layout package to a package list node.

+  This is a internal function.

+

+  @param  PackageHdr             Pointer to a buffer stored with Keyboard Layout

+                                 package information.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list which will be inserted

+                                 to.

+  @param  Package                Created Keyboard Layout package

+

+  @retval EFI_SUCCESS            Keyboard Layout Package is inserted successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Keyboard Layout package.

+  @retval EFI_INVALID_PARAMETER  PackageHdr is NULL or PackageList is NULL.

+

+**/

+EFI_STATUS

+InsertKeyboardLayoutPackage (

+  IN     VOID                               *PackageHdr,

+  IN     EFI_HII_DATABASE_NOTIFY_TYPE       NotifyType,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE  **Package

+  )

+{

+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+  EFI_STATUS                           Status;

+

+  if (PackageHdr == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  //

+  // Create a Keyboard Layout package node

+  //

+  KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));

+  if (KeyboardLayoutPackage == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+  KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;

+

+  KeyboardLayoutPackage->KeyboardPkg = (UINT8 *) AllocateZeroPool (PackageHeader.Length);

+  if (KeyboardLayoutPackage->KeyboardPkg == NULL) {

+    Status = EFI_OUT_OF_RESOURCES;

+    goto Error;

+  }

+

+  CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);

+  InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);

+

+  *Package = KeyboardLayoutPackage;

+

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    PackageList->PackageListHdr.PackageLength += PackageHeader.Length;

+  }

+

+  return EFI_SUCCESS;

+

+Error:

+

+

+  if (KeyboardLayoutPackage != NULL) {

+    if (KeyboardLayoutPackage->KeyboardPkg != NULL) {

+      FreePool (KeyboardLayoutPackage->KeyboardPkg);

+    }

+    FreePool (KeyboardLayoutPackage);

+  }

+

+  return Status;

+}

+

+

+/**

+  This function exports Keyboard Layout packages to a buffer.

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer be used.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+  @param  ResultSize             The size of the already exported content of  this

+                                 package list.

+

+  @retval EFI_SUCCESS            Keyboard Layout Packages are exported

+                                 successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportKeyboardLayoutPackages (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN UINTN                              UsedSize,

+  IN UINTN                              BufferSize,

+  IN OUT VOID                           *Buffer,

+  IN OUT UINTN                          *ResultSize

+  )

+{

+  LIST_ENTRY                           *Link;

+  UINTN                                PackageLength;

+  EFI_STATUS                           Status;

+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+

+  if (Private == NULL || PackageList == NULL || ResultSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  PackageLength = 0;

+  Status        = EFI_SUCCESS;

+

+  for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {

+    Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);

+    CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));

+    PackageLength += PackageHeader.Length;

+    if (PackageLength + *ResultSize + UsedSize <= BufferSize) {

+      //

+      // Invoke registered notification function with EXPORT_PACK notify type

+      //

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,

+                 (EFI_HII_PACKAGE_HEADER *) Package,

+                 EFI_HII_PACKAGE_KEYBOARD_LAYOUT,

+                 Handle

+                 );

+      ASSERT_EFI_ERROR (Status);

+

+      //

+      // Copy Keyboard Layout package

+      //

+      CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);

+      Buffer = (UINT8 *) Buffer + PackageHeader.Length;

+    }

+  }

+

+  *ResultSize += PackageLength;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function deletes all Keyboard Layout packages from a package list node.

+  This is a internal function.

+

+  @param  Private                Hii database private data.

+  @param  Handle                 Handle of the package list which contains the to

+                                 be  removed Keyboard Layout packages.

+  @param  PackageList            Pointer to a package list that contains removing

+                                 packages.

+

+  @retval EFI_SUCCESS            Keyboard Layout Package(s) is deleted

+                                 successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is not valid.

+

+**/

+EFI_STATUS

+RemoveKeyboardLayoutPackages (

+  IN     HII_DATABASE_PRIVATE_DATA          *Private,

+  IN     EFI_HII_HANDLE                     Handle,

+  IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList

+  )

+{

+  LIST_ENTRY                           *ListHead;

+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+  EFI_STATUS                           Status;

+

+  ListHead = &PackageList->KeyboardLayoutHdr;

+

+  while (!IsListEmpty (ListHead)) {

+    Package = CR (

+                ListHead->ForwardLink,

+                HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,

+                KeyboardEntry,

+                HII_KB_LAYOUT_PACKAGE_SIGNATURE

+                );

+    Status = InvokeRegisteredFunction (

+               Private,

+               EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,

+               (VOID *) Package,

+               EFI_HII_PACKAGE_KEYBOARD_LAYOUT,

+               Handle

+               );

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    RemoveEntryList (&Package->KeyboardEntry);

+    CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));

+    PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;

+    FreePool (Package->KeyboardPkg);

+    FreePool (Package);

+  }

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function will insert a package list to hii database firstly then

+  invoke notification functions if any. It is the worker function of

+  HiiNewPackageList and HiiUpdatePackageList.

+

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  NotifyType             The type of change concerning the database.

+  @param  PackageList            Pointer to a package list.

+  @param  DatabaseRecord         Pointer to a database record contains  a package

+                                 list instance which will be inserted to.

+

+  @retval EFI_SUCCESS            All incoming packages are inserted to current

+                                 database.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 Device path package.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+AddPackages (

+  IN HII_DATABASE_PRIVATE_DATA         *Private,

+  IN EFI_HII_DATABASE_NOTIFY_TYPE      NotifyType,

+  IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,

+  IN OUT   HII_DATABASE_RECORD         *DatabaseRecord

+  )

+{

+  EFI_STATUS                           Status;

+  HII_GUID_PACKAGE_INSTANCE            *GuidPackage;

+  HII_IFR_PACKAGE_INSTANCE             *FormPackage;

+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;

+  HII_STRING_PACKAGE_INSTANCE          *StringPackage;

+  HII_FONT_PACKAGE_INSTANCE            *FontPackage;

+  HII_SIMPLE_FONT_PACKAGE_INSTANCE     *SimpleFontPackage;

+  HII_IMAGE_PACKAGE_INSTANCE           *ImagePackage;

+  EFI_HII_PACKAGE_HEADER               *PackageHdrPtr;

+  EFI_HII_PACKAGE_HEADER               PackageHeader;

+  UINT32                               OldPackageListLen;

+  BOOLEAN                              StringPkgIsAdd;

+

+  //

+  // Initialize Variables

+  //

+  StringPkgIsAdd        = FALSE;

+  FontPackage           = NULL;

+  StringPackage         = NULL;

+  GuidPackage           = NULL;

+  FormPackage           = NULL;

+  ImagePackage          = NULL;

+  SimpleFontPackage     = NULL;

+  KeyboardLayoutPackage = NULL;

+

+  //

+  // Process the package list header

+  //

+  OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;

+  CopyMem (

+    &DatabaseRecord->PackageList->PackageListHdr,

+    (VOID *) PackageList,

+    sizeof (EFI_HII_PACKAGE_LIST_HEADER)

+    );

+  if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {

+    DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;

+  }

+

+  PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));

+  CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));

+

+  Status = EFI_SUCCESS;

+

+  while (PackageHeader.Type != EFI_HII_PACKAGE_END) {

+    switch (PackageHeader.Type) {

+    case EFI_HII_PACKAGE_TYPE_GUID:

+      Status = InsertGuidPackage (

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &GuidPackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) GuidPackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      break;

+    case EFI_HII_PACKAGE_FORMS:

+      Status = InsertFormPackage (

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &FormPackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) FormPackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      break;

+    case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:

+      Status = InsertKeyboardLayoutPackage (

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &KeyboardLayoutPackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) KeyboardLayoutPackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      break;

+    case EFI_HII_PACKAGE_STRINGS:

+      Status = InsertStringPackage (

+                 Private,

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &StringPackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      ASSERT (StringPackage != NULL);

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) StringPackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      StringPkgIsAdd = TRUE;

+      break;

+    case EFI_HII_PACKAGE_FONTS:

+      Status = InsertFontPackage (

+                 Private,

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &FontPackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) FontPackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      break;

+    case EFI_HII_PACKAGE_IMAGES:

+      Status = InsertImagePackage (

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &ImagePackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) ImagePackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      break;

+    case EFI_HII_PACKAGE_SIMPLE_FONTS:

+      Status = InsertSimpleFontPackage (

+                 PackageHdrPtr,

+                 NotifyType,

+                 DatabaseRecord->PackageList,

+                 &SimpleFontPackage

+                 );

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = InvokeRegisteredFunction (

+                 Private,

+                 NotifyType,

+                 (VOID *) SimpleFontPackage,

+                 (UINT8) (PackageHeader.Type),

+                 DatabaseRecord->Handle

+                 );

+      break;

+    case EFI_HII_PACKAGE_DEVICE_PATH:

+      Status = AddDevicePathPackage (

+                 Private,

+                 NotifyType,

+                 (EFI_DEVICE_PATH_PROTOCOL *) ((UINT8 *) PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),

+                 DatabaseRecord

+                 );

+      break;

+    default:

+      break;

+    }

+

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+    //

+    // goto header of next package

+    //

+    PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);

+    CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));

+  }

+  

+  //

+  // Adjust String Package to make sure all string packages have the same max string ID.

+  //

+  if (!EFI_ERROR (Status) && StringPkgIsAdd) {

+    Status = AdjustStringPackage (DatabaseRecord->PackageList);

+  }

+

+  return Status;

+}

+

+

+/**

+  This function exports a package list to a buffer. It is the worker function

+  of HiiExportPackageList.

+

+  This is a internal function.

+

+  @param  Private                Hii database private structure.

+  @param  Handle                 Identification of a package list.

+  @param  PackageList            Pointer to a package list which will be exported.

+  @param  UsedSize               The length of buffer has been used by exporting

+                                 package lists when Handle is NULL.

+  @param  BufferSize             Length of the Buffer.

+  @param  Buffer                 Allocated space for storing exported data.

+

+  @retval EFI_SUCCESS            Keyboard Layout Packages are exported

+                                 successfully.

+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.

+

+**/

+EFI_STATUS

+ExportPackageList (

+  IN HII_DATABASE_PRIVATE_DATA          *Private,

+  IN EFI_HII_HANDLE                     Handle,

+  IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,

+  IN OUT UINTN                          *UsedSize,

+  IN UINTN                              BufferSize,

+  OUT EFI_HII_PACKAGE_LIST_HEADER       *Buffer

+  )

+{

+  EFI_STATUS                          Status;

+  UINTN                               ResultSize;

+  EFI_HII_PACKAGE_HEADER              EndofPackageList;

+

+  ASSERT (Private != NULL && PackageList != NULL && UsedSize != NULL);

+  ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);

+  ASSERT (IsHiiHandleValid (Handle));

+

+  if (BufferSize > 0 && Buffer == NULL ) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Copy the package list header

+  // ResultSize indicates the length of the exported bytes of this package list

+  //

+  ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);

+  if (ResultSize + *UsedSize <= BufferSize) {

+    CopyMem ((VOID *) Buffer, PackageList, ResultSize);

+  }

+  //

+  // Copy the packages and invoke EXPORT_PACK notify functions if exists.

+  //

+  Status = ExportGuidPackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportFormPackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportKeyboardLayoutPackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportStringPackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportFontPackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportImagePackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportSimpleFontPackages (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  Status = ExportDevicePathPackage (

+             Private,

+             Handle,

+             PackageList,

+             *UsedSize,

+             BufferSize,

+             (VOID *) ((UINT8 *) Buffer + ResultSize),

+             &ResultSize

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+  //

+  // Append the package list end.

+  //

+  EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);

+  EndofPackageList.Type   = EFI_HII_PACKAGE_END;

+  if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {

+    CopyMem (

+      (VOID *) ((UINT8 *) Buffer + ResultSize),

+      (VOID *) &EndofPackageList,

+      sizeof (EFI_HII_PACKAGE_HEADER)

+      );

+  }

+

+  *UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function adds the packages in the package list to the database and returns a handle. If there is a

+  EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will

+  create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  PackageList            A pointer to an EFI_HII_PACKAGE_LIST_HEADER

+                                 structure.

+  @param  DriverHandle           Associate the package list with this EFI handle.

+                                 If a NULL is specified, this data will not be associate

+                                 with any drivers and cannot have a callback induced.

+  @param  Handle                 A pointer to the EFI_HII_HANDLE instance.

+

+  @retval EFI_SUCCESS            The package list associated with the Handle was

+                                 added to the HII database.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary resources for the new

+                                 database contents.

+  @retval EFI_INVALID_PARAMETER  PackageList is NULL or Handle is NULL.

+  @retval EFI_INVALID_PARAMETER  PackageListGuid already exists in database.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiNewPackageList (

+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,

+  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList,

+  IN CONST EFI_HANDLE                   DriverHandle, OPTIONAL

+  OUT EFI_HII_HANDLE                    *Handle

+  )

+{

+  EFI_STATUS                          Status;

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  HII_DATABASE_RECORD                 *DatabaseRecord;

+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;

+  LIST_ENTRY                          *Link;

+  EFI_GUID                            PackageListGuid;

+

+  if (This == NULL || PackageList == NULL || Handle == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+  CopyMem (&PackageListGuid, (VOID *) PackageList, sizeof (EFI_GUID));

+

+  //

+  // Check the Package list GUID to guarantee this GUID is unique in database.

+  //

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    if (CompareGuid (

+          &(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),

+          &PackageListGuid) && 

+        DatabaseRecord->DriverHandle == DriverHandle) {

+      return EFI_INVALID_PARAMETER;

+    }

+  }

+

+  //

+  // Build a PackageList node

+  //

+  Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Fill in information of the created Package List node

+  // according to incoming package list.

+  //

+  Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, PackageList, DatabaseRecord);

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  DatabaseRecord->DriverHandle = DriverHandle;

+

+  //

+  // Create a Device path package and add into the package list if exists.

+  //

+  Status = gBS->HandleProtocol (

+                  DriverHandle,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID **) &DevicePath

+                  );

+  if (!EFI_ERROR (Status)) {

+    Status = AddDevicePathPackage (Private, EFI_HII_DATABASE_NOTIFY_NEW_PACK, DevicePath, DatabaseRecord);

+    ASSERT_EFI_ERROR (Status);

+  }

+

+  *Handle = DatabaseRecord->Handle;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function removes the package list that is associated with a handle Handle

+  from the HII database. Before removing the package, any registered functions

+  with the notification type REMOVE_PACK and the same package type will be called.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  Handle                 The handle that was registered to the data that is

+                                 requested  for removal.

+

+  @retval EFI_SUCCESS            The data associated with the Handle was removed

+                                 from  the HII database.

+  @retval EFI_NOT_FOUND          The specified andle is not in database.

+  @retval EFI_INVALID_PARAMETER  The Handle was not valid.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiRemovePackageList (

+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,

+  IN EFI_HII_HANDLE                     Handle

+  )

+{

+  EFI_STATUS                          Status;

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  LIST_ENTRY                          *Link;

+  HII_DATABASE_RECORD                 *Node;

+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageList;

+  HII_HANDLE                          *HiiHandle;

+

+  if (This == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (!IsHiiHandleValid (Handle)) {

+    return EFI_NOT_FOUND;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+

+  //

+  // Get the packagelist to be removed.

+  //

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    if (Node->Handle == Handle) {

+      PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);

+      ASSERT (PackageList != NULL);

+

+      //

+      // Call registered functions with REMOVE_PACK before removing packages

+      // then remove them.

+      //

+      Status = RemoveGuidPackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveFormPackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveStringPackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveFontPackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveImagePackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveSimpleFontPackages (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+      Status = RemoveDevicePathPackage (Private, Handle, PackageList);

+      if (EFI_ERROR (Status)) {

+        return Status;

+      }

+

+      //

+      // Free resources of the package list

+      //

+      RemoveEntryList (&Node->DatabaseEntry);

+

+      HiiHandle = (HII_HANDLE *) Handle;

+      RemoveEntryList (&HiiHandle->Handle);

+      Private->HiiHandleCount--;

+      ASSERT (Private->HiiHandleCount >= 0);

+

+      HiiHandle->Signature = 0;

+      FreePool (HiiHandle);

+      FreePool (Node->PackageList);

+      FreePool (Node);

+

+      return EFI_SUCCESS;

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+

+/**

+  This function updates the existing package list (which has the specified Handle)

+  in the HII databases, using the new package list specified by PackageList.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  Handle                 The handle that was registered to the data that is

+                                  requested to be updated.

+  @param  PackageList            A pointer to an EFI_HII_PACKAGE_LIST_HEADER

+                                 package.

+

+  @retval EFI_SUCCESS            The HII database was successfully updated.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate enough memory for the updated

+                                 database.

+  @retval EFI_INVALID_PARAMETER  PackageList was NULL.

+  @retval EFI_NOT_FOUND          The specified Handle is not in database.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiUpdatePackageList (

+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,

+  IN EFI_HII_HANDLE                     Handle,

+  IN CONST EFI_HII_PACKAGE_LIST_HEADER  *PackageList

+  )

+{

+  EFI_STATUS                          Status;

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  LIST_ENTRY                          *Link;

+  HII_DATABASE_RECORD                 *Node;

+  EFI_HII_PACKAGE_HEADER              *PackageHdrPtr;

+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *OldPackageList;

+  EFI_HII_PACKAGE_HEADER              PackageHeader;

+

+  if (This == NULL || PackageList == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (!IsHiiHandleValid (Handle)) {

+    return EFI_NOT_FOUND;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+

+  PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));

+

+  Status = EFI_SUCCESS;

+

+  //

+  // Get original packagelist to be updated

+  //

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    if (Node->Handle == Handle) {

+      OldPackageList = Node->PackageList;

+      //

+      // Remove the package if its type matches one of the package types which is

+      // contained in the new package list.

+      //

+      CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));

+      while (PackageHeader.Type != EFI_HII_PACKAGE_END) {

+        switch (PackageHeader.Type) {

+        case EFI_HII_PACKAGE_TYPE_GUID:

+          Status = RemoveGuidPackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_FORMS:

+          Status = RemoveFormPackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:

+          Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_STRINGS:

+          Status = RemoveStringPackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_FONTS:

+          Status = RemoveFontPackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_IMAGES:

+          Status = RemoveImagePackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_SIMPLE_FONTS:

+          Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);

+          break;

+        case EFI_HII_PACKAGE_DEVICE_PATH:

+          Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);

+          break;

+        }

+

+        if (EFI_ERROR (Status)) {

+          return Status;

+        }

+

+        PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHdrPtr + PackageHeader.Length);

+        CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));

+      }

+

+      //

+      // Add all of the packages within the new package list

+      //

+      return AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+

+/**

+  This function returns a list of the package handles of the specified type

+  that are currently active in the database. The pseudo-type

+  EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  PackageType            Specifies the package type of the packages to list

+                                 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be

+                                 listed.

+  @param  PackageGuid            If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then

+                                 this  is the pointer to the GUID which must match

+                                 the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.

+                                 Otherwise,  it must be NULL.

+  @param  HandleBufferLength     On input, a pointer to the length of the handle

+                                 buffer.  On output, the length of the handle

+                                 buffer that is required for the handles found.

+  @param  Handle                 An array of EFI_HII_HANDLE instances returned.

+

+  @retval EFI_SUCCESS            The matching handles are outputed successfully.

+                                 HandleBufferLength is updated with the actual length.

+  @retval EFI_BUFFER_TO_SMALL    The HandleBufferLength parameter indicates that

+                                 Handle is too small to support the number of

+                                 handles. HandleBufferLength is updated with a

+                                 value that will  enable the data to fit.

+  @retval EFI_NOT_FOUND          No matching handle could not be found in database.

+  @retval EFI_INVALID_PARAMETER  HandleBufferLength was NULL.

+  @retval EFI_INVALID_PARAMETER  The value referenced by HandleBufferLength was not

+                                 zero and Handle was NULL.

+  @retval EFI_INVALID_PARAMETER  PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but

+                                 PackageGuid is not NULL, PackageType is a EFI_HII_

+                                 PACKAGE_TYPE_GUID but PackageGuid is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiListPackageLists (

+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,

+  IN  UINT8                             PackageType,

+  IN  CONST EFI_GUID                    *PackageGuid,

+  IN  OUT UINTN                         *HandleBufferLength,

+  OUT EFI_HII_HANDLE                    *Handle

+  )

+{

+  HII_GUID_PACKAGE_INSTANCE           *GuidPackage;

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  HII_DATABASE_RECORD                 *Node;

+  LIST_ENTRY                          *Link;

+  BOOLEAN                             Matched;

+  HII_HANDLE                          **Result;

+  UINTN                               ResultSize;

+  HII_DATABASE_PACKAGE_LIST_INSTANCE  *PackageList;

+  LIST_ENTRY                          *Link1;

+

+  //

+  // Check input parameters

+  //

+  if (This == NULL || HandleBufferLength == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (*HandleBufferLength > 0 && Handle == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||

+      (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private    = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+  Matched    = FALSE;

+  Result     = (HII_HANDLE **) Handle;

+  ResultSize = 0;

+

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);

+    switch (PackageType) {

+      case EFI_HII_PACKAGE_TYPE_GUID:

+        for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {

+          GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);

+          if (CompareGuid (

+                (EFI_GUID *) PackageGuid,

+                (EFI_GUID *) (GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))

+                )) {

+            Matched = TRUE;

+            break;

+          }

+        }

+        break;

+      case EFI_HII_PACKAGE_FORMS:

+        if (!IsListEmpty (&PackageList->FormPkgHdr)) {

+          Matched = TRUE;

+        }

+        break;

+      case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:

+        if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {

+          Matched = TRUE;

+        }

+        break;

+      case EFI_HII_PACKAGE_STRINGS:

+        if (!IsListEmpty (&PackageList->StringPkgHdr)) {

+          Matched = TRUE;

+        }

+        break;

+      case EFI_HII_PACKAGE_FONTS:

+        if (!IsListEmpty (&PackageList->FontPkgHdr)) {

+          Matched = TRUE;

+        }

+        break;

+      case EFI_HII_PACKAGE_IMAGES:

+        if (PackageList->ImagePkg != NULL) {

+          Matched = TRUE;

+        }

+        break;

+      case EFI_HII_PACKAGE_SIMPLE_FONTS:

+        if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {

+          Matched = TRUE;

+        }

+        break;

+      case EFI_HII_PACKAGE_DEVICE_PATH:

+        if (PackageList->DevicePathPkg != NULL) {

+          Matched = TRUE;

+        }

+        break;

+        //

+        // Pesudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles

+        // to be listed.

+        //

+      case EFI_HII_PACKAGE_TYPE_ALL:

+        Matched = TRUE;

+        break;

+      default:

+        break;

+    }

+

+    //

+    // This active package list has the specified package type, list it.

+    //

+    if (Matched) {

+      ResultSize += sizeof (EFI_HII_HANDLE);

+      if (ResultSize <= *HandleBufferLength) {

+        *Result++ = Node->Handle;

+      }

+    }

+    Matched = FALSE;

+  }

+

+  if (ResultSize == 0) {

+    return EFI_NOT_FOUND;

+  }

+

+  if (*HandleBufferLength < ResultSize) {

+    *HandleBufferLength = ResultSize;

+    return EFI_BUFFER_TOO_SMALL;

+  }

+

+  *HandleBufferLength = ResultSize;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This function will export one or all package lists in the database to a buffer.

+  For each package list exported, this function will call functions registered

+  with EXPORT_PACK and then copy the package list to the buffer.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  Handle                 An EFI_HII_HANDLE that corresponds to the desired

+                                 package list in the HII database to export or NULL

+                                 to indicate  all package lists should be exported.

+  @param  BufferSize             On input, a pointer to the length of the buffer.

+                                 On output, the length of the buffer that is

+                                 required for the exported data.

+  @param  Buffer                 A pointer to a buffer that will contain the

+                                 results of  the export function.

+

+  @retval EFI_SUCCESS            Package exported.

+  @retval EFI_BUFFER_TO_SMALL    The HandleBufferLength parameter indicates that

+                                 Handle is too small to support the number of

+                                 handles.      HandleBufferLength is updated with a

+                                 value that will enable the data to fit.

+  @retval EFI_NOT_FOUND          The specifiecd Handle could not be found in the

+                                 current database.

+  @retval EFI_INVALID_PARAMETER  BufferSize was NULL.

+  @retval EFI_INVALID_PARAMETER  The value referenced by BufferSize was not zero 

+                                 and Buffer was NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiExportPackageLists (

+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,

+  IN  EFI_HII_HANDLE                    Handle,

+  IN  OUT UINTN                         *BufferSize,

+  OUT EFI_HII_PACKAGE_LIST_HEADER       *Buffer

+  )

+{

+  LIST_ENTRY                          *Link;

+  EFI_STATUS                          Status;

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  HII_DATABASE_RECORD                 *Node;

+  UINTN                               UsedSize;

+

+  if (This == NULL || BufferSize == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (*BufferSize > 0 && Buffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if ((Handle != NULL) && (!IsHiiHandleValid (Handle))) {

+    return EFI_NOT_FOUND;

+  }

+

+  Private  = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+  UsedSize = 0;

+

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    if (Handle == NULL) {

+      //

+      // Export all package lists in current hii database.

+      //

+      Status = ExportPackageList (

+                 Private,

+                 Node->Handle,

+                 (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),

+                 &UsedSize,

+                 *BufferSize,

+                 (EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *) Buffer + UsedSize)

+                 );

+      ASSERT_EFI_ERROR (Status);

+    } else if (Handle != NULL && Node->Handle == Handle) {

+      Status = ExportPackageList (

+                 Private,

+                 Handle,

+                 (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList),

+                 &UsedSize,

+                 *BufferSize,

+                 Buffer

+                 );

+      ASSERT_EFI_ERROR (Status);

+      if (*BufferSize < UsedSize) {

+        *BufferSize = UsedSize;

+        return EFI_BUFFER_TOO_SMALL;

+      }

+      return EFI_SUCCESS;

+    }

+  }

+

+  if (Handle == NULL && UsedSize != 0) {

+    if (*BufferSize < UsedSize) {

+      *BufferSize = UsedSize;

+      return EFI_BUFFER_TOO_SMALL;

+    }

+    return EFI_SUCCESS;

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+

+/**

+  This function registers a function which will be called when specified actions related to packages of

+  the specified type occur in the HII database. By registering a function, other HII-related drivers are

+  notified when specific package types are added, removed or updated in the HII database.

+  Each driver or application which registers a notification should use

+  EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  PackageType            Specifies the package type of the packages to list

+                                 or EFI_HII_PACKAGE_TYPE_ALL for all packages to be

+                                 listed.

+  @param  PackageGuid            If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then

+                                 this is the pointer to the GUID which must match

+                                 the Guid field of

+                                 EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must

+                                 be NULL.

+  @param  PackageNotifyFn        Points to the function to be called when the event

+                                 specified by

+                                 NotificationType occurs.

+  @param  NotifyType             Describes the types of notification which this

+                                 function will be receiving.

+  @param  NotifyHandle           Points to the unique handle assigned to the

+                                 registered notification. Can be used in

+                                 EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()

+                                 to stop notifications.

+

+  @retval EFI_SUCCESS            Notification registered successfully.

+  @retval EFI_OUT_OF_RESOURCES   Unable to allocate necessary data structures

+  @retval EFI_INVALID_PARAMETER  NotifyHandle is NULL.

+  @retval EFI_INVALID_PARAMETER  PackageGuid is not NULL when PackageType is not

+                                 EFI_HII_PACKAGE_TYPE_GUID.

+  @retval EFI_INVALID_PARAMETER  PackageGuid is NULL when PackageType is

+                                 EFI_HII_PACKAGE_TYPE_GUID.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiRegisterPackageNotify (

+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,

+  IN  UINT8                             PackageType,

+  IN  CONST EFI_GUID                    *PackageGuid,

+  IN  CONST EFI_HII_DATABASE_NOTIFY     PackageNotifyFn,

+  IN  EFI_HII_DATABASE_NOTIFY_TYPE      NotifyType,

+  OUT EFI_HANDLE                        *NotifyHandle

+  )

+{

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  HII_DATABASE_NOTIFY                 *Notify;

+  EFI_STATUS                          Status;

+

+  if (This == NULL || NotifyHandle == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if ((PackageType == EFI_HII_PACKAGE_TYPE_GUID && PackageGuid == NULL) ||

+      (PackageType != EFI_HII_PACKAGE_TYPE_GUID && PackageGuid != NULL)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+

+  //

+  // Allocate a notification node

+  //

+  Notify = (HII_DATABASE_NOTIFY *) AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));

+  if (Notify == NULL) {

+    return EFI_OUT_OF_RESOURCES;

+  }

+

+  //

+  // Generate a notify handle

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &Notify->NotifyHandle,

+                  &gEfiCallerIdGuid,

+                  NULL,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Fill in the information to the notification node

+  //

+  Notify->Signature       = HII_DATABASE_NOTIFY_SIGNATURE;

+  Notify->PackageType     = PackageType;

+  Notify->PackageGuid     = (EFI_GUID *) PackageGuid;

+  Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY) PackageNotifyFn;

+  Notify->NotifyType      = NotifyType;

+

+  InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);

+  *NotifyHandle = Notify->NotifyHandle;

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Removes the specified HII database package-related notification.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  NotificationHandle     The handle of the notification function being

+                                 unregistered.

+

+  @retval EFI_SUCCESS            Notification is unregistered successfully.

+  @retval EFI_INVALID_PARAMETER  The Handle is invalid.

+  @retval EFI_NOT_FOUND          The incoming notification handle does not exist

+                                 in current hii database.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiUnregisterPackageNotify (

+  IN CONST EFI_HII_DATABASE_PROTOCOL    *This,

+  IN EFI_HANDLE                         NotificationHandle

+  )

+{

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  HII_DATABASE_NOTIFY                 *Notify;

+  LIST_ENTRY                          *Link;

+  EFI_STATUS                          Status;

+

+  if (This == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (NotificationHandle == NULL) {

+    return EFI_NOT_FOUND;

+  }

+

+  Status = gBS->OpenProtocol (

+                  NotificationHandle,

+                  &gEfiCallerIdGuid,

+                  NULL,

+                  NULL,

+                  NULL,

+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+                  );

+  if (EFI_ERROR (Status)) {

+    return EFI_NOT_FOUND;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+

+  for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {

+    Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);

+    if (Notify->NotifyHandle == NotificationHandle) {

+      //

+      // Remove the matching notification node

+      //

+      RemoveEntryList (&Notify->DatabaseNotifyEntry);

+      Status = gBS->UninstallMultipleProtocolInterfaces (

+                      Notify->NotifyHandle,

+                      &gEfiCallerIdGuid,

+                      NULL,

+                      NULL

+                      );

+      ASSERT_EFI_ERROR (Status);

+      FreePool (Notify);

+

+      return EFI_SUCCESS;

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+

+/**

+  This routine retrieves an array of GUID values for each keyboard layout that

+  was previously registered in the system.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  KeyGuidBufferLength    On input, a pointer to the length of the keyboard

+                                 GUID  buffer. On output, the length of the handle

+                                 buffer  that is required for the handles found.

+  @param  KeyGuidBuffer          An array of keyboard layout GUID instances

+                                 returned.

+

+  @retval EFI_SUCCESS            KeyGuidBuffer was updated successfully.

+  @retval EFI_BUFFER_TOO_SMALL   The KeyGuidBufferLength parameter indicates

+                                 that KeyGuidBuffer is too small to support the

+                                 number of GUIDs. KeyGuidBufferLength is

+                                 updated with a value that will enable the data to

+                                 fit.

+  @retval EFI_INVALID_PARAMETER  The KeyGuidBufferLength is NULL.

+  @retval EFI_INVALID_PARAMETER  The value referenced by KeyGuidBufferLength is not

+                                 zero and KeyGuidBuffer is NULL.

+  @retval EFI_NOT_FOUND          There was no keyboard layout.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiFindKeyboardLayouts (

+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,

+  IN  OUT UINT16                        *KeyGuidBufferLength,

+  OUT EFI_GUID                          *KeyGuidBuffer

+  )

+{

+  HII_DATABASE_PRIVATE_DATA            *Private;

+  HII_DATABASE_RECORD                  *Node;

+  HII_DATABASE_PACKAGE_LIST_INSTANCE   *PackageList;

+  LIST_ENTRY                           *Link;

+  LIST_ENTRY                           *Link1;

+  UINT16                               ResultSize;

+  UINTN                                Index;

+  UINT16                               LayoutCount;

+  UINT16                               LayoutLength;

+  UINT8                                *Layout;

+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;

+

+  if (This == NULL || KeyGuidBufferLength == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (*KeyGuidBufferLength > 0 && KeyGuidBuffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private     = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+  ResultSize  = 0;

+

+  //

+  // Search all package lists in whole database to retrieve keyboard layout.

+  //

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    PackageList = Node->PackageList;

+    for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;

+         Link1 != &PackageList->KeyboardLayoutHdr;

+         Link1 = Link1->ForwardLink

+        ) {

+      //

+      // Find out all Keyboard Layout packages in this package list.

+      //

+      Package = CR (

+                  Link1,

+                  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,

+                  KeyboardEntry,

+                  HII_KB_LAYOUT_PACKAGE_SIGNATURE

+                  );

+      Layout = (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);

+      CopyMem (

+        &LayoutCount,

+        (UINT8 *) Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),

+        sizeof (UINT16)

+        );

+      for (Index = 0; Index < LayoutCount; Index++) {

+        ResultSize += sizeof (EFI_GUID);

+        if (ResultSize <= *KeyGuidBufferLength) {

+          CopyMem (KeyGuidBuffer + (ResultSize / sizeof (EFI_GUID) - 1), Layout + sizeof (UINT16), sizeof (EFI_GUID));

+          CopyMem (&LayoutLength, Layout, sizeof (UINT16));

+          Layout = Layout + LayoutLength;

+        }

+      }

+    }

+  }

+

+  if (ResultSize == 0) {

+    return EFI_NOT_FOUND;

+  }

+

+  if (*KeyGuidBufferLength < ResultSize) {

+    *KeyGuidBufferLength = ResultSize;

+    return EFI_BUFFER_TOO_SMALL;

+  }

+

+  *KeyGuidBufferLength = ResultSize;

+  return EFI_SUCCESS;

+}

+

+

+/**

+  This routine retrieves the requested keyboard layout. The layout is a physical description of the keys

+  on a keyboard and the character(s) that are associated with a particular set of key strokes.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  KeyGuid                A pointer to the unique ID associated with a given

+                                 keyboard layout. If KeyGuid is NULL then the

+                                 current layout will be retrieved.

+  @param  KeyboardLayoutLength   On input, a pointer to the length of the

+                                 KeyboardLayout buffer.  On output, the length of

+                                 the data placed into KeyboardLayout.

+  @param  KeyboardLayout         A pointer to a buffer containing the retrieved

+                                 keyboard layout.

+

+  @retval EFI_SUCCESS            The keyboard layout was retrieved successfully.

+  @retval EFI_NOT_FOUND          The requested keyboard layout was not found.

+  @retval EFI_INVALID_PARAMETER  The KeyboardLayout or KeyboardLayoutLength was

+                                 NULL.

+  @retval EFI_BUFFER_TOO_SMALL   The KeyboardLayoutLength parameter indicates

+                                 that KeyboardLayout is too small to support the

+                                 requested keyboard layout. KeyboardLayoutLength is

+                                        updated with a value that will enable the

+                                 data to fit.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiGetKeyboardLayout (

+  IN  CONST EFI_HII_DATABASE_PROTOCOL   *This,

+  IN  CONST EFI_GUID                          *KeyGuid,

+  IN OUT UINT16                         *KeyboardLayoutLength,

+  OUT EFI_HII_KEYBOARD_LAYOUT           *KeyboardLayout

+  )

+{

+  HII_DATABASE_PRIVATE_DATA            *Private;

+  HII_DATABASE_RECORD                  *Node;

+  HII_DATABASE_PACKAGE_LIST_INSTANCE   *PackageList;

+  LIST_ENTRY                           *Link;

+  LIST_ENTRY                           *Link1;

+  UINTN                                Index;

+  UINT8                                *Layout;

+  UINT16                               LayoutCount;

+  UINT16                               LayoutLength;

+  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;

+

+  if (This == NULL || KeyboardLayoutLength == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  if (*KeyboardLayoutLength > 0 && KeyboardLayout == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+  //

+  // Retrieve the current keyboard layout.

+  //

+  if (KeyGuid == NULL) {

+    if (Private->CurrentLayout == NULL) {

+      return EFI_NOT_FOUND;

+    }

+    CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));

+    if (*KeyboardLayoutLength < LayoutLength) {

+      *KeyboardLayoutLength = LayoutLength;

+      return EFI_BUFFER_TOO_SMALL;

+    }

+    CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);

+    return EFI_SUCCESS;

+  }

+

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (Node->PackageList);

+    for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;

+         Link1 != &PackageList->KeyboardLayoutHdr;

+         Link1 = Link1->ForwardLink

+        ) {

+      Package = CR (

+                  Link1,

+                  HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,

+                  KeyboardEntry,

+                  HII_KB_LAYOUT_PACKAGE_SIGNATURE

+                  );

+

+      Layout = (UINT8 *) Package->KeyboardPkg +

+               sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);

+      CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));

+      for (Index = 0; Index < LayoutCount; Index++) {

+        CopyMem (&LayoutLength, Layout, sizeof (UINT16));

+        if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {

+          if (LayoutLength <= *KeyboardLayoutLength) {

+            CopyMem (KeyboardLayout, Layout, LayoutLength);

+            return EFI_SUCCESS;

+          } else {

+            *KeyboardLayoutLength = LayoutLength;

+            return EFI_BUFFER_TOO_SMALL;

+          }

+        }

+        Layout = Layout + LayoutLength;

+      }

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+

+/**

+  This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine

+  is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID

+  group type. This is so that agents which are sensitive to the current keyboard layout being changed

+  can be notified of this change.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  KeyGuid                A pointer to the unique ID associated with a given

+                                 keyboard layout.

+

+  @retval EFI_SUCCESS            The current keyboard layout was successfully set.

+  @retval EFI_NOT_FOUND          The referenced keyboard layout was not found, so

+                                 action was taken.

+  @retval EFI_INVALID_PARAMETER  The KeyGuid was NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiSetKeyboardLayout (

+  IN CONST EFI_HII_DATABASE_PROTOCOL          *This,

+  IN CONST EFI_GUID                           *KeyGuid

+  )

+{

+  HII_DATABASE_PRIVATE_DATA            *Private;

+  EFI_HII_KEYBOARD_LAYOUT              *KeyboardLayout;

+  UINT16                               KeyboardLayoutLength;

+  EFI_STATUS                           Status;

+

+  if (This == NULL || KeyGuid == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+

+  //

+  // The specified GUID equals the current keyboard layout GUID,

+  // return directly.

+  //

+  if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // Try to find the incoming keyboard layout data in current database.

+  //

+  KeyboardLayoutLength = 0;

+  KeyboardLayout       = NULL;

+  Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);

+  if (Status != EFI_BUFFER_TOO_SMALL) {

+    return Status;

+  }

+

+  KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *) AllocateZeroPool (KeyboardLayoutLength);

+  ASSERT (KeyboardLayout != NULL);

+  Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Backup current keyboard layout.

+  //

+  CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));

+  if (Private->CurrentLayout != NULL) {

+    FreePool(Private->CurrentLayout);

+  }

+  Private->CurrentLayout = KeyboardLayout;

+

+  //

+  // Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify

+  // current keyboard layout is changed.

+  //

+  Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);

+  ASSERT_EFI_ERROR (Status);

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Return the EFI handle associated with a package list.

+

+  @param  This                   A pointer to the EFI_HII_DATABASE_PROTOCOL

+                                 instance.

+  @param  PackageListHandle      An EFI_HII_HANDLE that corresponds to the desired

+                                 package list in the HIIdatabase.

+  @param  DriverHandle           On return, contains the EFI_HANDLE which was

+                                 registered with the package list in

+                                 NewPackageList().

+

+  @retval EFI_SUCCESS            The DriverHandle was returned successfully.

+  @retval EFI_INVALID_PARAMETER  The PackageListHandle was not valid or

+                                 DriverHandle was NULL.

+  @retval EFI_NOT_FOUND          This PackageList handle can not be found in

+                                 current database.

+

+**/

+EFI_STATUS

+EFIAPI

+HiiGetPackageListHandle (

+  IN  CONST EFI_HII_DATABASE_PROTOCOL         *This,

+  IN  EFI_HII_HANDLE                    PackageListHandle,

+  OUT EFI_HANDLE                        *DriverHandle

+  )

+{

+  HII_DATABASE_PRIVATE_DATA           *Private;

+  HII_DATABASE_RECORD                 *Node;

+  LIST_ENTRY                          *Link;

+

+  if (This == NULL || DriverHandle == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (!IsHiiHandleValid (PackageListHandle)) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);

+

+  for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {

+    Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);

+    if (Node->Handle == PackageListHandle) {

+      *DriverHandle = Node->DriverHandle;

+      return EFI_SUCCESS;

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+