blob: 0b09c24d52a47347acc5c67fdaac6d68d4116352 [file] [log] [blame]
/** @file
Implementation for EFI_HII_DATABASE_PROTOCOL.
Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "HiiDatabase.h"
#define BASE_NUMBER 10
EFI_HII_PACKAGE_LIST_HEADER *gRTDatabaseInfoBuffer = NULL;
EFI_STRING gRTConfigRespBuffer = NULL;
UINTN gDatabaseInfoSize = 0;
UINTN gConfigRespSize = 0;
BOOLEAN gExportConfigResp = FALSE;
UINTN gNvDefaultStoreSize = 0;
SKU_ID gSkuId = 0xFFFFFFFFFFFFFFFF;
LIST_ENTRY gVarStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gVarStorageList);
//
// HII database lock.
//
EFI_LOCK mHiiDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
/**
This function generates a HII_DATABASE_RECORD node and adds into hii database.
This is a internal function.
@param Private hii database private structure
@param DatabaseNode HII_DATABASE_RECORD node which is used to store a
package list
@retval EFI_SUCCESS A database record is generated successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
database contents.
@retval EFI_INVALID_PARAMETER Private is NULL or DatabaseRecord is NULL.
**/
EFI_STATUS
GenerateHiiDatabaseRecord (
IN HII_DATABASE_PRIVATE_DATA *Private,
OUT HII_DATABASE_RECORD **DatabaseNode
)
{
HII_DATABASE_RECORD *DatabaseRecord;
HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
HII_HANDLE *HiiHandle;
if ((Private == NULL) || (DatabaseNode == NULL)) {
return EFI_INVALID_PARAMETER;
}
DatabaseRecord = (HII_DATABASE_RECORD *)AllocateZeroPool (sizeof (HII_DATABASE_RECORD));
if (DatabaseRecord == NULL) {
return EFI_OUT_OF_RESOURCES;
}
DatabaseRecord->Signature = HII_DATABASE_RECORD_SIGNATURE;
DatabaseRecord->PackageList = AllocateZeroPool (sizeof (HII_DATABASE_PACKAGE_LIST_INSTANCE));
if (DatabaseRecord->PackageList == NULL) {
FreePool (DatabaseRecord);
return EFI_OUT_OF_RESOURCES;
}
PackageList = DatabaseRecord->PackageList;
InitializeListHead (&PackageList->GuidPkgHdr);
InitializeListHead (&PackageList->FormPkgHdr);
InitializeListHead (&PackageList->KeyboardLayoutHdr);
InitializeListHead (&PackageList->StringPkgHdr);
InitializeListHead (&PackageList->FontPkgHdr);
InitializeListHead (&PackageList->SimpleFontPkgHdr);
PackageList->ImagePkg = NULL;
PackageList->DevicePathPkg = NULL;
//
// Create a new hii handle
//
HiiHandle = (HII_HANDLE *)AllocateZeroPool (sizeof (HII_HANDLE));
if (HiiHandle == NULL) {
FreePool (DatabaseRecord->PackageList);
FreePool (DatabaseRecord);
return EFI_OUT_OF_RESOURCES;
}
HiiHandle->Signature = HII_HANDLE_SIGNATURE;
//
// Backup the number of Hii handles
//
Private->HiiHandleCount++;
HiiHandle->Key = (UINTN)Private->HiiHandleCount;
//
// Insert the handle to hii handle list of the whole database.
//
InsertTailList (&Private->HiiHandleList, &HiiHandle->Handle);
DatabaseRecord->Handle = (EFI_HII_HANDLE)HiiHandle;
//
// Insert the Package List node to Package List link of the whole database.
//
InsertTailList (&Private->DatabaseList, &DatabaseRecord->DatabaseEntry);
*DatabaseNode = DatabaseRecord;
return EFI_SUCCESS;
}
/**
This function checks whether a handle is a valid EFI_HII_HANDLE
This is a internal function.
@param Handle Pointer to a EFI_HII_HANDLE
@retval TRUE Valid
@retval FALSE Invalid
**/
BOOLEAN
IsHiiHandleValid (
EFI_HII_HANDLE Handle
)
{
HII_HANDLE *HiiHandle;
HiiHandle = (HII_HANDLE *)Handle;
if (HiiHandle == NULL) {
return FALSE;
}
if (HiiHandle->Signature != HII_HANDLE_SIGNATURE) {
return FALSE;
}
return TRUE;
}
/**
This function invokes the matching registered function.
This is a internal function.
@param Private HII Database driver private structure.
@param NotifyType The type of change concerning the database.
@param PackageInstance Points to the package referred to by the
notification.
@param PackageType Package type
@param Handle The handle of the package list which contains the
specified package.
@retval EFI_SUCCESS Already checked all registered function and
invoked if matched.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
InvokeRegisteredFunction (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN VOID *PackageInstance,
IN UINT8 PackageType,
IN EFI_HII_HANDLE Handle
)
{
HII_DATABASE_NOTIFY *Notify;
LIST_ENTRY *Link;
EFI_HII_PACKAGE_HEADER *Package;
UINT8 *Buffer;
UINT32 BufferSize;
UINT32 HeaderSize;
UINT32 ImageBlockSize;
UINT32 PaletteInfoSize;
if ((Private == NULL) || ((NotifyType & 0xF) == 0) || (PackageInstance == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
if (!IsHiiHandleValid (Handle)) {
return EFI_INVALID_PARAMETER;
}
Buffer = NULL;
Package = NULL;
//
// Convert the incoming package from hii database storage format to UEFI
// storage format. e.g. HII_GUID_PACKAGE_INSTANCE to EFI_HII_GUID_PACKAGE_HDR.
//
switch (PackageType) {
case EFI_HII_PACKAGE_TYPE_GUID:
Package = (EFI_HII_PACKAGE_HEADER *)(((HII_GUID_PACKAGE_INSTANCE *)PackageInstance)->GuidPkg);
break;
case EFI_HII_PACKAGE_FORMS:
BufferSize = ((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr.Length;
Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
ASSERT (Buffer != NULL);
CopyMem (
Buffer,
&((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->FormPkgHdr,
sizeof (EFI_HII_PACKAGE_HEADER)
);
CopyMem (
Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
((HII_IFR_PACKAGE_INSTANCE *)PackageInstance)->IfrData,
BufferSize - sizeof (EFI_HII_PACKAGE_HEADER)
);
Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
break;
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
Package = (EFI_HII_PACKAGE_HEADER *)(((HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *)PackageInstance)->KeyboardPkg);
break;
case EFI_HII_PACKAGE_STRINGS:
BufferSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->Header.Length;
HeaderSize = ((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr->HdrSize;
Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
ASSERT (Buffer != NULL);
CopyMem (
Buffer,
((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringPkgHdr,
HeaderSize
);
CopyMem (
Buffer + HeaderSize,
((HII_STRING_PACKAGE_INSTANCE *)PackageInstance)->StringBlock,
BufferSize - HeaderSize
);
Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
break;
case EFI_HII_PACKAGE_FONTS:
BufferSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->Header.Length;
HeaderSize = ((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr->HdrSize;
Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
ASSERT (Buffer != NULL);
CopyMem (
Buffer,
((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->FontPkgHdr,
HeaderSize
);
CopyMem (
Buffer + HeaderSize,
((HII_FONT_PACKAGE_INSTANCE *)PackageInstance)->GlyphBlock,
BufferSize - HeaderSize
);
Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
break;
case EFI_HII_PACKAGE_IMAGES:
BufferSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr.Header.Length;
HeaderSize = sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
ASSERT (Buffer != NULL);
CopyMem (
Buffer,
&((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImagePkgHdr,
HeaderSize
);
CopyMem (
Buffer + sizeof (EFI_HII_PACKAGE_HEADER),
&HeaderSize,
sizeof (UINT32)
);
ImageBlockSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlockSize;
if (ImageBlockSize != 0) {
CopyMem (
Buffer + HeaderSize,
((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->ImageBlock,
ImageBlockSize
);
}
PaletteInfoSize = ((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteInfoSize;
if (PaletteInfoSize != 0) {
CopyMem (
Buffer + HeaderSize + ImageBlockSize,
((HII_IMAGE_PACKAGE_INSTANCE *)PackageInstance)->PaletteBlock,
PaletteInfoSize
);
HeaderSize += ImageBlockSize;
CopyMem (
Buffer + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT32),
&HeaderSize,
sizeof (UINT32)
);
}
Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
break;
case EFI_HII_PACKAGE_SIMPLE_FONTS:
BufferSize = ((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr->Header.Length;
Buffer = (UINT8 *)AllocateZeroPool (BufferSize);
ASSERT (Buffer != NULL);
CopyMem (
Buffer,
((HII_SIMPLE_FONT_PACKAGE_INSTANCE *)PackageInstance)->SimpleFontPkgHdr,
BufferSize
);
Package = (EFI_HII_PACKAGE_HEADER *)Buffer;
break;
case EFI_HII_PACKAGE_DEVICE_PATH:
Package = (EFI_HII_PACKAGE_HEADER *)PackageInstance;
break;
default:
return EFI_INVALID_PARAMETER;
}
for (Link = Private->DatabaseNotifyList.ForwardLink;
Link != &Private->DatabaseNotifyList;
Link = Link->ForwardLink
)
{
Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
if ((Notify->NotifyType == NotifyType) && (Notify->PackageType == PackageType)) {
//
// Check in case PackageGuid is not NULL when Package is GUID package
//
if (PackageType != EFI_HII_PACKAGE_TYPE_GUID) {
Notify->PackageGuid = NULL;
}
//
// Status of Registered Function is unknown so did not check it
//
Notify->PackageNotifyFn (
Notify->PackageType,
Notify->PackageGuid,
Package,
Handle,
NotifyType
);
}
}
if (Buffer != NULL) {
FreePool (Buffer);
}
return EFI_SUCCESS;
}
/**
This function insert a GUID package to a package list node.
This is a internal function.
@param PackageHdr Pointer to a buffer stored with GUID package
information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created GUID package
@retval EFI_SUCCESS Guid Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Guid package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
**/
EFI_STATUS
InsertGuidPackage (
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_GUID_PACKAGE_INSTANCE **Package
)
{
HII_GUID_PACKAGE_INSTANCE *GuidPackage;
EFI_HII_PACKAGE_HEADER PackageHeader;
if ((PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
//
// Create a GUID package node
//
GuidPackage = (HII_GUID_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_GUID_PACKAGE_INSTANCE));
if (GuidPackage == NULL) {
return EFI_OUT_OF_RESOURCES;
}
GuidPackage->GuidPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);
if (GuidPackage->GuidPkg == NULL) {
FreePool (GuidPackage);
return EFI_OUT_OF_RESOURCES;
}
GuidPackage->Signature = HII_GUID_PACKAGE_SIGNATURE;
CopyMem (GuidPackage->GuidPkg, PackageHdr, PackageHeader.Length);
InsertTailList (&PackageList->GuidPkgHdr, &GuidPackage->GuidEntry);
*Package = GuidPackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
}
return EFI_SUCCESS;
}
/**
This function exports GUID packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS Guid Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportGuidPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
HII_GUID_PACKAGE_INSTANCE *GuidPackage;
LIST_ENTRY *Link;
UINTN PackageLength;
EFI_HII_PACKAGE_HEADER PackageHeader;
EFI_STATUS Status;
if ((PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
PackageLength = 0;
Status = EFI_SUCCESS;
for (Link = PackageList->GuidPkgHdr.ForwardLink; Link != &PackageList->GuidPkgHdr; Link = Link->ForwardLink) {
GuidPackage = CR (Link, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
CopyMem (&PackageHeader, GuidPackage->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
PackageLength += PackageHeader.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)GuidPackage,
EFI_HII_PACKAGE_TYPE_GUID,
Handle
);
ASSERT_EFI_ERROR (Status);
CopyMem (Buffer, GuidPackage->GuidPkg, PackageHeader.Length);
Buffer = (UINT8 *)Buffer + PackageHeader.Length;
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes all GUID packages from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed GUID packages.
@param PackageList Pointer to a package list that contains removing
packages.
@retval EFI_SUCCESS GUID Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveGuidPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *ListHead;
HII_GUID_PACKAGE_INSTANCE *Package;
EFI_STATUS Status;
EFI_HII_PACKAGE_HEADER PackageHeader;
ListHead = &PackageList->GuidPkgHdr;
while (!IsListEmpty (ListHead)) {
Package = CR (
ListHead->ForwardLink,
HII_GUID_PACKAGE_INSTANCE,
GuidEntry,
HII_GUID_PACKAGE_SIGNATURE
);
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_TYPE_GUID,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
RemoveEntryList (&Package->GuidEntry);
CopyMem (&PackageHeader, Package->GuidPkg, sizeof (EFI_HII_PACKAGE_HEADER));
PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
FreePool (Package->GuidPkg);
FreePool (Package);
}
return EFI_SUCCESS;
}
/**
Check the input question related to EFI variable
@param IfrQuestionHdr Point to Question header
@param EfiVarStoreList Point to EFI VarStore List
@param EfiVarStoreNumber The number of EFI VarStore
@retval Index The index of the found EFI varstore in EFI varstore list
EfiVarStoreNumber will return if no EFI varstore is found.
**/
UINTN
IsEfiVarStoreQuestion (
EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
EFI_IFR_VARSTORE_EFI **EfiVarStoreList,
UINTN EfiVarStoreNumber
)
{
UINTN Index;
for (Index = 0; Index < EfiVarStoreNumber; Index++) {
if (IfrQuestionHdr->VarStoreId == EfiVarStoreList[Index]->VarStoreId) {
return Index;
}
}
return EfiVarStoreNumber;
}
/**
Find the matched variable from the input variable storage.
@param[in] VariableStorage Point to the variable storage header.
@param[in] VarGuid A unique identifier for the variable.
@param[in] VarAttribute The attributes bitmask for the variable.
@param[in] VarName A Null-terminated ascii string that is the name of the variable.
@return Pointer to the matched variable header or NULL if not found.
**/
VARIABLE_HEADER *
FindVariableData (
IN VARIABLE_STORE_HEADER *VariableStorage,
IN EFI_GUID *VarGuid,
IN UINT32 VarAttribute,
IN CHAR16 *VarName
)
{
VARIABLE_HEADER *VariableHeader;
VARIABLE_HEADER *VariableEnd;
VariableEnd = (VARIABLE_HEADER *)((UINT8 *)VariableStorage + VariableStorage->Size);
VariableHeader = (VARIABLE_HEADER *)(VariableStorage + 1);
VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
while (VariableHeader < VariableEnd) {
if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&
(VariableHeader->Attributes == VarAttribute) &&
(StrCmp (VarName, (CHAR16 *)(VariableHeader + 1)) == 0))
{
return VariableHeader;
}
VariableHeader = (VARIABLE_HEADER *)((UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);
VariableHeader = (VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
}
return NULL;
}
/**
Find question default value from PcdNvStoreDefaultValueBuffer
@param DefaultId Default store ID
@param EfiVarStore Point to EFI VarStore header
@param IfrQuestionHdr Point to Question header
@param ValueBuffer Point to Buffer includes the found default setting
@param Width Width of the default value
@param BitFieldQuestion Whether the Question is stored in Bit field.
@retval EFI_SUCCESS Question default value is found.
@retval EFI_NOT_FOUND Question default value is not found.
**/
EFI_STATUS
FindQuestionDefaultSetting (
IN UINT16 DefaultId,
IN EFI_IFR_VARSTORE_EFI *EfiVarStore,
IN EFI_IFR_QUESTION_HEADER *IfrQuestionHdr,
OUT VOID *ValueBuffer,
IN UINTN Width,
IN BOOLEAN BitFieldQuestion
)
{
VARIABLE_HEADER *VariableHeader;
VARIABLE_STORE_HEADER *VariableStorage;
LIST_ENTRY *Link;
VARSTORAGE_DEFAULT_DATA *Entry;
VARIABLE_STORE_HEADER *NvStoreBuffer;
UINT8 *DataBuffer;
UINT8 *BufferEnd;
BOOLEAN IsFound;
UINTN Index;
UINT32 BufferValue;
UINT32 BitFieldVal;
UINTN BitOffset;
UINTN ByteOffset;
UINTN BitWidth;
UINTN StartBit;
UINTN EndBit;
PCD_DEFAULT_DATA *DataHeader;
PCD_DEFAULT_INFO *DefaultInfo;
PCD_DATA_DELTA *DeltaData;
if (gSkuId == 0xFFFFFFFFFFFFFFFF) {
gSkuId = LibPcdGetSku ();
}
//
// Find the DefaultId setting from the full DefaultSetting
//
VariableStorage = NULL;
Link = gVarStorageList.ForwardLink;
while (Link != &gVarStorageList) {
Entry = BASE_CR (Link, VARSTORAGE_DEFAULT_DATA, Entry);
if (Entry->DefaultId == DefaultId) {
VariableStorage = Entry->VariableStorage;
break;
}
Link = Link->ForwardLink;
}
if (Link == &gVarStorageList) {
DataBuffer = (UINT8 *)PcdGetPtr (PcdNvStoreDefaultValueBuffer);
gNvDefaultStoreSize = ((PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)DataBuffer)->Length;
//
// The first section data includes NV storage default setting.
//
DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER));
NvStoreBuffer = (VARIABLE_STORE_HEADER *)((UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize);
VariableStorage = AllocatePool (NvStoreBuffer->Size);
ASSERT (VariableStorage != NULL);
CopyMem (VariableStorage, NvStoreBuffer, NvStoreBuffer->Size);
//
// Find the matched SkuId and DefaultId in the first section
//
IsFound = FALSE;
DefaultInfo = &(DataHeader->DefaultInfo[0]);
BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
while ((UINT8 *)DefaultInfo < BufferEnd) {
if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {
IsFound = TRUE;
break;
}
DefaultInfo++;
}
//
// Find the matched SkuId and DefaultId in the remaining section
//
Index = sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER) + ((DataHeader->DataSize + 7) & (~7));
DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
while (!IsFound && Index < gNvDefaultStoreSize && DataHeader->DataSize != 0xFFFF) {
DefaultInfo = &(DataHeader->DefaultInfo[0]);
BufferEnd = (UINT8 *)DataHeader + sizeof (DataHeader->DataSize) + DataHeader->HeaderSize;
while ((UINT8 *)DefaultInfo < BufferEnd) {
if ((DefaultInfo->DefaultId == DefaultId) && (DefaultInfo->SkuId == gSkuId)) {
IsFound = TRUE;
break;
}
DefaultInfo++;
}
if (IsFound) {
DeltaData = (PCD_DATA_DELTA *)BufferEnd;
BufferEnd = (UINT8 *)DataHeader + DataHeader->DataSize;
while ((UINT8 *)DeltaData < BufferEnd) {
*((UINT8 *)VariableStorage + DeltaData->Offset) = (UINT8)DeltaData->Value;
DeltaData++;
}
break;
}
Index = (Index + DataHeader->DataSize + 7) & (~7);
DataHeader = (PCD_DEFAULT_DATA *)(DataBuffer + Index);
}
//
// Cache the found result in VarStorageList
//
if (!IsFound) {
FreePool (VariableStorage);
VariableStorage = NULL;
}
Entry = AllocatePool (sizeof (VARSTORAGE_DEFAULT_DATA));
if (Entry != NULL) {
Entry->DefaultId = DefaultId;
Entry->VariableStorage = VariableStorage;
InsertTailList (&gVarStorageList, &Entry->Entry);
} else if (VariableStorage != NULL) {
FreePool (VariableStorage);
VariableStorage = NULL;
}
}
//
// The matched variable storage is not found.
//
if (VariableStorage == NULL) {
return EFI_NOT_FOUND;
}
//
// Find the question default value from the variable storage
//
VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);
if (VariableHeader == NULL) {
return EFI_NOT_FOUND;
}
StartBit = 0;
EndBit = 0;
ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
if (BitFieldQuestion) {
BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
ByteOffset = BitOffset / 8;
BitWidth = Width;
StartBit = BitOffset % 8;
EndBit = StartBit + BitWidth - 1;
Width = EndBit / 8 + 1;
}
if (VariableHeader->DataSize < ByteOffset + Width) {
return EFI_INVALID_PARAMETER;
}
//
// Copy the question value
//
if (ValueBuffer != NULL) {
if (BitFieldQuestion) {
CopyMem (&BufferValue, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
CopyMem (ValueBuffer, &BitFieldVal, Width);
} else {
CopyMem (ValueBuffer, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
}
}
return EFI_SUCCESS;
}
/**
Update IFR default setting in Form Package.
@param FormPackage Form Package to be updated
**/
VOID
UpdateDefaultSettingInFormPackage (
HII_IFR_PACKAGE_INSTANCE *FormPackage
)
{
UINTN IfrOffset;
UINTN PackageLength;
EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
EFI_IFR_OP_HEADER *IfrOpHdr;
EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
UINT8 IfrQuestionType;
UINT8 IfrScope;
EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
EFI_IFR_VARSTORE_EFI **EfiVarStoreList;
UINTN EfiVarStoreMaxNum;
UINTN EfiVarStoreNumber;
UINT16 *DefaultIdList;
UINTN DefaultIdNumber;
UINTN DefaultIdMaxNum;
UINTN Index;
UINTN EfiVarStoreIndex;
EFI_IFR_TYPE_VALUE IfrValue;
EFI_IFR_TYPE_VALUE IfrManufactValue;
BOOLEAN StandardDefaultIsSet;
BOOLEAN ManufactDefaultIsSet;
EFI_IFR_CHECKBOX *IfrCheckBox;
EFI_STATUS Status;
EFI_IFR_DEFAULT *IfrDefault;
UINTN Width;
EFI_IFR_QUESTION_HEADER VarStoreQuestionHeader;
BOOLEAN QuestionReferBitField;
//
// If no default setting, do nothing
//
if (gNvDefaultStoreSize == 0) {
gNvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
}
if (gNvDefaultStoreSize < sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
return;
}
ZeroMem (&VarStoreQuestionHeader, sizeof (VarStoreQuestionHeader));
PackageLength = FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
Width = 0;
IfrOffset = 0;
IfrScope = 0;
IfrOpHdr = (EFI_IFR_OP_HEADER *)FormPackage->IfrData;
IfrQuestionHdr = NULL;
IfrQuestionType = 0;
EfiVarStoreMaxNum = 0;
EfiVarStoreNumber = 0;
DefaultIdMaxNum = 0;
DefaultIdNumber = 0;
EfiVarStoreList = NULL;
DefaultIdList = NULL;
StandardDefaultIsSet = FALSE;
ManufactDefaultIsSet = FALSE;
QuestionReferBitField = FALSE;
while (IfrOffset < PackageLength) {
switch (IfrOpHdr->OpCode) {
case EFI_IFR_VARSTORE_EFI_OP:
if (EfiVarStoreNumber >= EfiVarStoreMaxNum) {
//
// Reallocate EFI VarStore Buffer
//
EfiVarStoreList = ReallocatePool (EfiVarStoreMaxNum * sizeof (UINTN), (EfiVarStoreMaxNum + BASE_NUMBER) * sizeof (UINTN), EfiVarStoreList);
if (EfiVarStoreList == NULL) {
goto Done;
}
EfiVarStoreMaxNum = EfiVarStoreMaxNum + BASE_NUMBER;
}
IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *)IfrOpHdr;
//
// Convert VarStore Name from ASCII string to Unicode string.
//
EfiVarStoreList[EfiVarStoreNumber] = AllocatePool (IfrEfiVarStore->Header.Length + AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name));
if (EfiVarStoreList[EfiVarStoreNumber] == NULL) {
break;
}
CopyMem (EfiVarStoreList[EfiVarStoreNumber], IfrEfiVarStore, IfrEfiVarStore->Header.Length);
AsciiStrToUnicodeStrS ((CHAR8 *)IfrEfiVarStore->Name, (CHAR16 *)&(EfiVarStoreList[EfiVarStoreNumber]->Name[0]), AsciiStrSize ((CHAR8 *)IfrEfiVarStore->Name) * sizeof (CHAR16));
Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreNumber], &VarStoreQuestionHeader, NULL, IfrEfiVarStore->Size, FALSE);
if (!EFI_ERROR (Status)) {
EfiVarStoreNumber++;
} else {
FreePool (EfiVarStoreList[EfiVarStoreNumber]);
EfiVarStoreList[EfiVarStoreNumber] = NULL;
}
break;
case EFI_IFR_DEFAULTSTORE_OP:
if (DefaultIdNumber >= DefaultIdMaxNum) {
//
// Reallocate DefaultIdNumber
//
DefaultIdList = ReallocatePool (DefaultIdMaxNum * sizeof (UINT16), (DefaultIdMaxNum + BASE_NUMBER) * sizeof (UINT16), DefaultIdList);
if (DefaultIdList == NULL) {
goto Done;
}
DefaultIdMaxNum = DefaultIdMaxNum + BASE_NUMBER;
}
DefaultIdList[DefaultIdNumber++] = ((EFI_IFR_DEFAULTSTORE *)IfrOpHdr)->DefaultId;
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
//
// No EFI varstore is found and directly return.
//
if ((EfiVarStoreNumber == 0) || (DefaultIdNumber == 0)) {
goto Done;
}
break;
case EFI_IFR_CHECKBOX_OP:
IfrScope = IfrOpHdr->Scope;
IfrQuestionType = IfrOpHdr->OpCode;
IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
IfrCheckBox = (EFI_IFR_CHECKBOX *)IfrOpHdr;
EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
Width = sizeof (BOOLEAN);
if (EfiVarStoreIndex < EfiVarStoreNumber) {
for (Index = 0; Index < DefaultIdNumber; Index++) {
if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
if (!EFI_ERROR (Status)) {
if (IfrValue.b) {
IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT;
} else {
IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT);
}
}
} else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
Status = FindQuestionDefaultSetting (DefaultIdList[Index], EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, sizeof (BOOLEAN), QuestionReferBitField);
if (!EFI_ERROR (Status)) {
if (IfrValue.b) {
IfrCheckBox->Flags = IfrCheckBox->Flags | EFI_IFR_CHECKBOX_DEFAULT_MFG;
} else {
IfrCheckBox->Flags = IfrCheckBox->Flags & (~EFI_IFR_CHECKBOX_DEFAULT_MFG);
}
}
}
}
}
break;
case EFI_IFR_NUMERIC_OP:
IfrScope = IfrOpHdr->Scope;
IfrQuestionType = IfrOpHdr->OpCode;
IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
if (QuestionReferBitField) {
Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
} else {
Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
}
break;
case EFI_IFR_ONE_OF_OP:
IfrScope = IfrOpHdr->Scope;
IfrQuestionType = IfrOpHdr->OpCode;
IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
if (QuestionReferBitField) {
Width = (UINTN)(((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EDKII_IFR_NUMERIC_SIZE_BIT);
} else {
Width = (UINTN)((UINT32)1 << (((EFI_IFR_ONE_OF *)IfrOpHdr)->Flags & EFI_IFR_NUMERIC_SIZE));
}
EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
StandardDefaultIsSet = FALSE;
ManufactDefaultIsSet = FALSE;
//
// Find Default and Manufacturing default for OneOf question
//
if (EfiVarStoreIndex < EfiVarStoreNumber) {
for (Index = 0; Index < DefaultIdNumber; Index++) {
if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_STANDARD) {
Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_STANDARD, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrValue, Width, QuestionReferBitField);
if (!EFI_ERROR (Status)) {
StandardDefaultIsSet = TRUE;
}
} else if (DefaultIdList[Index] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
Status = FindQuestionDefaultSetting (EFI_HII_DEFAULT_CLASS_MANUFACTURING, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrManufactValue, Width, QuestionReferBitField);
if (!EFI_ERROR (Status)) {
ManufactDefaultIsSet = TRUE;
}
}
}
}
break;
case EFI_IFR_ORDERED_LIST_OP:
IfrScope = IfrOpHdr->Scope;
IfrQuestionType = IfrOpHdr->OpCode;
IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)(IfrOpHdr + 1);
break;
case EFI_IFR_ONE_OF_OPTION_OP:
if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {
IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *)IfrOpHdr;
if (IfrQuestionType == EFI_IFR_ONE_OF_OP) {
Width = (UINTN)((UINT32)1 << (IfrOneOfOption->Flags & EFI_IFR_NUMERIC_SIZE));
if (StandardDefaultIsSet) {
if (CompareMem (&IfrOneOfOption->Value, &IfrValue, Width) == 0) {
IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT;
} else {
IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT;
}
}
if (ManufactDefaultIsSet) {
if (CompareMem (&IfrOneOfOption->Value, &IfrManufactValue, Width) == 0) {
IfrOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG;
} else {
IfrOneOfOption->Flags &= ~EFI_IFR_OPTION_DEFAULT_MFG;
}
}
}
}
break;
case EFI_IFR_DEFAULT_OP:
if ((IfrQuestionHdr != NULL) && (IfrScope > 0)) {
IfrDefault = (EFI_IFR_DEFAULT *)IfrOpHdr;
//
// Collect default value width
//
if (!QuestionReferBitField) {
Width = 0;
if ((IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_8) || (IfrDefault->Type == EFI_IFR_TYPE_BOOLEAN)) {
Width = 1;
} else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_16) {
Width = 2;
} else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_32) {
Width = 4;
} else if (IfrDefault->Type == EFI_IFR_TYPE_NUM_SIZE_64) {
Width = 8;
} else if (IfrDefault->Type == EFI_IFR_TYPE_BUFFER) {
Width = IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value);
}
}
//
// Update the default value
//
if (Width > 0) {
EfiVarStoreIndex = IsEfiVarStoreQuestion (IfrQuestionHdr, EfiVarStoreList, EfiVarStoreNumber);
if (EfiVarStoreIndex < EfiVarStoreNumber) {
Status = FindQuestionDefaultSetting (IfrDefault->DefaultId, EfiVarStoreList[EfiVarStoreIndex], IfrQuestionHdr, &IfrDefault->Value, Width, QuestionReferBitField);
}
}
}
break;
case EFI_IFR_END_OP:
if (IfrQuestionHdr != NULL) {
if (IfrScope > 0) {
IfrScope--;
}
if (IfrScope == 0) {
IfrQuestionHdr = NULL;
QuestionReferBitField = FALSE;
}
}
break;
case EFI_IFR_GUID_OP:
if (CompareGuid ((EFI_GUID *)((UINT8 *)IfrOpHdr + sizeof (EFI_IFR_OP_HEADER)), &gEdkiiIfrBitVarstoreGuid)) {
QuestionReferBitField = TRUE;
}
break;
default:
break;
}
IfrOffset = IfrOffset + IfrOpHdr->Length;
IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *)IfrOpHdr + IfrOpHdr->Length);
if (IfrScope > 0) {
IfrScope += IfrOpHdr->Scope;
}
}
Done:
if (EfiVarStoreList != NULL) {
for (Index = 0; Index < EfiVarStoreNumber; Index++) {
FreePool (EfiVarStoreList[Index]);
}
}
return;
}
/**
This function insert a Form package to a package list node.
This is a internal function.
@param PackageHdr Pointer to a buffer stored with Form package
information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created Form package
@retval EFI_SUCCESS Form Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Form package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
**/
EFI_STATUS
InsertFormPackage (
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_IFR_PACKAGE_INSTANCE **Package
)
{
HII_IFR_PACKAGE_INSTANCE *FormPackage;
EFI_HII_PACKAGE_HEADER PackageHeader;
if ((PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Get the length of the package, including package header itself
//
CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
//
// Create a Form package node
//
FormPackage = (HII_IFR_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IFR_PACKAGE_INSTANCE));
if (FormPackage == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FormPackage->IfrData = (UINT8 *)AllocateZeroPool (PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER));
if (FormPackage->IfrData == NULL) {
FreePool (FormPackage);
return EFI_OUT_OF_RESOURCES;
}
FormPackage->Signature = HII_IFR_PACKAGE_SIGNATURE;
//
// Copy Package Header
//
CopyMem (&FormPackage->FormPkgHdr, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
//
// Copy Ifr contents
//
CopyMem (
FormPackage->IfrData,
(UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER),
PackageHeader.Length - sizeof (EFI_HII_PACKAGE_HEADER)
);
InsertTailList (&PackageList->FormPkgHdr, &FormPackage->IfrEntry);
*Package = FormPackage;
//
// Update FormPackage with the default setting
//
UpdateDefaultSettingInFormPackage (FormPackage);
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += FormPackage->FormPkgHdr.Length;
}
return EFI_SUCCESS;
}
/**
This function exports Form packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS Form Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportFormPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
HII_IFR_PACKAGE_INSTANCE *FormPackage;
UINTN PackageLength;
LIST_ENTRY *Link;
EFI_STATUS Status;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
PackageLength = 0;
Status = EFI_SUCCESS;
//
// Export Form packages.
//
for (Link = PackageList->FormPkgHdr.ForwardLink; Link != &PackageList->FormPkgHdr; Link = Link->ForwardLink) {
FormPackage = CR (Link, HII_IFR_PACKAGE_INSTANCE, IfrEntry, HII_IFR_PACKAGE_SIGNATURE);
PackageLength += FormPackage->FormPkgHdr.Length;
if ((Buffer != NULL) && (PackageLength + *ResultSize + UsedSize <= BufferSize)) {
//
// Invoke registered notification if exists
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)FormPackage,
EFI_HII_PACKAGE_FORMS,
Handle
);
ASSERT_EFI_ERROR (Status);
//
// Copy the Form package content.
//
CopyMem (Buffer, (VOID *)(&FormPackage->FormPkgHdr), sizeof (EFI_HII_PACKAGE_HEADER));
Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_PACKAGE_HEADER);
CopyMem (
Buffer,
(VOID *)FormPackage->IfrData,
FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER)
);
Buffer = (UINT8 *)Buffer + FormPackage->FormPkgHdr.Length - sizeof (EFI_HII_PACKAGE_HEADER);
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes all Form packages from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed Form packages.
@param PackageList Pointer to a package list that contains removing
packages.
@retval EFI_SUCCESS Form Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveFormPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *ListHead;
HII_IFR_PACKAGE_INSTANCE *Package;
EFI_STATUS Status;
ListHead = &PackageList->FormPkgHdr;
while (!IsListEmpty (ListHead)) {
Package = CR (
ListHead->ForwardLink,
HII_IFR_PACKAGE_INSTANCE,
IfrEntry,
HII_IFR_PACKAGE_SIGNATURE
);
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_FORMS,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
RemoveEntryList (&Package->IfrEntry);
PackageList->PackageListHdr.PackageLength -= Package->FormPkgHdr.Length;
FreePool (Package->IfrData);
FreePool (Package);
//
// If Hii runtime support feature is enabled,
// will export Hii info for runtime use after ReadyToBoot event triggered.
// If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
// will need to export the content of HiiDatabase.
// But if form packages removed, also need to export the ConfigResp string
//
if (gExportAfterReadyToBoot) {
gExportConfigResp = TRUE;
}
}
return EFI_SUCCESS;
}
/**
This function insert a String package to a package list node.
This is a internal function.
@param Private Hii database private structure.
@param PackageHdr Pointer to a buffer stored with String package
information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created String package
@retval EFI_SUCCESS String Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
String package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
@retval EFI_UNSUPPORTED A string package with the same language already
exists in current package list.
**/
EFI_STATUS
InsertStringPackage (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_STRING_PACKAGE_INSTANCE **Package
)
{
HII_STRING_PACKAGE_INSTANCE *StringPackage;
UINT32 HeaderSize;
EFI_STATUS Status;
EFI_HII_PACKAGE_HEADER PackageHeader;
CHAR8 *Language;
UINT32 LanguageSize;
LIST_ENTRY *Link;
if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Private->Signature != HII_DATABASE_PRIVATE_DATA_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
//
// It is illegal to have two string packages with same language within one packagelist
// since the stringid will be duplicate if so. Check it to avoid this potential issue.
//
LanguageSize = HeaderSize - sizeof (EFI_HII_STRING_PACKAGE_HDR) + sizeof (CHAR8);
Language = (CHAR8 *)AllocateZeroPool (LanguageSize);
if (Language == NULL) {
return EFI_OUT_OF_RESOURCES;
}
AsciiStrCpyS (Language, LanguageSize / sizeof (CHAR8), (CHAR8 *)PackageHdr + HeaderSize - LanguageSize);
for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
if (HiiCompareLanguage (Language, StringPackage->StringPkgHdr->Language)) {
FreePool (Language);
return EFI_UNSUPPORTED;
}
}
FreePool (Language);
//
// Create a String package node
//
StringPackage = (HII_STRING_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
if (StringPackage == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
StringPackage->StringPkgHdr = (EFI_HII_STRING_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);
if (StringPackage->StringPkgHdr == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
StringPackage->StringBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);
if (StringPackage->StringBlock == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
StringPackage->FontId = 0;
InitializeListHead (&StringPackage->FontInfoList);
//
// Copy the String package header.
//
CopyMem (StringPackage->StringPkgHdr, PackageHdr, HeaderSize);
//
// Copy the String blocks
//
CopyMem (
StringPackage->StringBlock,
(UINT8 *)PackageHdr + HeaderSize,
PackageHeader.Length - HeaderSize
);
//
// Collect all font block info
//
Status = FindStringBlock (Private, StringPackage, (EFI_STRING_ID)(-1), NULL, NULL, NULL, &StringPackage->MaxStringId, NULL);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Insert to String package array
//
InsertTailList (&PackageList->StringPkgHdr, &StringPackage->StringEntry);
*Package = StringPackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
}
return EFI_SUCCESS;
Error:
if (StringPackage != NULL) {
if (StringPackage->StringBlock != NULL) {
FreePool (StringPackage->StringBlock);
}
if (StringPackage->StringPkgHdr != NULL) {
FreePool (StringPackage->StringPkgHdr);
}
FreePool (StringPackage);
}
return Status;
}
/**
Adjust all string packages in a single package list to have the same max string ID.
@param PackageList Pointer to a package list which will be adjusted.
@retval EFI_SUCCESS Adjust all string packages successfully.
@retval others Can't adjust string packages.
**/
EFI_STATUS
AdjustStringPackage (
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *Link;
HII_STRING_PACKAGE_INSTANCE *StringPackage;
UINT32 Skip2BlockSize;
UINT32 OldBlockSize;
UINT8 *StringBlock;
UINT8 *BlockPtr;
EFI_STRING_ID MaxStringId;
UINT16 SkipCount;
MaxStringId = 0;
for (Link = PackageList->StringPkgHdr.ForwardLink;
Link != &PackageList->StringPkgHdr;
Link = Link->ForwardLink
)
{
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
if (MaxStringId < StringPackage->MaxStringId) {
MaxStringId = StringPackage->MaxStringId;
}
}
for (Link = PackageList->StringPkgHdr.ForwardLink;
Link != &PackageList->StringPkgHdr;
Link = Link->ForwardLink
)
{
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
if (StringPackage->MaxStringId < MaxStringId) {
OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
//
// Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCKs to reserve the missing string IDs.
//
SkipCount = (UINT16)(MaxStringId - StringPackage->MaxStringId);
Skip2BlockSize = (UINT32)sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
StringBlock = (UINT8 *)AllocateZeroPool (OldBlockSize + Skip2BlockSize);
if (StringBlock == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Copy original string blocks, except the EFI_HII_SIBT_END.
//
CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
//
// Create SKIP2 EFI_HII_SIBT_SKIP2_BLOCK blocks
//
BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
*BlockPtr = EFI_HII_SIBT_SKIP2;
CopyMem (BlockPtr + 1, &SkipCount, sizeof (UINT16));
BlockPtr += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
//
// Append a EFI_HII_SIBT_END block to the end.
//
*BlockPtr = EFI_HII_SIBT_END;
FreePool (StringPackage->StringBlock);
StringPackage->StringBlock = StringBlock;
StringPackage->StringPkgHdr->Header.Length += Skip2BlockSize;
PackageList->PackageListHdr.PackageLength += Skip2BlockSize;
StringPackage->MaxStringId = MaxStringId;
}
}
return EFI_SUCCESS;
}
/**
This function exports String packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS String Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportStringPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
LIST_ENTRY *Link;
UINTN PackageLength;
EFI_STATUS Status;
HII_STRING_PACKAGE_INSTANCE *StringPackage;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
PackageLength = 0;
Status = EFI_SUCCESS;
for (Link = PackageList->StringPkgHdr.ForwardLink; Link != &PackageList->StringPkgHdr; Link = Link->ForwardLink) {
StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
PackageLength += StringPackage->StringPkgHdr->Header.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
//
// Invoke registered notification function with EXPORT_PACK notify type
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)StringPackage,
EFI_HII_PACKAGE_STRINGS,
Handle
);
ASSERT_EFI_ERROR (Status);
//
// Copy String package header
//
CopyMem (Buffer, StringPackage->StringPkgHdr, StringPackage->StringPkgHdr->HdrSize);
Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->HdrSize;
//
// Copy String blocks information
//
CopyMem (
Buffer,
StringPackage->StringBlock,
StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize
);
Buffer = (UINT8 *)Buffer + StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes all String packages from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed String packages.
@param PackageList Pointer to a package list that contains removing
packages.
@retval EFI_SUCCESS String Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveStringPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *ListHead;
HII_STRING_PACKAGE_INSTANCE *Package;
HII_FONT_INFO *FontInfo;
EFI_STATUS Status;
ListHead = &PackageList->StringPkgHdr;
while (!IsListEmpty (ListHead)) {
Package = CR (
ListHead->ForwardLink,
HII_STRING_PACKAGE_INSTANCE,
StringEntry,
HII_STRING_PACKAGE_SIGNATURE
);
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_STRINGS,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
RemoveEntryList (&Package->StringEntry);
PackageList->PackageListHdr.PackageLength -= Package->StringPkgHdr->Header.Length;
FreePool (Package->StringBlock);
FreePool (Package->StringPkgHdr);
//
// Delete font information
//
while (!IsListEmpty (&Package->FontInfoList)) {
FontInfo = CR (
Package->FontInfoList.ForwardLink,
HII_FONT_INFO,
Entry,
HII_FONT_INFO_SIGNATURE
);
RemoveEntryList (&FontInfo->Entry);
FreePool (FontInfo);
}
FreePool (Package);
}
return EFI_SUCCESS;
}
/**
This function insert a Font package to a package list node.
This is a internal function.
@param Private Hii database private structure.
@param PackageHdr Pointer to a buffer stored with Font package
information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created Font package
@retval EFI_SUCCESS Font Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Font package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
@retval EFI_UNSUPPORTED A font package with same EFI_FONT_INFO already
exists in current hii database.
**/
EFI_STATUS
InsertFontPackage (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_FONT_PACKAGE_INSTANCE **Package
)
{
HII_FONT_PACKAGE_INSTANCE *FontPackage;
EFI_HII_FONT_PACKAGE_HDR *FontPkgHdr;
UINT32 HeaderSize;
EFI_STATUS Status;
EFI_HII_PACKAGE_HEADER PackageHeader;
EFI_FONT_INFO *FontInfo;
UINT32 FontInfoSize;
HII_GLOBAL_FONT_INFO *GlobalFont;
if ((Private == NULL) || (PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
CopyMem (&HeaderSize, (UINT8 *)PackageHdr + sizeof (EFI_HII_PACKAGE_HEADER), sizeof (UINT32));
FontInfo = NULL;
FontPackage = NULL;
GlobalFont = NULL;
//
// It is illegal to have two font packages with same EFI_FONT_INFO within hii
// database. EFI_FONT_INFO (FontName, FontSize, FontStyle) describes font's
// attributes and identify a font uniquely.
//
FontPkgHdr = (EFI_HII_FONT_PACKAGE_HDR *)AllocateZeroPool (HeaderSize);
if (FontPkgHdr == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
CopyMem (FontPkgHdr, PackageHdr, HeaderSize);
FontInfoSize = sizeof (EFI_FONT_INFO) + HeaderSize - sizeof (EFI_HII_FONT_PACKAGE_HDR);
FontInfo = (EFI_FONT_INFO *)AllocateZeroPool (FontInfoSize);
if (FontInfo == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
FontInfo->FontStyle = FontPkgHdr->FontStyle;
FontInfo->FontSize = FontPkgHdr->Cell.Height;
StrCpyS (FontInfo->FontName, (FontInfoSize - OFFSET_OF (EFI_FONT_INFO, FontName)) / sizeof (CHAR16), FontPkgHdr->FontFamily);
if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, NULL)) {
Status = EFI_UNSUPPORTED;
goto Error;
}
//
// Create a Font package node
//
FontPackage = (HII_FONT_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_FONT_PACKAGE_INSTANCE));
if (FontPackage == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
FontPackage->Signature = HII_FONT_PACKAGE_SIGNATURE;
FontPackage->FontPkgHdr = FontPkgHdr;
InitializeListHead (&FontPackage->GlyphInfoList);
FontPackage->GlyphBlock = (UINT8 *)AllocateZeroPool (PackageHeader.Length - HeaderSize);
if (FontPackage->GlyphBlock == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
CopyMem (FontPackage->GlyphBlock, (UINT8 *)PackageHdr + HeaderSize, PackageHeader.Length - HeaderSize);
//
// Collect all default character cell information and backup in GlyphInfoList.
//
Status = FindGlyphBlock (FontPackage, (CHAR16)(-1), NULL, NULL, NULL);
if (EFI_ERROR (Status)) {
goto Error;
}
//
// This font package describes an unique EFI_FONT_INFO. Backup it in global
// font info list.
//
GlobalFont = (HII_GLOBAL_FONT_INFO *)AllocateZeroPool (sizeof (HII_GLOBAL_FONT_INFO));
if (GlobalFont == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
GlobalFont->Signature = HII_GLOBAL_FONT_INFO_SIGNATURE;
GlobalFont->FontPackage = FontPackage;
GlobalFont->FontInfoSize = FontInfoSize;
GlobalFont->FontInfo = FontInfo;
InsertTailList (&Private->FontInfoList, &GlobalFont->Entry);
//
// Insert this font package to Font package array
//
InsertTailList (&PackageList->FontPkgHdr, &FontPackage->FontEntry);
*Package = FontPackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += FontPackage->FontPkgHdr->Header.Length;
}
return EFI_SUCCESS;
Error:
if (FontPkgHdr != NULL) {
FreePool (FontPkgHdr);
}
if (FontInfo != NULL) {
FreePool (FontInfo);
}
if (FontPackage != NULL) {
if (FontPackage->GlyphBlock != NULL) {
FreePool (FontPackage->GlyphBlock);
}
FreePool (FontPackage);
}
if (GlobalFont != NULL) {
FreePool (GlobalFont);
}
return Status;
}
/**
This function exports Font packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS Font Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportFontPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
LIST_ENTRY *Link;
UINTN PackageLength;
EFI_STATUS Status;
HII_FONT_PACKAGE_INSTANCE *Package;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
PackageLength = 0;
Status = EFI_SUCCESS;
for (Link = PackageList->FontPkgHdr.ForwardLink; Link != &PackageList->FontPkgHdr; Link = Link->ForwardLink) {
Package = CR (Link, HII_FONT_PACKAGE_INSTANCE, FontEntry, HII_FONT_PACKAGE_SIGNATURE);
PackageLength += Package->FontPkgHdr->Header.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
//
// Invoke registered notification function with EXPORT_PACK notify type
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_FONTS,
Handle
);
ASSERT_EFI_ERROR (Status);
//
// Copy Font package header
//
CopyMem (Buffer, Package->FontPkgHdr, Package->FontPkgHdr->HdrSize);
Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->HdrSize;
//
// Copy Glyph blocks information
//
CopyMem (
Buffer,
Package->GlyphBlock,
Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize
);
Buffer = (UINT8 *)Buffer + Package->FontPkgHdr->Header.Length - Package->FontPkgHdr->HdrSize;
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes all Font packages from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed Font packages.
@param PackageList Pointer to a package list that contains removing
packages.
@retval EFI_SUCCESS Font Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveFontPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *ListHead;
HII_FONT_PACKAGE_INSTANCE *Package;
EFI_STATUS Status;
HII_GLYPH_INFO *GlyphInfo;
LIST_ENTRY *Link;
HII_GLOBAL_FONT_INFO *GlobalFont;
ListHead = &PackageList->FontPkgHdr;
while (!IsListEmpty (ListHead)) {
Package = CR (
ListHead->ForwardLink,
HII_FONT_PACKAGE_INSTANCE,
FontEntry,
HII_FONT_PACKAGE_SIGNATURE
);
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_FONTS,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
RemoveEntryList (&Package->FontEntry);
PackageList->PackageListHdr.PackageLength -= Package->FontPkgHdr->Header.Length;
if (Package->GlyphBlock != NULL) {
FreePool (Package->GlyphBlock);
}
FreePool (Package->FontPkgHdr);
//
// Delete default character cell information
//
while (!IsListEmpty (&Package->GlyphInfoList)) {
GlyphInfo = CR (
Package->GlyphInfoList.ForwardLink,
HII_GLYPH_INFO,
Entry,
HII_GLYPH_INFO_SIGNATURE
);
RemoveEntryList (&GlyphInfo->Entry);
FreePool (GlyphInfo);
}
//
// Remove corresponding global font info
//
for (Link = Private->FontInfoList.ForwardLink; Link != &Private->FontInfoList; Link = Link->ForwardLink) {
GlobalFont = CR (Link, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
if (GlobalFont->FontPackage == Package) {
RemoveEntryList (&GlobalFont->Entry);
FreePool (GlobalFont->FontInfo);
FreePool (GlobalFont);
break;
}
}
FreePool (Package);
}
return EFI_SUCCESS;
}
/**
This function insert a Image package to a package list node.
This is a internal function.
@param PackageHdr Pointer to a buffer stored with Image package
information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created Image package
@retval EFI_SUCCESS Image Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Image package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
**/
EFI_STATUS
InsertImagePackage (
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_IMAGE_PACKAGE_INSTANCE **Package
)
{
HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
UINT32 PaletteSize;
UINT32 ImageSize;
UINT16 Index;
EFI_HII_IMAGE_PALETTE_INFO_HEADER *PaletteHdr;
EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo;
UINT32 PaletteInfoOffset;
UINT32 ImageInfoOffset;
UINT16 CurrentSize;
if ((PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Less than one image package is allowed in one package list.
//
if (PackageList->ImagePkg != NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Create a Image package node
//
ImagePackage = (HII_IMAGE_PACKAGE_INSTANCE *)AllocateZeroPool (sizeof (HII_IMAGE_PACKAGE_INSTANCE));
if (ImagePackage == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Copy the Image package header.
//
CopyMem (&ImagePackage->ImagePkgHdr, PackageHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
PaletteInfoOffset = ImagePackage->ImagePkgHdr.PaletteInfoOffset;
ImageInfoOffset = ImagePackage->ImagePkgHdr.ImageInfoOffset;
//
// If PaletteInfoOffset is zero, there are no palettes in this image package.
//
PaletteSize = 0;
ImagePackage->PaletteBlock = NULL;
if (PaletteInfoOffset != 0) {
PaletteHdr = (EFI_HII_IMAGE_PALETTE_INFO_HEADER *)((UINT8 *)PackageHdr + PaletteInfoOffset);
PaletteSize = sizeof (EFI_HII_IMAGE_PALETTE_INFO_HEADER);
PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteHdr + PaletteSize);
for (Index = 0; Index < PaletteHdr->PaletteCount; Index++) {
CopyMem (&CurrentSize, PaletteInfo, sizeof (UINT16));
CurrentSize += sizeof (UINT16);
PaletteSize += (UINT32)CurrentSize;
PaletteInfo = (EFI_HII_IMAGE_PALETTE_INFO *)((UINT8 *)PaletteInfo + CurrentSize);
}
ImagePackage->PaletteBlock = (UINT8 *)AllocateZeroPool (PaletteSize);
if (ImagePackage->PaletteBlock == NULL) {
FreePool (ImagePackage);
return EFI_OUT_OF_RESOURCES;
}
CopyMem (
ImagePackage->PaletteBlock,
(UINT8 *)PackageHdr + PaletteInfoOffset,
PaletteSize
);
}
//
// If ImageInfoOffset is zero, there are no images in this package.
//
ImageSize = 0;
ImagePackage->ImageBlock = NULL;
if (ImageInfoOffset != 0) {
ImageSize = ImagePackage->ImagePkgHdr.Header.Length -
sizeof (EFI_HII_IMAGE_PACKAGE_HDR) - PaletteSize;
ImagePackage->ImageBlock = AllocateZeroPool (ImageSize);
if (ImagePackage->ImageBlock == NULL) {
FreePool (ImagePackage->PaletteBlock);
FreePool (ImagePackage);
return EFI_OUT_OF_RESOURCES;
}
CopyMem (
ImagePackage->ImageBlock,
(UINT8 *)PackageHdr + ImageInfoOffset,
ImageSize
);
}
ImagePackage->ImageBlockSize = ImageSize;
ImagePackage->PaletteInfoSize = PaletteSize;
PackageList->ImagePkg = ImagePackage;
*Package = ImagePackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += ImagePackage->ImagePkgHdr.Header.Length;
}
return EFI_SUCCESS;
}
/**
This function exports Image packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS Image Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportImagePackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
UINTN PackageLength;
EFI_STATUS Status;
HII_IMAGE_PACKAGE_INSTANCE *Package;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
Package = PackageList->ImagePkg;
if (Package == NULL) {
return EFI_SUCCESS;
}
PackageLength = Package->ImagePkgHdr.Header.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
//
// Invoke registered notification function with EXPORT_PACK notify type
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_IMAGES,
Handle
);
ASSERT_EFI_ERROR (Status);
ASSERT (
Package->ImagePkgHdr.Header.Length ==
sizeof (EFI_HII_IMAGE_PACKAGE_HDR) + Package->ImageBlockSize + Package->PaletteInfoSize
);
//
// Copy Image package header,
// then justify the offset for image info and palette info in the header.
//
CopyMem (Buffer, &Package->ImagePkgHdr, sizeof (EFI_HII_IMAGE_PACKAGE_HDR));
Buffer = (UINT8 *)Buffer + sizeof (EFI_HII_IMAGE_PACKAGE_HDR);
//
// Copy Image blocks information
//
if (Package->ImageBlockSize != 0) {
CopyMem (Buffer, Package->ImageBlock, Package->ImageBlockSize);
Buffer = (UINT8 *)Buffer + Package->ImageBlockSize;
}
//
// Copy Palette information
//
if (Package->PaletteInfoSize != 0) {
CopyMem (Buffer, Package->PaletteBlock, Package->PaletteInfoSize);
Buffer = (UINT8 *)Buffer + Package->PaletteInfoSize;
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes Image package from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed Image packages.
@param PackageList Package List which contains the to be removed
Image package.
@retval EFI_SUCCESS Image Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveImagePackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
HII_IMAGE_PACKAGE_INSTANCE *Package;
EFI_STATUS Status;
Package = PackageList->ImagePkg;
//
// Image package does not exist, return directly.
//
if (Package == NULL) {
return EFI_SUCCESS;
}
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_IMAGES,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
PackageList->PackageListHdr.PackageLength -= Package->ImagePkgHdr.Header.Length;
FreePool (Package->ImageBlock);
if (Package->PaletteBlock != NULL) {
FreePool (Package->PaletteBlock);
}
FreePool (Package);
PackageList->ImagePkg = NULL;
return EFI_SUCCESS;
}
/**
This function insert a Simple Font package to a package list node.
This is a internal function.
@param PackageHdr Pointer to a buffer stored with Simple Font
package information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created Simple Font package
@retval EFI_SUCCESS Simple Font Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Simple Font package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
**/
EFI_STATUS
InsertSimpleFontPackage (
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_SIMPLE_FONT_PACKAGE_INSTANCE **Package
)
{
HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
EFI_STATUS Status;
EFI_HII_PACKAGE_HEADER Header;
if ((PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Create a Simple Font package node
//
SimpleFontPackage = AllocateZeroPool (sizeof (HII_SIMPLE_FONT_PACKAGE_INSTANCE));
if (SimpleFontPackage == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
SimpleFontPackage->Signature = HII_S_FONT_PACKAGE_SIGNATURE;
//
// Copy the Simple Font package.
//
CopyMem (&Header, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
SimpleFontPackage->SimpleFontPkgHdr = AllocateZeroPool (Header.Length);
if (SimpleFontPackage->SimpleFontPkgHdr == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
CopyMem (SimpleFontPackage->SimpleFontPkgHdr, PackageHdr, Header.Length);
//
// Insert to Simple Font package array
//
InsertTailList (&PackageList->SimpleFontPkgHdr, &SimpleFontPackage->SimpleFontEntry);
*Package = SimpleFontPackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += Header.Length;
}
return EFI_SUCCESS;
Error:
if (SimpleFontPackage != NULL) {
if (SimpleFontPackage->SimpleFontPkgHdr != NULL) {
FreePool (SimpleFontPackage->SimpleFontPkgHdr);
}
FreePool (SimpleFontPackage);
}
return Status;
}
/**
This function exports SimpleFont packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS SimpleFont Packages are exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportSimpleFontPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
LIST_ENTRY *Link;
UINTN PackageLength;
EFI_STATUS Status;
HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
PackageLength = 0;
Status = EFI_SUCCESS;
for (Link = PackageList->SimpleFontPkgHdr.ForwardLink; Link != &PackageList->SimpleFontPkgHdr; Link = Link->ForwardLink) {
Package = CR (Link, HII_SIMPLE_FONT_PACKAGE_INSTANCE, SimpleFontEntry, HII_S_FONT_PACKAGE_SIGNATURE);
PackageLength += Package->SimpleFontPkgHdr->Header.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
//
// Invoke registered notification function with EXPORT_PACK notify type
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_SIMPLE_FONTS,
Handle
);
ASSERT_EFI_ERROR (Status);
//
// Copy SimpleFont package
//
CopyMem (Buffer, Package->SimpleFontPkgHdr, Package->SimpleFontPkgHdr->Header.Length);
Buffer = (UINT8 *)Buffer + Package->SimpleFontPkgHdr->Header.Length;
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes all Simple Font packages from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed Simple Font packages.
@param PackageList Pointer to a package list that contains removing
packages.
@retval EFI_SUCCESS Simple Font Package(s) is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveSimpleFontPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *ListHead;
HII_SIMPLE_FONT_PACKAGE_INSTANCE *Package;
EFI_STATUS Status;
ListHead = &PackageList->SimpleFontPkgHdr;
while (!IsListEmpty (ListHead)) {
Package = CR (
ListHead->ForwardLink,
HII_SIMPLE_FONT_PACKAGE_INSTANCE,
SimpleFontEntry,
HII_S_FONT_PACKAGE_SIGNATURE
);
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_SIMPLE_FONTS,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
RemoveEntryList (&Package->SimpleFontEntry);
PackageList->PackageListHdr.PackageLength -= Package->SimpleFontPkgHdr->Header.Length;
FreePool (Package->SimpleFontPkgHdr);
FreePool (Package);
}
return EFI_SUCCESS;
}
/**
This function insert a Device path package to a package list node.
This is a internal function.
@param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
instance
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@retval EFI_SUCCESS Device path Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Device path package.
@retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
**/
EFI_STATUS
InsertDevicePathPackage (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
UINT32 PackageLength;
EFI_HII_PACKAGE_HEADER Header;
if ((DevicePath == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Less than one device path package is allowed in one package list.
//
if (PackageList->DevicePathPkg != NULL) {
return EFI_INVALID_PARAMETER;
}
PackageLength = (UINT32)GetDevicePathSize (DevicePath) + sizeof (EFI_HII_PACKAGE_HEADER);
PackageList->DevicePathPkg = (UINT8 *)AllocateZeroPool (PackageLength);
if (PackageList->DevicePathPkg == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Header.Length = PackageLength;
Header.Type = EFI_HII_PACKAGE_DEVICE_PATH;
CopyMem (PackageList->DevicePathPkg, &Header, sizeof (EFI_HII_PACKAGE_HEADER));
CopyMem (
PackageList->DevicePathPkg + sizeof (EFI_HII_PACKAGE_HEADER),
DevicePath,
PackageLength - sizeof (EFI_HII_PACKAGE_HEADER)
);
//
// Since Device Path package is created by NewPackageList, either NEW_PACK
// or ADD_PACK should increase the length of package list.
//
PackageList->PackageListHdr.PackageLength += PackageLength;
return EFI_SUCCESS;
}
/**
This function exports device path package to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS Device path Package is exported successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportDevicePathPackage (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
EFI_STATUS Status;
UINT8 *Package;
EFI_HII_PACKAGE_HEADER Header;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
Package = PackageList->DevicePathPkg;
if (Package == NULL) {
return EFI_SUCCESS;
}
CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
if (Header.Length + *ResultSize + UsedSize <= BufferSize) {
//
// Invoke registered notification function with EXPORT_PACK notify type
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_DEVICE_PATH,
Handle
);
ASSERT_EFI_ERROR (Status);
//
// Copy Device path package
//
CopyMem (Buffer, Package, Header.Length);
}
*ResultSize += Header.Length;
return EFI_SUCCESS;
}
/**
This function deletes Device Path package from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list.
@param PackageList Package List which contains the to be removed
Device Path package.
@retval EFI_SUCCESS Device Path Package is deleted successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveDevicePathPackage (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
EFI_STATUS Status;
UINT8 *Package;
EFI_HII_PACKAGE_HEADER Header;
Package = PackageList->DevicePathPkg;
//
// No device path, return directly.
//
if (Package == NULL) {
return EFI_SUCCESS;
}
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_DEVICE_PATH,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
CopyMem (&Header, Package, sizeof (EFI_HII_PACKAGE_HEADER));
PackageList->PackageListHdr.PackageLength -= Header.Length;
FreePool (Package);
PackageList->DevicePathPkg = NULL;
return EFI_SUCCESS;
}
/**
This function will insert a device path package to package list firstly then
invoke notification functions if any.
This is a internal function.
@param Private Hii database private structure.
@param NotifyType The type of change concerning the database.
@param DevicePath Pointer to a EFI_DEVICE_PATH_PROTOCOL protocol
instance
@param DatabaseRecord Pointer to a database record contains a package
list which will be inserted to.
@retval EFI_SUCCESS Device path Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Device path package.
@retval EFI_INVALID_PARAMETER DevicePath is NULL or PackageList is NULL.
**/
EFI_STATUS
AddDevicePathPackage (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN OUT HII_DATABASE_RECORD *DatabaseRecord
)
{
EFI_STATUS Status;
if (DevicePath == NULL) {
return EFI_SUCCESS;
}
ASSERT (Private != NULL);
ASSERT (DatabaseRecord != NULL);
//
// Create a device path package and insert to packagelist
//
Status = InsertDevicePathPackage (
DevicePath,
NotifyType,
DatabaseRecord->PackageList
);
if (EFI_ERROR (Status)) {
return Status;
}
return InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)DatabaseRecord->PackageList->DevicePathPkg,
EFI_HII_PACKAGE_DEVICE_PATH,
DatabaseRecord->Handle
);
}
/**
This function insert a Keyboard Layout package to a package list node.
This is a internal function.
@param PackageHdr Pointer to a buffer stored with Keyboard Layout
package information.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list which will be inserted
to.
@param Package Created Keyboard Layout package
@retval EFI_SUCCESS Keyboard Layout Package is inserted successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Keyboard Layout package.
@retval EFI_INVALID_PARAMETER PackageHdr is NULL or PackageList is NULL.
**/
EFI_STATUS
InsertKeyboardLayoutPackage (
IN VOID *PackageHdr,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
OUT HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE **Package
)
{
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
EFI_HII_PACKAGE_HEADER PackageHeader;
EFI_STATUS Status;
if ((PackageHdr == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
CopyMem (&PackageHeader, PackageHdr, sizeof (EFI_HII_PACKAGE_HEADER));
//
// Create a Keyboard Layout package node
//
KeyboardLayoutPackage = AllocateZeroPool (sizeof (HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE));
if (KeyboardLayoutPackage == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
KeyboardLayoutPackage->Signature = HII_KB_LAYOUT_PACKAGE_SIGNATURE;
KeyboardLayoutPackage->KeyboardPkg = (UINT8 *)AllocateZeroPool (PackageHeader.Length);
if (KeyboardLayoutPackage->KeyboardPkg == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
CopyMem (KeyboardLayoutPackage->KeyboardPkg, PackageHdr, PackageHeader.Length);
InsertTailList (&PackageList->KeyboardLayoutHdr, &KeyboardLayoutPackage->KeyboardEntry);
*Package = KeyboardLayoutPackage;
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
PackageList->PackageListHdr.PackageLength += PackageHeader.Length;
}
return EFI_SUCCESS;
Error:
if (KeyboardLayoutPackage != NULL) {
if (KeyboardLayoutPackage->KeyboardPkg != NULL) {
FreePool (KeyboardLayoutPackage->KeyboardPkg);
}
FreePool (KeyboardLayoutPackage);
}
return Status;
}
/**
This function exports Keyboard Layout packages to a buffer.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer be used.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@param ResultSize The size of the already exported content of this
package list.
@retval EFI_SUCCESS Keyboard Layout Packages are exported
successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportKeyboardLayoutPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN UINTN UsedSize,
IN UINTN BufferSize,
IN OUT VOID *Buffer,
IN OUT UINTN *ResultSize
)
{
LIST_ENTRY *Link;
UINTN PackageLength;
EFI_STATUS Status;
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
EFI_HII_PACKAGE_HEADER PackageHeader;
if ((Private == NULL) || (PackageList == NULL) || (ResultSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
PackageLength = 0;
Status = EFI_SUCCESS;
for (Link = PackageList->KeyboardLayoutHdr.ForwardLink; Link != &PackageList->KeyboardLayoutHdr; Link = Link->ForwardLink) {
Package = CR (Link, HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE, KeyboardEntry, HII_KB_LAYOUT_PACKAGE_SIGNATURE);
CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
PackageLength += PackageHeader.Length;
if (PackageLength + *ResultSize + UsedSize <= BufferSize) {
//
// Invoke registered notification function with EXPORT_PACK notify type
//
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_EXPORT_PACK,
(EFI_HII_PACKAGE_HEADER *)Package,
EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
Handle
);
ASSERT_EFI_ERROR (Status);
//
// Copy Keyboard Layout package
//
CopyMem (Buffer, Package->KeyboardPkg, PackageHeader.Length);
Buffer = (UINT8 *)Buffer + PackageHeader.Length;
}
}
*ResultSize += PackageLength;
return EFI_SUCCESS;
}
/**
This function deletes all Keyboard Layout packages from a package list node.
This is a internal function.
@param Private Hii database private data.
@param Handle Handle of the package list which contains the to
be removed Keyboard Layout packages.
@param PackageList Pointer to a package list that contains removing
packages.
@retval EFI_SUCCESS Keyboard Layout Package(s) is deleted
successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is not valid.
**/
EFI_STATUS
RemoveKeyboardLayoutPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN OUT HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList
)
{
LIST_ENTRY *ListHead;
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
EFI_HII_PACKAGE_HEADER PackageHeader;
EFI_STATUS Status;
ListHead = &PackageList->KeyboardLayoutHdr;
while (!IsListEmpty (ListHead)) {
Package = CR (
ListHead->ForwardLink,
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
KeyboardEntry,
HII_KB_LAYOUT_PACKAGE_SIGNATURE
);
Status = InvokeRegisteredFunction (
Private,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
(VOID *)Package,
EFI_HII_PACKAGE_KEYBOARD_LAYOUT,
Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
RemoveEntryList (&Package->KeyboardEntry);
CopyMem (&PackageHeader, Package->KeyboardPkg, sizeof (EFI_HII_PACKAGE_HEADER));
PackageList->PackageListHdr.PackageLength -= PackageHeader.Length;
FreePool (Package->KeyboardPkg);
FreePool (Package);
}
return EFI_SUCCESS;
}
/**
This function will insert a package list to hii database firstly then
invoke notification functions if any. It is the worker function of
HiiNewPackageList and HiiUpdatePackageList.
This is a internal function.
@param Private Hii database private structure.
@param NotifyType The type of change concerning the database.
@param PackageList Pointer to a package list.
@param DatabaseRecord Pointer to a database record contains a package
list instance which will be inserted to.
@retval EFI_SUCCESS All incoming packages are inserted to current
database.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
Device path package.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
AddPackages (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
IN OUT HII_DATABASE_RECORD *DatabaseRecord
)
{
EFI_STATUS Status;
HII_GUID_PACKAGE_INSTANCE *GuidPackage;
HII_IFR_PACKAGE_INSTANCE *FormPackage;
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *KeyboardLayoutPackage;
HII_STRING_PACKAGE_INSTANCE *StringPackage;
HII_FONT_PACKAGE_INSTANCE *FontPackage;
HII_SIMPLE_FONT_PACKAGE_INSTANCE *SimpleFontPackage;
HII_IMAGE_PACKAGE_INSTANCE *ImagePackage;
EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
EFI_HII_PACKAGE_HEADER PackageHeader;
UINT32 OldPackageListLen;
BOOLEAN StringPkgIsAdd;
//
// Initialize Variables
//
StringPkgIsAdd = FALSE;
FontPackage = NULL;
StringPackage = NULL;
GuidPackage = NULL;
FormPackage = NULL;
ImagePackage = NULL;
SimpleFontPackage = NULL;
KeyboardLayoutPackage = NULL;
//
// Process the package list header
//
OldPackageListLen = DatabaseRecord->PackageList->PackageListHdr.PackageLength;
CopyMem (
&DatabaseRecord->PackageList->PackageListHdr,
(VOID *)PackageList,
sizeof (EFI_HII_PACKAGE_LIST_HEADER)
);
if (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK) {
DatabaseRecord->PackageList->PackageListHdr.PackageLength = OldPackageListLen;
}
PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
Status = EFI_SUCCESS;
while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
switch (PackageHeader.Type) {
case EFI_HII_PACKAGE_TYPE_GUID:
Status = InsertGuidPackage (
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&GuidPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)GuidPackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
break;
case EFI_HII_PACKAGE_FORMS:
Status = InsertFormPackage (
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&FormPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)FormPackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
//
// If Hii runtime support feature is enabled,
// will export Hii info for runtime use after ReadyToBoot event triggered.
// If some driver add/update/remove packages from HiiDatabase after ReadyToBoot,
// will need to export the content of HiiDatabase.
// But if form packages added/updated, also need to export the ConfigResp string.
//
if (gExportAfterReadyToBoot) {
gExportConfigResp = TRUE;
}
break;
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
Status = InsertKeyboardLayoutPackage (
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&KeyboardLayoutPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)KeyboardLayoutPackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
break;
case EFI_HII_PACKAGE_STRINGS:
Status = InsertStringPackage (
Private,
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&StringPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (StringPackage != NULL);
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)StringPackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
StringPkgIsAdd = TRUE;
break;
case EFI_HII_PACKAGE_FONTS:
Status = InsertFontPackage (
Private,
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&FontPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)FontPackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
break;
case EFI_HII_PACKAGE_IMAGES:
Status = InsertImagePackage (
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&ImagePackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)ImagePackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
break;
case EFI_HII_PACKAGE_SIMPLE_FONTS:
Status = InsertSimpleFontPackage (
PackageHdrPtr,
NotifyType,
DatabaseRecord->PackageList,
&SimpleFontPackage
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = InvokeRegisteredFunction (
Private,
NotifyType,
(VOID *)SimpleFontPackage,
(UINT8)(PackageHeader.Type),
DatabaseRecord->Handle
);
break;
case EFI_HII_PACKAGE_DEVICE_PATH:
Status = AddDevicePathPackage (
Private,
NotifyType,
(EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)PackageHdrPtr + sizeof (EFI_HII_PACKAGE_HEADER)),
DatabaseRecord
);
break;
default:
break;
}
if (EFI_ERROR (Status)) {
return Status;
}
//
// goto header of next package
//
PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageHdrPtr + PackageHeader.Length);
CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
}
//
// Adjust String Package to make sure all string packages have the same max string ID.
//
if (!EFI_ERROR (Status) && StringPkgIsAdd) {
Status = AdjustStringPackage (DatabaseRecord->PackageList);
}
return Status;
}
/**
This function exports a package list to a buffer. It is the worker function
of HiiExportPackageList.
This is a internal function.
@param Private Hii database private structure.
@param Handle Identification of a package list.
@param PackageList Pointer to a package list which will be exported.
@param UsedSize The length of buffer has been used by exporting
package lists when Handle is NULL.
@param BufferSize Length of the Buffer.
@param Buffer Allocated space for storing exported data.
@retval EFI_SUCCESS Keyboard Layout Packages are exported
successfully.
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.
**/
EFI_STATUS
ExportPackageList (
IN HII_DATABASE_PRIVATE_DATA *Private,
IN EFI_HII_HANDLE Handle,
IN HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList,
IN OUT UINTN *UsedSize,
IN UINTN BufferSize,
OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
)
{
EFI_STATUS Status;
UINTN ResultSize;
EFI_HII_PACKAGE_HEADER EndofPackageList;
ASSERT (Private != NULL && PackageList != NULL && UsedSize != NULL);
ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
ASSERT (IsHiiHandleValid (Handle));
if ((BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Copy the package list header
// ResultSize indicates the length of the exported bytes of this package list
//
ResultSize = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
if (ResultSize + *UsedSize <= BufferSize) {
CopyMem ((VOID *)Buffer, PackageList, ResultSize);
}
//
// Copy the packages and invoke EXPORT_PACK notify functions if exists.
//
Status = ExportGuidPackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportFormPackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportKeyboardLayoutPackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportStringPackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportFontPackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportImagePackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportSimpleFontPackages (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ExportDevicePathPackage (
Private,
Handle,
PackageList,
*UsedSize,
BufferSize,
(VOID *)((UINT8 *)Buffer + ResultSize),
&ResultSize
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Append the package list end.
//
EndofPackageList.Length = sizeof (EFI_HII_PACKAGE_HEADER);
EndofPackageList.Type = EFI_HII_PACKAGE_END;
if (ResultSize + *UsedSize + sizeof (EFI_HII_PACKAGE_HEADER) <= BufferSize) {
CopyMem (
(VOID *)((UINT8 *)Buffer + ResultSize),
(VOID *)&EndofPackageList,
sizeof (EFI_HII_PACKAGE_HEADER)
);
}
*UsedSize += ResultSize + sizeof (EFI_HII_PACKAGE_HEADER);
return EFI_SUCCESS;
}
/**
This function mainly use to get and update ConfigResp string.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@retval EFI_SUCCESS Get the information successfully.
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Configuration Setting data.
**/
EFI_STATUS
HiiGetConfigRespInfo (
IN CONST EFI_HII_DATABASE_PROTOCOL *This
)
{
EFI_STATUS Status;
HII_DATABASE_PRIVATE_DATA *Private;
EFI_STRING ConfigAltResp;
UINTN ConfigSize;
ConfigAltResp = NULL;
ConfigSize = 0;
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
//
// Get ConfigResp string
//
Status = HiiConfigRoutingExportConfig (&Private->ConfigRouting, &ConfigAltResp);
if (!EFI_ERROR (Status)) {
ConfigSize = StrSize (ConfigAltResp);
if (ConfigSize > gConfigRespSize) {
//
// Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.
// Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.
//
gConfigRespSize = ConfigSize + (ConfigSize >> 2);
if (gRTConfigRespBuffer != NULL) {
FreePool (gRTConfigRespBuffer);
DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));
}
gRTConfigRespBuffer = (EFI_STRING)AllocateRuntimeZeroPool (gConfigRespSize);
if (gRTConfigRespBuffer == NULL) {
FreePool (ConfigAltResp);
DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the ConfigResp string.\n"));
//
// Remove from the System Table when the configuration runtime buffer is freed.
//
gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, NULL);
return EFI_OUT_OF_RESOURCES;
}
} else {
ZeroMem (gRTConfigRespBuffer, gConfigRespSize);
}
CopyMem (gRTConfigRespBuffer, ConfigAltResp, ConfigSize);
gBS->InstallConfigurationTable (&gEfiHiiConfigRoutingProtocolGuid, gRTConfigRespBuffer);
FreePool (ConfigAltResp);
}
return EFI_SUCCESS;
}
/**
This is an internal function,mainly use to get HiiDatabase information.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL instance.
@retval EFI_SUCCESS Get the information successfully.
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the Hiidatabase data.
**/
EFI_STATUS
HiiGetDatabaseInfo (
IN CONST EFI_HII_DATABASE_PROTOCOL *This
)
{
EFI_STATUS Status;
EFI_HII_PACKAGE_LIST_HEADER *DatabaseInfo;
UINTN DatabaseInfoSize;
DatabaseInfo = NULL;
DatabaseInfoSize = 0;
//
// Get HiiDatabase information.
//
Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, DatabaseInfo);
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
if (DatabaseInfoSize > gDatabaseInfoSize ) {
//
// Do 25% overallocation to minimize the number of memory allocations after ReadyToBoot.
// Since lots of allocation after ReadyToBoot may change memory map and cause S4 resume issue.
//
gDatabaseInfoSize = DatabaseInfoSize + (DatabaseInfoSize >> 2);
if (gRTDatabaseInfoBuffer != NULL) {
FreePool (gRTDatabaseInfoBuffer);
DEBUG ((DEBUG_WARN, "[HiiDatabase]: Memory allocation is required after ReadyToBoot, which may change memory map and cause S4 resume issue.\n"));
}
gRTDatabaseInfoBuffer = AllocateRuntimeZeroPool (gDatabaseInfoSize);
if (gRTDatabaseInfoBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "[HiiDatabase]: No enough memory resource to store the HiiDatabase info.\n"));
//
// Remove from the System Table when the configuration runtime buffer is freed.
//
gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, NULL);
return EFI_OUT_OF_RESOURCES;
}
} else {
ZeroMem (gRTDatabaseInfoBuffer, gDatabaseInfoSize);
}
Status = HiiExportPackageLists (This, NULL, &DatabaseInfoSize, gRTDatabaseInfoBuffer);
ASSERT_EFI_ERROR (Status);
gBS->InstallConfigurationTable (&gEfiHiiDatabaseProtocolGuid, gRTDatabaseInfoBuffer);
return EFI_SUCCESS;
}
/**
This function adds the packages in the package list to the database and returns a handle. If there is a
EFI_DEVICE_PATH_PROTOCOL associated with the DriverHandle, then this function will
create a package of type EFI_PACKAGE_TYPE_DEVICE_PATH and add it to the package list.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
structure.
@param DriverHandle Associate the package list with this EFI handle.
If a NULL is specified, this data will not be associate
with any drivers and cannot have a callback induced.
@param Handle A pointer to the EFI_HII_HANDLE instance.
@retval EFI_SUCCESS The package list associated with the Handle was
added to the HII database.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary resources for the new
database contents.
@retval EFI_INVALID_PARAMETER PackageList is NULL or Handle is NULL.
@retval EFI_INVALID_PARAMETER PackageListGuid already exists in database.
**/
EFI_STATUS
EFIAPI
HiiNewPackageList (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList,
IN CONST EFI_HANDLE DriverHandle OPTIONAL,
OUT EFI_HII_HANDLE *Handle
)
{
EFI_STATUS Status;
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_RECORD *DatabaseRecord;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
LIST_ENTRY *Link;
EFI_GUID PackageListGuid;
if ((This == NULL) || (PackageList == NULL) || (Handle == NULL)) {
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
CopyMem (&PackageListGuid, (VOID *)PackageList, sizeof (EFI_GUID));
//
// Check the Package list GUID to guarantee this GUID is unique in database.
//
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
if (CompareGuid (
&(DatabaseRecord->PackageList->PackageListHdr.PackageListGuid),
&PackageListGuid
) &&
(DatabaseRecord->DriverHandle == DriverHandle))
{
return EFI_INVALID_PARAMETER;
}
}
EfiAcquireLock (&mHiiDatabaseLock);
//
// Build a PackageList node
//
Status = GenerateHiiDatabaseRecord (Private, &DatabaseRecord);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
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)) {
EfiReleaseLock (&mHiiDatabaseLock);
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;
//
// Check whether need to get the Database info.
// Only after ReadyToBoot, need to do the export.
//
if (gExportAfterReadyToBoot) {
HiiGetDatabaseInfo (This);
}
EfiReleaseLock (&mHiiDatabaseLock);
//
// Notes:
// HiiGetDatabaseInfo () will get the contents of HII data base,
// belong to the atomic behavior of Hii Database update.
// And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
// we can not think it belong to the atomic behavior of Hii Database update.
// That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
//
// Check whether need to get the configuration setting info from HII drivers.
// When after ReadyToBoot and need to do the export for form package add.
//
if (gExportAfterReadyToBoot && gExportConfigResp) {
HiiGetConfigRespInfo (This);
}
return EFI_SUCCESS;
}
/**
This function removes the package list that is associated with Handle
from the HII database. Before removing the package, any registered functions
with the notification type REMOVE_PACK and the same package type will be called.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param Handle The handle that was registered to the data that is
requested for removal.
@retval EFI_SUCCESS The data associated with the Handle was removed
from the HII database.
@retval EFI_NOT_FOUND The specified handle 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;
}
EfiAcquireLock (&mHiiDatabaseLock);
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)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveFormPackages (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveKeyboardLayoutPackages (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveStringPackages (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveFontPackages (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveImagePackages (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveSimpleFontPackages (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
return Status;
}
Status = RemoveDevicePathPackage (Private, Handle, PackageList);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
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);
//
// Check whether need to get the Database info.
// Only after ReadyToBoot, need to do the export.
//
if (gExportAfterReadyToBoot) {
HiiGetDatabaseInfo (This);
}
EfiReleaseLock (&mHiiDatabaseLock);
//
// Notes:
// HiiGetDatabaseInfo () will get the contents of HII data base,
// belong to the atomic behavior of Hii Database update.
// And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
// we can not think it belong to the atomic behavior of Hii Database update.
// That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
//
//
// Check whether need to get the configuration setting info from HII drivers.
// When after ReadyToBoot and need to do the export for form package remove.
//
if (gExportAfterReadyToBoot && gExportConfigResp) {
HiiGetConfigRespInfo (This);
}
return EFI_SUCCESS;
}
}
EfiReleaseLock (&mHiiDatabaseLock);
return EFI_NOT_FOUND;
}
/**
This function updates the existing package list (which has the specified Handle)
in the HII databases, using the new package list specified by PackageList.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param Handle The handle that was registered to the data that is
requested to be updated.
@param PackageList A pointer to an EFI_HII_PACKAGE_LIST_HEADER
package.
@retval EFI_SUCCESS The HII database was successfully updated.
@retval EFI_OUT_OF_RESOURCES Unable to allocate enough memory for the updated
database.
@retval EFI_INVALID_PARAMETER PackageList was NULL.
@retval EFI_NOT_FOUND The specified Handle is not in database.
**/
EFI_STATUS
EFIAPI
HiiUpdatePackageList (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE Handle,
IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageList
)
{
EFI_STATUS Status;
HII_DATABASE_PRIVATE_DATA *Private;
LIST_ENTRY *Link;
HII_DATABASE_RECORD *Node;
EFI_HII_PACKAGE_HEADER *PackageHdrPtr;
HII_DATABASE_PACKAGE_LIST_INSTANCE *OldPackageList;
EFI_HII_PACKAGE_HEADER PackageHeader;
if ((This == NULL) || (PackageList == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (!IsHiiHandleValid (Handle)) {
return EFI_NOT_FOUND;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
PackageHdrPtr = (EFI_HII_PACKAGE_HEADER *)((UINT8 *)PackageList + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
Status = EFI_SUCCESS;
EfiAcquireLock (&mHiiDatabaseLock);
//
// Get original packagelist to be updated
//
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
if (Node->Handle == Handle) {
OldPackageList = Node->PackageList;
//
// Remove the package if its type matches one of the package types which is
// contained in the new package list.
//
CopyMem (&PackageHeader, PackageHdrPtr, sizeof (EFI_HII_PACKAGE_HEADER));
while (PackageHeader.Type != EFI_HII_PACKAGE_END) {
switch (PackageHeader.Type) {
case EFI_HII_PACKAGE_TYPE_GUID:
Status = RemoveGuidPackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_FORMS:
Status = RemoveFormPackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
Status = RemoveKeyboardLayoutPackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_STRINGS:
Status = RemoveStringPackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_FONTS:
Status = RemoveFontPackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_IMAGES:
Status = RemoveImagePackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_SIMPLE_FONTS:
Status = RemoveSimpleFontPackages (Private, Handle, OldPackageList);
break;
case EFI_HII_PACKAGE_DEVICE_PATH:
Status = RemoveDevicePathPackage (Private, Handle, OldPackageList);
break;
}
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mHiiDatabaseLock);
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
//
Status = AddPackages (Private, EFI_HII_DATABASE_NOTIFY_ADD_PACK, PackageList, Node);
//
// Check whether need to get the Database info.
// Only after ReadyToBoot, need to do the export.
//
if (gExportAfterReadyToBoot && (Status == EFI_SUCCESS)) {
HiiGetDatabaseInfo (This);
}
EfiReleaseLock (&mHiiDatabaseLock);
//
// Notes:
// HiiGetDatabaseInfo () will get the contents of HII data base,
// belong to the atomic behavior of Hii Database update.
// And since HiiGetConfigRespInfo () will get the configuration setting info from HII drivers
// we can not think it belong to the atomic behavior of Hii Database update.
// That's why EfiReleaseLock (&mHiiDatabaseLock) is callled before HiiGetConfigRespInfo ().
//
//
// Check whether need to get the configuration setting info from HII drivers.
// When after ReadyToBoot and need to do the export for form package update.
//
if (gExportAfterReadyToBoot && gExportConfigResp && (Status == EFI_SUCCESS)) {
HiiGetConfigRespInfo (This);
}
return Status;
}
}
EfiReleaseLock (&mHiiDatabaseLock);
return EFI_NOT_FOUND;
}
/**
This function returns a list of the package handles of the specified type
that are currently active in the database. The pseudo-type
EFI_HII_PACKAGE_TYPE_ALL will cause all package handles to be listed.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param PackageType Specifies the package type of the packages to list
or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
listed.
@param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
this is the pointer to the GUID which must match
the Guid field of EFI_HII_GUID_PACKAGE_GUID_HDR.
Otherwise, it must be NULL.
@param HandleBufferLength On input, a pointer to the length of the handle
buffer. On output, the length of the handle
buffer that is required for the handles found.
@param Handle An array of EFI_HII_HANDLE instances returned.
@retval EFI_SUCCESS The matching handles are outputted successfully.
HandleBufferLength is updated with the actual length.
@retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
Handle is too small to support the number of
handles. HandleBufferLength is updated with a
value that will enable the data to fit.
@retval EFI_NOT_FOUND No matching handle could not be found in database.
@retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
@retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
zero and Handle was NULL.
@retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
PackageGuid is not NULL, PackageType is a EFI_HII_
PACKAGE_TYPE_GUID but PackageGuid is NULL.
**/
EFI_STATUS
EFIAPI
HiiListPackageLists (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN OUT UINTN *HandleBufferLength,
OUT EFI_HII_HANDLE *Handle
)
{
HII_GUID_PACKAGE_INSTANCE *GuidPackage;
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_RECORD *Node;
LIST_ENTRY *Link;
BOOLEAN Matched;
HII_HANDLE **Result;
UINTN ResultSize;
HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
LIST_ENTRY *Link1;
//
// Check input parameters
//
if ((This == NULL) || (HandleBufferLength == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((*HandleBufferLength > 0) && (Handle == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||
((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))
{
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
Matched = FALSE;
Result = (HII_HANDLE **)Handle;
ResultSize = 0;
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
switch (PackageType) {
case EFI_HII_PACKAGE_TYPE_GUID:
for (Link1 = PackageList->GuidPkgHdr.ForwardLink; Link1 != &PackageList->GuidPkgHdr; Link1 = Link1->ForwardLink) {
GuidPackage = CR (Link1, HII_GUID_PACKAGE_INSTANCE, GuidEntry, HII_GUID_PACKAGE_SIGNATURE);
if (CompareGuid (
(EFI_GUID *)PackageGuid,
(EFI_GUID *)(GuidPackage->GuidPkg + sizeof (EFI_HII_PACKAGE_HEADER))
))
{
Matched = TRUE;
break;
}
}
break;
case EFI_HII_PACKAGE_FORMS:
if (!IsListEmpty (&PackageList->FormPkgHdr)) {
Matched = TRUE;
}
break;
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
if (!IsListEmpty (&PackageList->KeyboardLayoutHdr)) {
Matched = TRUE;
}
break;
case EFI_HII_PACKAGE_STRINGS:
if (!IsListEmpty (&PackageList->StringPkgHdr)) {
Matched = TRUE;
}
break;
case EFI_HII_PACKAGE_FONTS:
if (!IsListEmpty (&PackageList->FontPkgHdr)) {
Matched = TRUE;
}
break;
case EFI_HII_PACKAGE_IMAGES:
if (PackageList->ImagePkg != NULL) {
Matched = TRUE;
}
break;
case EFI_HII_PACKAGE_SIMPLE_FONTS:
if (!IsListEmpty (&PackageList->SimpleFontPkgHdr)) {
Matched = TRUE;
}
break;
case EFI_HII_PACKAGE_DEVICE_PATH:
if (PackageList->DevicePathPkg != NULL) {
Matched = TRUE;
}
break;
//
// Pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package handles
// to be listed.
//
case EFI_HII_PACKAGE_TYPE_ALL:
Matched = TRUE;
break;
default:
break;
}
//
// This active package list has the specified package type, list it.
//
if (Matched) {
ResultSize += sizeof (EFI_HII_HANDLE);
if (ResultSize <= *HandleBufferLength) {
*Result++ = Node->Handle;
}
}
Matched = FALSE;
}
if (ResultSize == 0) {
return EFI_NOT_FOUND;
}
if (*HandleBufferLength < ResultSize) {
*HandleBufferLength = ResultSize;
return EFI_BUFFER_TOO_SMALL;
}
*HandleBufferLength = ResultSize;
return EFI_SUCCESS;
}
/**
This function will export one or all package lists in the database to a buffer.
For each package list exported, this function will call functions registered
with EXPORT_PACK and then copy the package list to the buffer.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param Handle An EFI_HII_HANDLE that corresponds to the desired
package list in the HII database to export or NULL
to indicate all package lists should be exported.
@param BufferSize On input, a pointer to the length of the buffer.
On output, the length of the buffer that is
required for the exported data.
@param Buffer A pointer to a buffer that will contain the
results of the export function.
@retval EFI_SUCCESS Package exported.
@retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
Handle is too small to support the number of
handles. HandleBufferLength is updated with a
value that will enable the data to fit.
@retval EFI_NOT_FOUND The specified Handle could not be found in the
current database.
@retval EFI_INVALID_PARAMETER BufferSize was NULL.
@retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
and Buffer was NULL.
**/
EFI_STATUS
EFIAPI
HiiExportPackageLists (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE Handle,
IN OUT UINTN *BufferSize,
OUT EFI_HII_PACKAGE_LIST_HEADER *Buffer
)
{
LIST_ENTRY *Link;
EFI_STATUS Status;
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_RECORD *Node;
UINTN UsedSize;
if ((This == NULL) || (BufferSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((*BufferSize > 0) && (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((Handle != NULL) && (!IsHiiHandleValid (Handle))) {
return EFI_NOT_FOUND;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
UsedSize = 0;
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
if (Handle == NULL) {
//
// Export all package lists in current hii database.
//
Status = ExportPackageList (
Private,
Node->Handle,
(HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),
&UsedSize,
*BufferSize,
(EFI_HII_PACKAGE_LIST_HEADER *)((UINT8 *)Buffer + UsedSize)
);
ASSERT_EFI_ERROR (Status);
} else if ((Handle != NULL) && (Node->Handle == Handle)) {
Status = ExportPackageList (
Private,
Handle,
(HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList),
&UsedSize,
*BufferSize,
Buffer
);
ASSERT_EFI_ERROR (Status);
if (*BufferSize < UsedSize) {
*BufferSize = UsedSize;
return EFI_BUFFER_TOO_SMALL;
}
return EFI_SUCCESS;
}
}
if ((Handle == NULL) && (UsedSize != 0)) {
if (*BufferSize < UsedSize) {
*BufferSize = UsedSize;
return EFI_BUFFER_TOO_SMALL;
}
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
/**
This function registers a function which will be called when specified actions related to packages of
the specified type occur in the HII database. By registering a function, other HII-related drivers are
notified when specific package types are added, removed or updated in the HII database.
Each driver or application which registers a notification should use
EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify() before exiting.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param PackageType Specifies the package type of the packages to list
or EFI_HII_PACKAGE_TYPE_ALL for all packages to be
listed.
@param PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then
this is the pointer to the GUID which must match
the Guid field of
EFI_HII_GUID_PACKAGE_GUID_HDR. Otherwise, it must
be NULL.
@param PackageNotifyFn Points to the function to be called when the event
specified by
NotificationType occurs.
@param NotifyType Describes the types of notification which this
function will be receiving.
@param NotifyHandle Points to the unique handle assigned to the
registered notification. Can be used in
EFI_HII_DATABASE_PROTOCOL.UnregisterPackageNotify()
to stop notifications.
@retval EFI_SUCCESS Notification registered successfully.
@retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures
@retval EFI_INVALID_PARAMETER NotifyHandle is NULL.
@retval EFI_INVALID_PARAMETER PackageGuid is not NULL when PackageType is not
EFI_HII_PACKAGE_TYPE_GUID.
@retval EFI_INVALID_PARAMETER PackageGuid is NULL when PackageType is
EFI_HII_PACKAGE_TYPE_GUID.
**/
EFI_STATUS
EFIAPI
HiiRegisterPackageNotify (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN CONST EFI_HII_DATABASE_NOTIFY PackageNotifyFn,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType,
OUT EFI_HANDLE *NotifyHandle
)
{
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_NOTIFY *Notify;
EFI_STATUS Status;
if ((This == NULL) || (NotifyHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (((PackageType == EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid == NULL)) ||
((PackageType != EFI_HII_PACKAGE_TYPE_GUID) && (PackageGuid != NULL)))
{
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
//
// Allocate a notification node
//
Notify = (HII_DATABASE_NOTIFY *)AllocateZeroPool (sizeof (HII_DATABASE_NOTIFY));
if (Notify == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Generate a notify handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Notify->NotifyHandle,
&gEfiCallerIdGuid,
NULL,
NULL
);
ASSERT_EFI_ERROR (Status);
//
// Fill in the information to the notification node
//
Notify->Signature = HII_DATABASE_NOTIFY_SIGNATURE;
Notify->PackageType = PackageType;
Notify->PackageGuid = (EFI_GUID *)PackageGuid;
Notify->PackageNotifyFn = (EFI_HII_DATABASE_NOTIFY)PackageNotifyFn;
Notify->NotifyType = NotifyType;
InsertTailList (&Private->DatabaseNotifyList, &Notify->DatabaseNotifyEntry);
*NotifyHandle = Notify->NotifyHandle;
return EFI_SUCCESS;
}
/**
Removes the specified HII database package-related notification.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param NotificationHandle The handle of the notification function being
unregistered.
@retval EFI_SUCCESS Notification is unregistered successfully.
@retval EFI_INVALID_PARAMETER The Handle is invalid.
@retval EFI_NOT_FOUND The incoming notification handle does not exist
in current hii database.
**/
EFI_STATUS
EFIAPI
HiiUnregisterPackageNotify (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HANDLE NotificationHandle
)
{
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_NOTIFY *Notify;
LIST_ENTRY *Link;
EFI_STATUS Status;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
if (NotificationHandle == NULL) {
return EFI_NOT_FOUND;
}
Status = gBS->OpenProtocol (
NotificationHandle,
&gEfiCallerIdGuid,
NULL,
NULL,
NULL,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
for (Link = Private->DatabaseNotifyList.ForwardLink; Link != &Private->DatabaseNotifyList; Link = Link->ForwardLink) {
Notify = CR (Link, HII_DATABASE_NOTIFY, DatabaseNotifyEntry, HII_DATABASE_NOTIFY_SIGNATURE);
if (Notify->NotifyHandle == NotificationHandle) {
//
// Remove the matching notification node
//
RemoveEntryList (&Notify->DatabaseNotifyEntry);
Status = gBS->UninstallMultipleProtocolInterfaces (
Notify->NotifyHandle,
&gEfiCallerIdGuid,
NULL,
NULL
);
ASSERT_EFI_ERROR (Status);
FreePool (Notify);
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
/**
This routine retrieves an array of GUID values for each keyboard layout that
was previously registered in the system.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param KeyGuidBufferLength On input, a pointer to the length of the keyboard
GUID buffer. On output, the length of the handle
buffer that is required for the handles found.
@param KeyGuidBuffer An array of keyboard layout GUID instances
returned.
@retval EFI_SUCCESS KeyGuidBuffer was updated successfully.
@retval EFI_BUFFER_TOO_SMALL The KeyGuidBufferLength parameter indicates
that KeyGuidBuffer is too small to support the
number of GUIDs. KeyGuidBufferLength is
updated with a value that will enable the data to
fit.
@retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
@retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
zero and KeyGuidBuffer is NULL.
@retval EFI_NOT_FOUND There was no keyboard layout.
**/
EFI_STATUS
EFIAPI
HiiFindKeyboardLayouts (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN OUT UINT16 *KeyGuidBufferLength,
OUT EFI_GUID *KeyGuidBuffer
)
{
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_RECORD *Node;
HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
LIST_ENTRY *Link;
LIST_ENTRY *Link1;
UINT16 ResultSize;
UINTN Index;
UINT16 LayoutCount;
UINT16 LayoutLength;
UINT8 *Layout;
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
if ((This == NULL) || (KeyGuidBufferLength == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((*KeyGuidBufferLength > 0) && (KeyGuidBuffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
ResultSize = 0;
//
// Search all package lists in whole database to retrieve keyboard layout.
//
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
PackageList = Node->PackageList;
for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
Link1 != &PackageList->KeyboardLayoutHdr;
Link1 = Link1->ForwardLink
)
{
//
// Find out all Keyboard Layout packages in this package list.
//
Package = CR (
Link1,
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
KeyboardEntry,
HII_KB_LAYOUT_PACKAGE_SIGNATURE
);
Layout = (UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
CopyMem (
&LayoutCount,
(UINT8 *)Package->KeyboardPkg + sizeof (EFI_HII_PACKAGE_HEADER),
sizeof (UINT16)
);
for (Index = 0; Index < LayoutCount; Index++) {
ResultSize += sizeof (EFI_GUID);
if (ResultSize <= *KeyGuidBufferLength) {
CopyMem (KeyGuidBuffer + (ResultSize / sizeof (EFI_GUID) - 1), Layout + sizeof (UINT16), sizeof (EFI_GUID));
CopyMem (&LayoutLength, Layout, sizeof (UINT16));
Layout = Layout + LayoutLength;
}
}
}
}
if (ResultSize == 0) {
return EFI_NOT_FOUND;
}
if (*KeyGuidBufferLength < ResultSize) {
*KeyGuidBufferLength = ResultSize;
return EFI_BUFFER_TOO_SMALL;
}
*KeyGuidBufferLength = ResultSize;
return EFI_SUCCESS;
}
/**
This routine retrieves the requested keyboard layout. The layout is a physical description of the keys
on a keyboard and the character(s) that are associated with a particular set of key strokes.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param KeyGuid A pointer to the unique ID associated with a given
keyboard layout. If KeyGuid is NULL then the
current layout will be retrieved.
@param KeyboardLayoutLength On input, a pointer to the length of the
KeyboardLayout buffer. On output, the length of
the data placed into KeyboardLayout.
@param KeyboardLayout A pointer to a buffer containing the retrieved
keyboard layout.
@retval EFI_SUCCESS The keyboard layout was retrieved successfully.
@retval EFI_NOT_FOUND The requested keyboard layout was not found.
@retval EFI_INVALID_PARAMETER The KeyboardLayout or KeyboardLayoutLength was
NULL.
@retval EFI_BUFFER_TOO_SMALL The KeyboardLayoutLength parameter indicates
that KeyboardLayout is too small to support the
requested keyboard layout. KeyboardLayoutLength is
updated with a value that will enable the
data to fit.
**/
EFI_STATUS
EFIAPI
HiiGetKeyboardLayout (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_GUID *KeyGuid,
IN OUT UINT16 *KeyboardLayoutLength,
OUT EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout
)
{
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_RECORD *Node;
HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageList;
LIST_ENTRY *Link;
LIST_ENTRY *Link1;
UINTN Index;
UINT8 *Layout;
UINT16 LayoutCount;
UINT16 LayoutLength;
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE *Package;
if ((This == NULL) || (KeyboardLayoutLength == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((*KeyboardLayoutLength > 0) && (KeyboardLayout == NULL)) {
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
//
// Retrieve the current keyboard layout.
//
if (KeyGuid == NULL) {
if (Private->CurrentLayout == NULL) {
return EFI_NOT_FOUND;
}
CopyMem (&LayoutLength, Private->CurrentLayout, sizeof (UINT16));
if (*KeyboardLayoutLength < LayoutLength) {
*KeyboardLayoutLength = LayoutLength;
return EFI_BUFFER_TOO_SMALL;
}
CopyMem (KeyboardLayout, Private->CurrentLayout, LayoutLength);
return EFI_SUCCESS;
}
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
PackageList = (HII_DATABASE_PACKAGE_LIST_INSTANCE *)(Node->PackageList);
for (Link1 = PackageList->KeyboardLayoutHdr.ForwardLink;
Link1 != &PackageList->KeyboardLayoutHdr;
Link1 = Link1->ForwardLink
)
{
Package = CR (
Link1,
HII_KEYBOARD_LAYOUT_PACKAGE_INSTANCE,
KeyboardEntry,
HII_KB_LAYOUT_PACKAGE_SIGNATURE
);
Layout = (UINT8 *)Package->KeyboardPkg +
sizeof (EFI_HII_PACKAGE_HEADER) + sizeof (UINT16);
CopyMem (&LayoutCount, Layout - sizeof (UINT16), sizeof (UINT16));
for (Index = 0; Index < LayoutCount; Index++) {
CopyMem (&LayoutLength, Layout, sizeof (UINT16));
if (CompareMem (Layout + sizeof (UINT16), KeyGuid, sizeof (EFI_GUID)) == 0) {
if (LayoutLength <= *KeyboardLayoutLength) {
CopyMem (KeyboardLayout, Layout, LayoutLength);
return EFI_SUCCESS;
} else {
*KeyboardLayoutLength = LayoutLength;
return EFI_BUFFER_TOO_SMALL;
}
}
Layout = Layout + LayoutLength;
}
}
}
return EFI_NOT_FOUND;
}
/**
This routine sets the default keyboard layout to the one referenced by KeyGuid. When this routine
is called, an event will be signaled of the EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID
group type. This is so that agents which are sensitive to the current keyboard layout being changed
can be notified of this change.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param KeyGuid A pointer to the unique ID associated with a given
keyboard layout.
@retval EFI_SUCCESS The current keyboard layout was successfully set.
@retval EFI_NOT_FOUND The referenced keyboard layout was not found, so
action was taken.
@retval EFI_INVALID_PARAMETER The KeyGuid was NULL.
**/
EFI_STATUS
EFIAPI
HiiSetKeyboardLayout (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN CONST EFI_GUID *KeyGuid
)
{
HII_DATABASE_PRIVATE_DATA *Private;
EFI_HII_KEYBOARD_LAYOUT *KeyboardLayout;
UINT16 KeyboardLayoutLength;
EFI_STATUS Status;
if ((This == NULL) || (KeyGuid == NULL)) {
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
//
// The specified GUID equals the current keyboard layout GUID,
// return directly.
//
if (CompareGuid (&Private->CurrentLayoutGuid, KeyGuid)) {
return EFI_SUCCESS;
}
//
// Try to find the incoming keyboard layout data in current database.
//
KeyboardLayoutLength = 0;
KeyboardLayout = NULL;
Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
if (Status != EFI_BUFFER_TOO_SMALL) {
return Status;
}
KeyboardLayout = (EFI_HII_KEYBOARD_LAYOUT *)AllocateZeroPool (KeyboardLayoutLength);
ASSERT (KeyboardLayout != NULL);
Status = HiiGetKeyboardLayout (This, KeyGuid, &KeyboardLayoutLength, KeyboardLayout);
ASSERT_EFI_ERROR (Status);
//
// Backup current keyboard layout.
//
CopyMem (&Private->CurrentLayoutGuid, KeyGuid, sizeof (EFI_GUID));
if (Private->CurrentLayout != NULL) {
FreePool (Private->CurrentLayout);
}
Private->CurrentLayout = KeyboardLayout;
//
// Signal EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group to notify
// current keyboard layout is changed.
//
Status = gBS->SignalEvent (gHiiKeyboardLayoutChanged);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
/**
Return the EFI handle associated with a package list.
@param This A pointer to the EFI_HII_DATABASE_PROTOCOL
instance.
@param PackageListHandle An EFI_HII_HANDLE that corresponds to the desired
package list in the HIIdatabase.
@param DriverHandle On return, contains the EFI_HANDLE which was
registered with the package list in
NewPackageList().
@retval EFI_SUCCESS The DriverHandle was returned successfully.
@retval EFI_INVALID_PARAMETER The PackageListHandle was not valid or
DriverHandle was NULL.
@retval EFI_NOT_FOUND This PackageList handle can not be found in
current database.
**/
EFI_STATUS
EFIAPI
HiiGetPackageListHandle (
IN CONST EFI_HII_DATABASE_PROTOCOL *This,
IN EFI_HII_HANDLE PackageListHandle,
OUT EFI_HANDLE *DriverHandle
)
{
HII_DATABASE_PRIVATE_DATA *Private;
HII_DATABASE_RECORD *Node;
LIST_ENTRY *Link;
if ((This == NULL) || (DriverHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (!IsHiiHandleValid (PackageListHandle)) {
return EFI_INVALID_PARAMETER;
}
Private = HII_DATABASE_DATABASE_PRIVATE_DATA_FROM_THIS (This);
for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
Node = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
if (Node->Handle == PackageListHandle) {
*DriverHandle = Node->DriverHandle;
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}