diff options
Diffstat (limited to 'MdeModulePkg/Universal/HiiDatabaseDxe/Database.c')
| -rw-r--r-- | MdeModulePkg/Universal/HiiDatabaseDxe/Database.c | 9444 |
1 files changed, 4722 insertions, 4722 deletions
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c index 0b09c24d52..f506f8b415 100644 --- a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c +++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c @@ -1,4722 +1,4722 @@ -/** @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;
-}
+/** @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; +} |
