| /** @file | |
| This file contains the keyboard processing code to the HII database. | |
| Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "HiiDatabase.h" | |
| #include "HiiHandle.h" | |
| #include <Library/DebugLib.h> | |
| #include <Guid/ZeroGuid.h> | |
| CONST CHAR16 FrameworkReservedVarstoreName[] = FRAMEWORK_RESERVED_VARSTORE_NAME; | |
| /** | |
| This function returns a list of the package handles of the | |
| specified type that are currently active in the HII database. The | |
| pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package | |
| handles to be listed. | |
| If HandleBufferLength is NULL, then ASSERT. | |
| If HandleBuffer is NULL, the ASSERT. | |
| If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is | |
| NULL, then ASSERT. | |
| If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not | |
| NULL, then ASSERT. | |
| @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_PACKAGE_GUID_HEADER. Otherwise, it | |
| must be NULL. | |
| @param HandleBufferLength On output, the length of the handle buffer | |
| that is required for the handles found. | |
| @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned. | |
| The caller is responcible to free this pointer allocated. | |
| @retval EFI_SUCCESS The matching handles are outputted successfully. | |
| HandleBufferLength is updated with the actual length. | |
| @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation. | |
| @retval EFI_NOT_FOUND No matching handle could not be found in database. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ListPackageLists ( | |
| IN UINT8 PackageType, | |
| IN CONST EFI_GUID *PackageGuid, | |
| IN OUT UINTN *HandleBufferLength, | |
| OUT EFI_HII_HANDLE **HandleBuffer | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| ASSERT (HandleBufferLength != NULL); | |
| ASSERT (HandleBuffer != NULL); | |
| *HandleBufferLength = 0; | |
| *HandleBuffer = NULL; | |
| if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) { | |
| ASSERT (PackageGuid != NULL); | |
| } else { | |
| ASSERT (PackageGuid == NULL); | |
| } | |
| Status = mHiiDatabase->ListPackageLists ( | |
| mHiiDatabase, | |
| PackageType, | |
| PackageGuid, | |
| HandleBufferLength, | |
| *HandleBuffer | |
| ); | |
| if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { | |
| // | |
| // No packages is registered to UEFI HII Database, just return. | |
| // | |
| // | |
| return Status; | |
| } | |
| *HandleBuffer = AllocateZeroPool (*HandleBufferLength); | |
| if (*HandleBuffer == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| return mHiiDatabase->ListPackageLists ( | |
| mHiiDatabase, | |
| PackageType, | |
| PackageGuid, | |
| HandleBufferLength, | |
| *HandleBuffer | |
| ); | |
| } | |
| /** | |
| Exports the contents of one or all package lists in the HII database into a buffer. | |
| If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database, | |
| then ASSERT. | |
| If PackageListHeader is NULL, then ASSERT. | |
| If PackageListSize is NULL, then ASSERT. | |
| @param Handle The HII Handle. | |
| @param PackageListHeader A pointer to a buffer that will contain the results of | |
| the export function. | |
| @param PackageListSize On output, the length of the buffer that is required for the exported data. | |
| @retval EFI_SUCCESS Package exported. | |
| @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ExportPackageLists ( | |
| IN EFI_HII_HANDLE Handle, | |
| OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader, | |
| OUT UINTN *PackageListSize | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN Size; | |
| EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr; | |
| ASSERT (PackageListSize != NULL); | |
| ASSERT (PackageListHeader != NULL); | |
| Size = 0; | |
| PackageListHdr = NULL; | |
| Status = mHiiDatabase->ExportPackageLists ( | |
| mHiiDatabase, | |
| Handle, | |
| &Size, | |
| PackageListHdr | |
| ); | |
| ASSERT (Status != EFI_BUFFER_TOO_SMALL); | |
| if (Status == EFI_BUFFER_TOO_SMALL) { | |
| PackageListHdr = AllocateZeroPool (Size); | |
| if (PackageListHeader == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } else { | |
| Status = mHiiDatabase->ExportPackageLists ( | |
| mHiiDatabase, | |
| Handle, | |
| &Size, | |
| PackageListHdr | |
| ); | |
| } | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| *PackageListHeader = PackageListHdr; | |
| *PackageListSize = Size; | |
| } else { | |
| FreePool (PackageListHdr); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Extract Hii package list GUID for given HII handle. | |
| If HiiHandle could not be found in the HII database, then ASSERT. | |
| If Guid is NULL, then ASSERT. | |
| @param Handle Hii handle | |
| @param Guid Package list GUID | |
| @retval EFI_SUCCESS Successfully extract GUID from Hii database. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ExtractGuidFromHiiHandle ( | |
| IN EFI_HII_HANDLE Handle, | |
| OUT EFI_GUID *Guid | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| UINTN BufferSize; | |
| EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; | |
| ASSERT (Guid != NULL); | |
| ASSERT (Handle != NULL); | |
| // | |
| // Get HII PackageList | |
| // | |
| BufferSize = 0; | |
| HiiPackageList = NULL; | |
| Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); | |
| ASSERT (Status != EFI_NOT_FOUND); | |
| if (Status == EFI_BUFFER_TOO_SMALL) { | |
| HiiPackageList = AllocatePool (BufferSize); | |
| ASSERT (HiiPackageList != NULL); | |
| Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| FreePool (HiiPackageList); | |
| return Status; | |
| } | |
| // | |
| // Extract GUID | |
| // | |
| CopyGuid (Guid, &HiiPackageList->PackageListGuid); | |
| FreePool (HiiPackageList); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Find the corressponding UEFI HII Handle from a Framework HII Handle given. | |
| @param Private The HII Thunk Module Private context. | |
| @param FwHiiHandle The Framemwork HII Handle. | |
| @return NULL If Framework HII Handle is invalid. | |
| @return The corresponding UEFI HII Handle. | |
| **/ | |
| EFI_HII_HANDLE | |
| FwHiiHandleToUefiHiiHandle ( | |
| IN CONST HII_THUNK_PRIVATE_DATA *Private, | |
| IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle | |
| ) | |
| { | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0); | |
| ASSERT (Private != NULL); | |
| ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle); | |
| if (ThunkContext != NULL) { | |
| return ThunkContext->UefiHiiHandle; | |
| } | |
| return (EFI_HII_HANDLE) NULL; | |
| } | |
| /** | |
| Find the corressponding HII Thunk Context from a Framework HII Handle given. | |
| @param Private The HII Thunk Module Private context. | |
| @param FwHiiHandle The Framemwork HII Handle. | |
| @return NULL If Framework HII Handle is invalid. | |
| @return The corresponding HII Thunk Context. | |
| **/ | |
| HII_THUNK_CONTEXT * | |
| FwHiiHandleToThunkContext ( | |
| IN CONST HII_THUNK_PRIVATE_DATA *Private, | |
| IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| Link = GetFirstNode (&Private->ThunkContextListHead); | |
| while (!IsNull (&Private->ThunkContextListHead, Link)) { | |
| ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link); | |
| if (FwHiiHandle == ThunkContext->FwHiiHandle) { | |
| return ThunkContext; | |
| } | |
| Link = GetNextNode (&Private->ThunkContextListHead, Link); | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Find the corressponding HII Thunk Context from a UEFI HII Handle given. | |
| @param Private The HII Thunk Module Private context. | |
| @param UefiHiiHandle The UEFI HII Handle. | |
| @return NULL If UEFI HII Handle is invalid. | |
| @return The corresponding HII Thunk Context. | |
| **/ | |
| HII_THUNK_CONTEXT * | |
| UefiHiiHandleToThunkContext ( | |
| IN CONST HII_THUNK_PRIVATE_DATA *Private, | |
| IN EFI_HII_HANDLE UefiHiiHandle | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| Link = GetFirstNode (&Private->ThunkContextListHead); | |
| while (!IsNull (&Private->ThunkContextListHead, Link)) { | |
| ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link); | |
| if (UefiHiiHandle == ThunkContext->UefiHiiHandle) { | |
| return ThunkContext; | |
| } | |
| Link = GetNextNode (&Private->ThunkContextListHead, Link); | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Find the corressponding HII Thunk Context from a Tag GUID. | |
| @param Private The HII Thunk Module Private context. | |
| @param Guid The Tag GUID. | |
| @return NULL No HII Thunk Context matched the Tag GUID. | |
| @return The corresponding HII Thunk Context. | |
| **/ | |
| HII_THUNK_CONTEXT * | |
| TagGuidToIfrPackThunkContext ( | |
| IN CONST HII_THUNK_PRIVATE_DATA *Private, | |
| IN CONST EFI_GUID *Guid | |
| ) | |
| { | |
| LIST_ENTRY *Link; | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| Link = GetFirstNode (&Private->ThunkContextListHead); | |
| while (!IsNull (&Private->ThunkContextListHead, Link)) { | |
| ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link); | |
| if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) { | |
| return ThunkContext; | |
| } | |
| Link = GetNextNode (&Private->ThunkContextListHead, Link); | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Clean up the HII Thunk Context for a UEFI HII Handle. | |
| @param Private The HII Thunk Module Private context. | |
| @param UefiHiiHandle The UEFI HII Handle. | |
| **/ | |
| VOID | |
| DestroyThunkContextForUefiHiiHandle ( | |
| IN HII_THUNK_PRIVATE_DATA *Private, | |
| IN EFI_HII_HANDLE UefiHiiHandle | |
| ) | |
| { | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle); | |
| ASSERT (ThunkContext != NULL); | |
| DestroyThunkContext (ThunkContext); | |
| } | |
| /** | |
| This function create a HII_THUNK_CONTEXT for the input UEFI HiiHandle | |
| that is created when a package list registered by a module calling | |
| EFI_HII_DATABASE_PROTOCOL.NewPackageList. | |
| This function records the PackageListGuid of EFI_HII_PACKAGE_LIST_HEADER | |
| into the TagGuid of the created HII_THUNK_CONTEXT. | |
| @param UefiHiiHandle The UEFI HII Handle. | |
| @return the new created Hii thunk context. | |
| **/ | |
| HII_THUNK_CONTEXT * | |
| CreateThunkContextForUefiHiiHandle ( | |
| IN EFI_HII_HANDLE UefiHiiHandle | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_GUID PackageGuid; | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| ThunkContext = AllocateZeroPool (sizeof (*ThunkContext)); | |
| ASSERT (ThunkContext != NULL); | |
| ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE; | |
| Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle); | |
| if (EFI_ERROR (Status)) { | |
| return NULL; | |
| } | |
| ThunkContext->UefiHiiHandle = UefiHiiHandle; | |
| Status = ExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid); | |
| ASSERT_EFI_ERROR (Status); | |
| CopyGuid(&ThunkContext->TagGuid, &PackageGuid); | |
| return ThunkContext; | |
| } | |
| /** | |
| Get the number of HII Package for a Package type. | |
| @param PackageListHeader The Package List. | |
| @param PackageType The Package Type. | |
| @return The number of Package for given type. | |
| **/ | |
| UINTN | |
| GetPackageCountByType ( | |
| IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader, | |
| IN UINT8 PackageType | |
| ) | |
| { | |
| UINTN Count; | |
| EFI_HII_PACKAGE_HEADER *PackageHeader; | |
| PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER)); | |
| Count = 0; | |
| while (PackageHeader->Type != EFI_HII_PACKAGE_END) { | |
| if (PackageHeader->Type == PackageType ) { | |
| Count++; | |
| } | |
| PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length); | |
| } | |
| return Count; | |
| } | |
| /** | |
| Get the Form Package from a Framework Package List. | |
| @param Packages Framework Package List. | |
| @return The Form Package Header found. | |
| **/ | |
| EFI_HII_PACKAGE_HEADER * | |
| GetIfrPackage ( | |
| IN CONST EFI_HII_PACKAGES *Packages | |
| ) | |
| { | |
| UINTN Index; | |
| TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray; | |
| ASSERT (Packages != NULL); | |
| TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId)); | |
| for (Index = 0; Index < Packages->NumberOfPackages; Index++) { | |
| // | |
| // The current UEFI HII build tool generate a binary in the format defined by | |
| // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in | |
| // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount | |
| // may not be the exact number of valid package number in the binary generated | |
| // by HII Build tool. | |
| // | |
| switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) { | |
| case EFI_HII_IFR: | |
| return &TianoAutogenPackageHdrArray[Index]->PackageHeader; | |
| break; | |
| case EFI_HII_STRING: | |
| case EFI_HII_FONT: | |
| break; | |
| default: | |
| ASSERT (FALSE); | |
| return NULL; | |
| break; | |
| } | |
| } | |
| return NULL; | |
| } | |
| /** | |
| Get FormSet GUID. | |
| ASSERT if no FormSet Opcode is found. | |
| @param Packages Form Framework Package. | |
| @param FormSetGuid Return the FormSet Guid. | |
| **/ | |
| VOID | |
| GetFormSetGuid ( | |
| IN EFI_HII_PACKAGE_HEADER *Package, | |
| OUT EFI_GUID *FormSetGuid | |
| ) | |
| { | |
| UINTN Offset; | |
| EFI_IFR_OP_HEADER *OpCode; | |
| EFI_IFR_FORM_SET *FormSet; | |
| Offset = sizeof (EFI_HII_PACKAGE_HEADER); | |
| while (Offset < Package->Length) { | |
| OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset); | |
| switch (OpCode->OpCode) { | |
| case EFI_IFR_FORM_SET_OP: | |
| FormSet = (EFI_IFR_FORM_SET *) OpCode; | |
| CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid); | |
| return; | |
| default: | |
| break; | |
| } | |
| Offset += OpCode->Length; | |
| } | |
| // | |
| // A proper IFR must have a formset opcode. | |
| // | |
| ASSERT (FALSE); | |
| } | |
| /** | |
| Creat a Thunk Context. | |
| ASSERT if no FormSet Opcode is found. | |
| @param Private The HII Thunk Private Context. | |
| @param StringPackageCount The String package count. | |
| @param IfrPackageCount The IFR Package count. | |
| @return A newly created Thunk Context. | |
| @retval NULL No resource to create a new Thunk Context. | |
| **/ | |
| HII_THUNK_CONTEXT * | |
| CreateThunkContext ( | |
| IN HII_THUNK_PRIVATE_DATA *Private, | |
| IN UINTN StringPackageCount, | |
| IN UINTN IfrPackageCount | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| HII_THUNK_CONTEXT *ThunkContext; | |
| ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT)); | |
| ASSERT (ThunkContext != NULL); | |
| ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE; | |
| ThunkContext->IfrPackageCount = IfrPackageCount; | |
| ThunkContext->StringPackageCount = StringPackageCount; | |
| Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle); | |
| if (EFI_ERROR (Status)) { | |
| return NULL; | |
| } | |
| return ThunkContext; | |
| } | |
| /** | |
| Destroy the Thunk Context and free up all resource. | |
| @param ThunkContext The HII Thunk Private Context to be freed. | |
| **/ | |
| VOID | |
| DestroyThunkContext ( | |
| IN HII_THUNK_CONTEXT *ThunkContext | |
| ) | |
| { | |
| ASSERT (ThunkContext != NULL); | |
| FreeHiiHandle (ThunkContext->FwHiiHandle); | |
| RemoveEntryList (&ThunkContext->Link); | |
| if (ThunkContext->FormSet != NULL) { | |
| DestroyFormSet (ThunkContext->FormSet); | |
| } | |
| FreePool (ThunkContext); | |
| } | |
| /** | |
| Get the FormSet's Default Varstore ID based on the rule (Descending Priority): | |
| 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used. | |
| 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used | |
| as the default Var Store ID. | |
| @param FormSet The Form Set. The Default Varstore ID is updated if found. | |
| **/ | |
| VOID | |
| GetFormsetDefaultVarstoreId ( | |
| IN OUT FORM_BROWSER_FORMSET * FormSet | |
| ) | |
| { | |
| LIST_ENTRY *StorageList; | |
| FORMSET_STORAGE *Storage; | |
| // | |
| // VarStoreId 0 is invalid in UEFI IFR. | |
| // | |
| FormSet->DefaultVarStoreId = 0; | |
| StorageList = GetFirstNode (&FormSet->StorageListHead); | |
| while (!IsNull (&FormSet->StorageListHead, StorageList)) { | |
| Storage = FORMSET_STORAGE_FROM_LINK (StorageList); | |
| DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet->Guid, Storage->VarStoreId, Storage->Name, Storage->Size)); | |
| if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) { | |
| // | |
| // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used. | |
| // | |
| FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID; | |
| break; | |
| } | |
| StorageList = GetNextNode (&FormSet->StorageListHead, StorageList); | |
| } | |
| if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) { | |
| // | |
| // | |
| // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used | |
| // as the default Var Store ID. | |
| // | |
| StorageList = GetFirstNode (&FormSet->StorageListHead); | |
| if (!IsNull (&FormSet->StorageListHead, StorageList)) { | |
| Storage = FORMSET_STORAGE_FROM_LINK (StorageList); | |
| FormSet->DefaultVarStoreId = Storage->VarStoreId; | |
| } | |
| } | |
| if (FormSet->DefaultVarStoreId == 0) { | |
| DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid)); | |
| } | |
| return; | |
| } | |
| /** | |
| Fetch the Ifr binary data of a FormSet. | |
| @param Handle PackageList Handle | |
| @param FormSetGuid GUID of a formset. If not specified (NULL or zero | |
| GUID), take the first FormSet found in package | |
| list. | |
| @param BinaryLength The length of the FormSet IFR binary. | |
| @param BinaryData The buffer designed to receive the FormSet. | |
| @retval EFI_SUCCESS Buffer filled with the requested FormSet. | |
| BufferLength was updated. | |
| @retval EFI_INVALID_PARAMETER The handle is unknown. | |
| @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot | |
| be found with the requested FormId. | |
| **/ | |
| EFI_STATUS | |
| GetIfrBinaryData ( | |
| IN EFI_HII_HANDLE Handle, | |
| IN OUT EFI_GUID *FormSetGuid, | |
| OUT UINTN *BinaryLength, | |
| OUT UINT8 **BinaryData | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; | |
| UINTN BufferSize; | |
| UINT8 *Package; | |
| UINT8 *OpCodeData; | |
| UINT32 Offset; | |
| UINT32 Offset2; | |
| BOOLEAN ReturnDefault; | |
| UINT32 PackageListLength; | |
| EFI_HII_PACKAGE_HEADER PackageHeader; | |
| OpCodeData = NULL; | |
| Package = NULL; | |
| ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));; | |
| // | |
| // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list | |
| // | |
| if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) { | |
| ReturnDefault = TRUE; | |
| } else { | |
| ReturnDefault = FALSE; | |
| } | |
| // | |
| // Get HII PackageList | |
| // | |
| BufferSize = 0; | |
| HiiPackageList = NULL; | |
| Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); | |
| if (Status == EFI_BUFFER_TOO_SMALL) { | |
| HiiPackageList = AllocatePool (BufferSize); | |
| ASSERT (HiiPackageList != NULL); | |
| Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); | |
| } | |
| if (EFI_ERROR (Status) || HiiPackageList == NULL) { | |
| return EFI_NOT_FOUND; | |
| } | |
| // | |
| // Get Form package from this HII package List | |
| // | |
| Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); | |
| Offset2 = 0; | |
| CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); | |
| while (Offset < PackageListLength) { | |
| Package = ((UINT8 *) HiiPackageList) + Offset; | |
| CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); | |
| if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { | |
| // | |
| // Search FormSet in this Form Package | |
| // | |
| Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); | |
| while (Offset2 < PackageHeader.Length) { | |
| OpCodeData = Package + Offset2; | |
| if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { | |
| // | |
| // Check whether return default FormSet | |
| // | |
| if (ReturnDefault) { | |
| break; | |
| } | |
| // | |
| // FormSet GUID is specified, check it | |
| // | |
| if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { | |
| break; | |
| } | |
| } | |
| Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; | |
| } | |
| if (Offset2 < PackageHeader.Length) { | |
| // | |
| // Target formset found | |
| // | |
| break; | |
| } | |
| } | |
| Offset += PackageHeader.Length; | |
| } | |
| if (Offset >= PackageListLength) { | |
| // | |
| // Form package not found in this Package List | |
| // | |
| gBS->FreePool (HiiPackageList); | |
| return EFI_NOT_FOUND; | |
| } | |
| if (ReturnDefault && FormSetGuid != NULL) { | |
| // | |
| // Return the default FormSet GUID | |
| // | |
| CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)); | |
| } | |
| // | |
| // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes | |
| // in this FormSet; So, here just simply copy the data from start of a FormSet to the end | |
| // of the Form Package. | |
| // | |
| *BinaryLength = PackageHeader.Length - Offset2; | |
| *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData); | |
| gBS->FreePool (HiiPackageList); | |
| if (*BinaryData == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Initialize the internal data structure of a FormSet. | |
| @param Handle PackageList Handle | |
| @param FormSetGuid GUID of a formset. If not specified (NULL or zero | |
| GUID), take the first FormSet found in package | |
| list. | |
| @param FormSet FormSet data structure. | |
| @retval EFI_SUCCESS The function completed successfully. | |
| @retval EFI_NOT_FOUND The specified FormSet could not be found. | |
| **/ | |
| EFI_STATUS | |
| InitializeFormSet ( | |
| IN EFI_HII_HANDLE Handle, | |
| IN OUT EFI_GUID *FormSetGuid, | |
| OUT FORM_BROWSER_FORMSET *FormSet | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| FormSet->HiiHandle = Handle; | |
| CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID)); | |
| // | |
| // Parse the IFR binary OpCodes | |
| // | |
| Status = ParseOpCodes (FormSet); | |
| if (EFI_ERROR (Status)) { | |
| return Status; | |
| } | |
| GetFormsetDefaultVarstoreId (FormSet); | |
| return Status; | |
| } | |
| /** | |
| Parse the Form Package and build a FORM_BROWSER_FORMSET structure. | |
| @param UefiHiiHandle PackageList Handle | |
| @return A pointer to FORM_BROWSER_FORMSET. | |
| **/ | |
| FORM_BROWSER_FORMSET * | |
| ParseFormSet ( | |
| IN EFI_HII_HANDLE UefiHiiHandle | |
| ) | |
| { | |
| FORM_BROWSER_FORMSET *FormSet; | |
| EFI_GUID FormSetGuid; | |
| EFI_STATUS Status; | |
| FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); | |
| ASSERT (FormSet != NULL); | |
| CopyGuid (&FormSetGuid, &gZeroGuid); | |
| Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet); | |
| if (EFI_ERROR (Status)) { | |
| FreePool (FormSet); | |
| return NULL; | |
| } | |
| return FormSet; | |
| } | |