alder_lake_bios/Insyde/InsydeModulePkg/Universal/UserInterface/HiiDatabaseDxe/Database.c

4167 lines
140 KiB
C

/** @file
Implementation for EFI_HII_DATABASE_PROTOCOL.
;******************************************************************************
;* Copyright (c) 2012 - 2020, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
Copyright (c) 2007 - 2011, 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[in] Private hii database private structure
@param[out] 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->AnimationPkg = 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[in] Handle Pointer to a EFI_HII_HANDLE
@retval TRUE Valid
@retval FALSE Invalid
**/
BOOLEAN
IsHiiHandleValid (
IN 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[in] Private HII Database driver private structure.
@param[in] NotifyType The type of change concerning the database.
@param[in] PackageInstance Points to the package referred to by the
notification.
@param[in] PackageType Package type
@param[in] 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;
UINT32 AnimationBlockSize;
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;
}
//
// Check if these is a matching registered notify type and register type.
//
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) {
break;
}
}
if (Link == &Private->DatabaseNotifyList) {
return EFI_SUCCESS;
}
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);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
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);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
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);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
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);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
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_ANIMATIONS:
BufferSize = ((HII_ANIMATION_PACKAGE_INSTANCE *) PackageInstance)->AnimationPkgHdr.Header.Length;
HeaderSize = sizeof (EFI_HII_ANIMATION_PACKAGE_HDR);
Buffer = (UINT8 *) AllocateZeroPool (BufferSize);
ASSERT (Buffer != NULL);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (
Buffer,
&((HII_ANIMATION_PACKAGE_INSTANCE *) PackageInstance)->AnimationPkgHdr,
HeaderSize
);
CopyMem (
Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
&HeaderSize,
sizeof (UINT32)
);
AnimationBlockSize = ((HII_ANIMATION_PACKAGE_INSTANCE *) PackageInstance)->AnimationBlockSize;
if (AnimationBlockSize != 0) {
CopyMem (
Buffer + HeaderSize,
((HII_ANIMATION_PACKAGE_INSTANCE *) PackageInstance)->AnimationBlock,
AnimationBlockSize
);
}
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);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
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[in] PackageHdr Pointer to a buffer stored with GUID package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed GUID packages.
@param[in, out] 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[in] PackageHdr Pointer to a buffer stored with Form package
information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed Form packages.
@param[in, out] 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[in] Private Hii database private structure.
@param[in] PackageHdr Pointer to a buffer stored with String package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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;
}
AsciiStrCpyS (Language, LanguageSize, (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->StringBlockSize = (UINTN) SUGGEST_STRING_BLOCK_BUFFER_SIZE(PackageHeader.Length - HeaderSize);
StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (StringPackage->StringBlockSize);
if (StringPackage->StringBlock == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
StringPackage->StringBlockInfoCount = 0x500;
StringPackage->StringBlockInfo = (HII_STRING_BLOCK_INFO *) AllocateZeroPool (sizeof (HII_STRING_BLOCK_INFO) * StringPackage->StringBlockInfoCount);
if (StringPackage->StringBlockInfo == 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->StringBlockInfo != NULL) {
FreePool (StringPackage->StringBlockInfo);
}
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[in, out] 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);
if (StringPackage->StringBlockSize < (OldBlockSize + Skip2BlockSize)) {
StringPackage->StringBlockSize = (UINTN) SUGGEST_STRING_BLOCK_BUFFER_SIZE (OldBlockSize + Skip2BlockSize);
StringBlock = (UINT8 *) AllocateZeroPool (StringPackage->StringBlockSize);
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));
} else {
StringBlock = StringPackage->StringBlock;
}
//
// Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks
//
BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
SetMem (BlockPtr, sizeof (EFI_HII_SIBT_SKIP2_BLOCK), 0);
*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;
if (StringPackage->StringBlock != StringBlock) {
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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed String packages.
@param[in, out] 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);
FreePool (Package->StringBlockInfo);
//
// 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;
}
/**
Internal function to initialize true type font database
@param[in] Buffer TTF file buffer
@param[in] BufferSize input buffer size
@retval EFI_SUCCESS Initialize true type font database successfully.
@retval EFI_NOT_FOUND Cannot find true type decoder protocol.
@retval other Initialize true type data failure caused by ture type decoder protcol.
**/
STATIC
EFI_STATUS
InitTtfDatabase (
IN UINT8 *Buffer,
IN UINT32 BufferSize
)
{
TRUE_TYPE_DECODER_PROTOCOL *TrueTypeDecoder;
if (Buffer == NULL || BufferSize == 0) {
return EFI_INVALID_PARAMETER;
}
TrueTypeDecoder = GetTrueTypeDecoderProtocol ();
if (TrueTypeDecoder == NULL) {
return EFI_UNSUPPORTED;
}
return TrueTypeDecoder->SetDataBase (
TrueTypeDecoder,
Buffer,
BufferSize
);
}
/**
This function insert a Font package to a package list node.
This is a internal function.
@param[in] Private Hii database private structure.
@param[in] PackageHdr Pointer to a buffer stored with Font package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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;
StrCpyS (FontInfo->FontName, (HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR)) / sizeof(CHAR16) + 1, 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;
}
if (IsTtfFontPackage (FontInfo->FontName)) {
InitTtfDatabase (FontPackage->GlyphBlock, PackageHeader.Length - HeaderSize);
}
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);
}
return Status;
}
/**
This function exports Font packages to a buffer.
This is a internal function.
@param[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed Font packages.
@param[in, out] 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[in] PackageHdr Pointer to a buffer stored with Image package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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;
EFI_STATUS Status;
UINT8 *SourcePkgDataPtr;
UINT8 *ParsedPackageData;
UINT32 ParsedPackageDataLength;
UINT32 OriginalImagePackageLength;
ParsedPackageData = NULL;
ParsedPackageDataLength = 0;
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) {
//
// Check if this is a multi image package.
// If so, let board id decide which package data will be installed.
// Call ClassifyMultiBoardImageBlock() to get package data for the board we are running on.
//
// Ex. This package contains images for Default 00
// board 0x04
// board 0x0B
//
// If we are running on board 0x0B, then this function return image package data for board 0x0B.
//
// +-----------------+ +------+
// | | | | ----> ClassifyMultiBoardImageBlock () ----> | |
// +-----------------+ +------+
//
SourcePkgDataPtr = (UINT8 *)PackageHdr + ImageInfoOffset;
Status = ClassifyMultiBoardImageBlock(
SourcePkgDataPtr,
(VOID **)&ParsedPackageData,
(VOID *)&ParsedPackageDataLength
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
if (ImagePackage->PaletteBlock != NULL) {
FreePool (ImagePackage->PaletteBlock);
}
FreePool (ImagePackage);
return Status;
}
//
// Update header size.
// [Header 12byte] + [ParsedPackageDataLength + EFI_HII_IIBT_END 1byte] + [PaletteSize].
//
ImagePackage->ImagePkgHdr.Header.Length = sizeof (EFI_HII_IMAGE_PACKAGE_HDR)
+ ParsedPackageDataLength + sizeof (UINT8) + PaletteSize;
//
// Update PaletteInfoOffset only if Palette exists in this package.
//
if (ImagePackage->ImagePkgHdr.PaletteInfoOffset != 0) {
ImagePackage->ImagePkgHdr.PaletteInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset
+ ParsedPackageDataLength + sizeof (UINT8);
}
ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
ImagePackage->ImageBlock = (UINT8 *) AllocateZeroPool (ImageSize);
if (ImagePackage->ImageBlock == NULL) {
if (ImagePackage->PaletteBlock != NULL) {
FreePool (ImagePackage->PaletteBlock);
}
FreePool (ImagePackage);
if (ParsedPackageData != NULL) {
FreePool (ParsedPackageData);
}
return EFI_OUT_OF_RESOURCES;
}
//
// Insyde multi image package extension.
// Install image package belongs to current board.
//
CopyMem (
ImagePackage->ImageBlock,
ParsedPackageData,
ParsedPackageDataLength
);
//
// Append a end block.
//
*(ImagePackage->ImageBlock + ParsedPackageDataLength) = EFI_HII_IIBT_END;
//
// Update package list length.
//
OriginalImagePackageLength = ((EFI_HII_IMAGE_PACKAGE_HDR *)PackageHdr)->Header.Length;
PackageList->PackageListHdr.PackageLength -= OriginalImagePackageLength;
PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
//
// Insyde multi image package extension.
// Data installed in hii completelly, so now ParsedPackageData is no longer required,free it.
//
if (ParsedPackageData != NULL) {
FreePool (ParsedPackageData);
}
}
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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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);
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes Image package from a package list node.
This is a internal function.
@param[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed Image packages.
@param[in, out] 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 animation package to a package list node.
@param[in] PackageHdr Pointer to a buffer stored with animation package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] Package Created animation package
@retval EFI_SUCCESS Animation Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new animation package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
@retval EFI_UNSUPPORTED A animtion package with the same language already exists
in current package list.
**/
STATIC
EFI_STATUS
InsertAnimationPackage (
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_ANIMATION_PACKAGE_INSTANCE **Package
)
{
HII_ANIMATION_PACKAGE_INSTANCE *AnimationPackage;
UINT32 AnimationInfoOffset;
UINT32 AnimationSize;
if (PackageHdr == NULL || PackageList == NULL) {
return EFI_INVALID_PARAMETER;
}
if (PackageList->AnimationPkg != NULL) {
return EFI_INVALID_PARAMETER;
}
AnimationPackage = (HII_ANIMATION_PACKAGE_INSTANCE *) AllocateZeroPool (sizeof (HII_ANIMATION_PACKAGE_INSTANCE));
if (AnimationPackage == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (&AnimationPackage->AnimationPkgHdr, PackageHdr, sizeof (EFI_HII_ANIMATION_PACKAGE_HDR));
AnimationInfoOffset = AnimationPackage->AnimationPkgHdr.AnimationInfoOffset;
AnimationSize = 0;
AnimationPackage->AnimationBlock = NULL;
AnimationPackage->AnimationBlockSize = 0;
if (AnimationInfoOffset != 0) {
AnimationSize = AnimationPackage->AnimationPkgHdr.Header.Length -
sizeof (EFI_HII_ANIMATION_PACKAGE_HDR);
AnimationPackage->AnimationBlock = (UINT8 *) AllocateZeroPool (AnimationSize);
if (AnimationPackage->AnimationBlock == NULL) {
FreePool (AnimationPackage);
return EFI_OUT_OF_RESOURCES;
}
CopyMem (
AnimationPackage->AnimationBlock,
(UINT8 *) PackageHdr + AnimationInfoOffset,
AnimationSize
);
}
AnimationPackage->AnimationBlockSize = AnimationSize;
PackageList->AnimationPkg = AnimationPackage;
*Package = AnimationPackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += AnimationPackage->AnimationPkgHdr.Header.Length;
}
return EFI_SUCCESS;
}
/**
This function exports animation packages to a buffer.
@param[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize Address offset of RTC.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] ResultSize The size of the already exported content of this package list.
@retval EFI_SUCCESS Animation Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
STATIC
EFI_STATUS
ExportAnimationPackages (
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_ANIMATION_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->AnimationPkg;
if (Package == NULL) {
return EFI_SUCCESS;
}
PackageLength = Package->AnimationPkgHdr.Header.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *) Package,
EFI_HII_PACKAGE_ANIMATIONS,
Handle
);
ASSERT_EFI_ERROR (Status);
ASSERT (Package->AnimationPkgHdr.Header.Length ==
sizeof (EFI_HII_ANIMATION_PACKAGE_HDR) + Package->AnimationBlockSize);
CopyMem (Buffer, &Package->AnimationPkgHdr, sizeof (EFI_HII_ANIMATION_PACKAGE_HDR));
Buffer = (UINT8 *) Buffer + sizeof (EFI_HII_ANIMATION_PACKAGE_HDR);
if (Package->AnimationBlockSize != 0) {
CopyMem (Buffer, Package->AnimationBlock, Package->AnimationBlockSize);
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes Animation package from a package list node.
@param[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to be removed animation packages.
@param[in, out] PackageList Package List which contains the to be removed animation package.
@retval EFI_SUCCESS Animation Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
STATIC
EFI_STATUS
RemoveAnimationPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
HII_ANIMATION_PACKAGE_INSTANCE *Package;
EFI_STATUS Status;
Package = PackageList->AnimationPkg;
if (Package == NULL) {
return EFI_SUCCESS;
}
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *) Package,
EFI_HII_PACKAGE_ANIMATIONS,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
PackageList->PackageListHdr.PackageLength -= Package->AnimationPkgHdr.Header.Length;
FreePool (Package->AnimationBlock);
FreePool (Package);
PackageList->AnimationPkg = NULL;
return EFI_SUCCESS;
}
/**
This function insert a Simple Font package to a package list node.
This is a internal function.
@param[in] PackageHdr Pointer to a buffer stored with Simple Font
package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed Simple Font packages.
@param[in, out] 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[in] DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol instance
@param[in] NotifyType The type of change concerning the database.
@param[in, out] 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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list.
@param[in, out] 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[in] Private Hii database private structure.
@param[in] NotifyType The type of change concerning the database.
@param[in] DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol instance
@param[in, out] 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[in] PackageHdr Pointer to a buffer stored with Keyboard Layout
package information.
@param[in] NotifyType The type of change concerning the database.
@param[in, out] PackageList Pointer to a package list which will be inserted to.
@param[out] 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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in] UsedSize The length of buffer be used.
@param[in] BufferSize Length of the Buffer.
@param[in, out] Buffer Allocated space for storing exported data.
@param[in, out] 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[in] Private Hii database private data.
@param[in] Handle Handle of the package list which contains the to
be removed Keyboard Layout packages.
@param[in, out] 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[in] Private Hii database private structure.
@param[in] NotifyType The type of change concerning the database.
@param[in] PackageList Pointer to a package list.
@param[in, out] 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;
HII_ANIMATION_PACKAGE_INSTANCE *AnimationPackage;
EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
EFI_HII_PACKAGE_HEADER PackageHeader;
UINT32 OldPackageListLen;
BOOLEAN StringPkgIsAdd;
//
// Initialize Variables
//
StringPkgIsAdd = FALSE;
FontPackage = NULL;
StringPackage = NULL;
AnimationPackage = 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_ANIMATIONS:
Status = InsertAnimationPackage (
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&AnimationPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *) AnimationPackage,
(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[in] Private Hii database private structure.
@param[in] Handle Identification of a package list.
@param[in] PackageList Pointer to a package list which will be exported.
@param[in, out] UsedSize The length of buffer has been used by exporting
package lists when Handle is NULL.
@param[in] BufferSize Length of the Buffer.
@param[out] 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;
EFI_HII_PACKAGE_LIST_HEADER *ListHeader;
BOOLEAN NeedFixHeader;
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
//
NeedFixHeader = FALSE;
ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
if (ResultSize + *UsedSize <= BufferSize) {
CopyMem ((VOID *) Buffer, PackageList, ResultSize);
NeedFixHeader = TRUE;
}
//
// 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 = ExportAnimationPackages (
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)
);
}
//
// double check the HII Package List size,
// if package length isn't equal result size,
// Maybe call this function in NEW_PACK callback
//
//
if (NeedFixHeader) {
ListHeader = (EFI_HII_PACKAGE_LIST_HEADER *)Buffer;
if (ListHeader->PackageLength != (ResultSize + sizeof (EFI_HII_PACKAGE_HEADER))) {
ListHeader->PackageLength = (UINT32)(ResultSize + 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param[in] PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
structure.
@param[in] 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[out] 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] 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 = RemoveAnimationPackages (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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param[in] Handle The handle that was registered to the data that is
requested to be updated.
@param[in] 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_ANIMATIONS:
Status = RemoveAnimationPackages (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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] PackageType Specifies the package type of the packages to list
or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
listed.
@param[in] 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[in, out] 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[out] 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 Handle or HandleBufferLength 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] 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[in, out] 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[out] 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 Handle or Buffer or BufferSize 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] PackageType Specifies the package type of the packages to list
or EFI_HII_PACKAGE_TYPE_ALL for all packages to be listed.
@param[in] 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[in] PackageNotifyFn Points to the function to be called when the event
specified by NotificationType occurs.
@param[in] NotifyType Describes the types of notification which this
function will be receiving.
@param[out] 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in, out] 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[out] 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 KeyGuidBuffer or KeyGuidBufferLength was 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] 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[in, out] KeyboardLayoutLength On input, a pointer to the length of the
KeyboardLayout buffer. On output, the length of
the data placed into KeyboardLayout.
@param[out] 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] 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[in] This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@param[in] PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
package list in the HIIdatabase.
@param[out] 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;
}