/** @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; | |
} |