diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/ConfigAccess.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/ConfigAccess.c index 0ab9074b75..ab99d5d760 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/ConfigAccess.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/ConfigAccess.c @@ -332,8 +332,8 @@ ThunkExtractConfig ( } if (!EFI_ERROR (Status)) { - Status = mUefiConfigRoutingProtocol->BlockToConfig ( - mUefiConfigRoutingProtocol, + Status = mHiiConfigRoutingProtocol->BlockToConfig ( + mHiiConfigRoutingProtocol, Request, Data, DataSize, @@ -378,8 +378,8 @@ ThunkRouteConfig ( if (Data == NULL) { return EFI_OUT_OF_RESOURCES; } - Status = mUefiConfigRoutingProtocol->ConfigToBlock ( - mUefiConfigRoutingProtocol, + Status = mHiiConfigRoutingProtocol->ConfigToBlock ( + mHiiConfigRoutingProtocol, Configuration, Data, &LastModifiedByteIndex, diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Fonts.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Fonts.c index eadc5b35b4..29914064e5 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Fonts.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Fonts.c @@ -16,6 +16,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "HiiDatabase.h" + +UINT8 mGlyphBuffer[EFI_GLYPH_WIDTH * 2 * EFI_GLYPH_HEIGHT]; + EFI_STATUS EFIAPI HiiGetGlyph ( @@ -47,7 +50,7 @@ Returns: --*/ { ASSERT (FALSE); - return EFI_SUCCESS; + return EFI_UNSUPPORTED; } EFI_STATUS @@ -64,5 +67,5 @@ HiiGlyphToBlt ( ) { ASSERT (FALSE); - return EFI_SUCCESS; + return EFI_UNSUPPORTED; } diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c index 59a859fc93..e5615cf8a4 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Forms.c @@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "HiiDatabase.h" +#include "UefiIfrDefault.h" EFI_STATUS EFIAPI @@ -89,6 +90,7 @@ Returns: return EFI_UNSUPPORTED; } + EFI_STATUS EFIAPI HiiGetDefaultImage ( @@ -119,7 +121,31 @@ HiiGetDefaultImage ( --*/ { - return EFI_SUCCESS; + LIST_ENTRY *UefiDefaults; + EFI_HII_HANDLE UefiHiiHandle; + EFI_STATUS Status; + EFI_HII_THUNK_PRIVATE_DATA *Private; + + Private = EFI_HII_THUNK_PRIVATE_DATA_FROM_THIS(This); + + UefiHiiHandle = FrameworkHiiHandleToUefiHiiHandle (Private, Handle); + if (UefiHiiHandle == NULL) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + UefiDefaults = NULL; + Status = UefiIfrGetBufferTypeDefaults (UefiHiiHandle, &UefiDefaults); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = UefiDefaultsToFrameworkDefaults (UefiDefaults, DefaultMask, VariablePackList); + +Done: + FreeDefaultList (UefiDefaults); + + return Status; } EFI_STATUS @@ -143,8 +169,8 @@ ThunkUpdateFormCallBack ( return EFI_INVALID_PARAMETER; } - Status = mUefiHiiDatabaseProtocol->GetPackageListHandle ( - mUefiHiiDatabaseProtocol, + Status = mHiiDatabase->GetPackageListHandle ( + mHiiDatabase, HandleMapEntry->UefiHiiHandle, &UefiDriverHandle ); @@ -191,7 +217,7 @@ AppendToUpdateBuffer ( } EFI_STATUS -Framework2UefiCreateSubtitleOpCode ( +F2UCreateSubtitleOpCode ( IN CONST FRAMEWORK_EFI_IFR_SUBTITLE *FwSubTitle, OUT EFI_HII_UPDATE_DATA *UefiData ) @@ -209,7 +235,7 @@ Framework2UefiCreateSubtitleOpCode ( } EFI_STATUS -Framework2UefiCreateTextOpCode ( +F2UCreateTextOpCode ( IN CONST FRAMEWORK_EFI_IFR_TEXT *FwText, OUT EFI_HII_UPDATE_DATA *UefiData ) @@ -260,11 +286,11 @@ ThunkFrameworkUpdateDataToUefiUpdateData ( for (Index = 0; Index < Data->DataCount; Index++) { switch (FrameworkOpcodeBuffer->OpCode) { case FRAMEWORK_EFI_IFR_SUBTITLE_OP: - Status = Framework2UefiCreateSubtitleOpCode ((FRAMEWORK_EFI_IFR_SUBTITLE *) FrameworkOpcodeBuffer, UefiUpdateDataBuffer); + Status = F2UCreateSubtitleOpCode ((FRAMEWORK_EFI_IFR_SUBTITLE *) FrameworkOpcodeBuffer, UefiUpdateDataBuffer); break; case FRAMEWORK_EFI_IFR_TEXT_OP: - Status = Framework2UefiCreateTextOpCode ((FRAMEWORK_EFI_IFR_TEXT *) FrameworkOpcodeBuffer, UefiUpdateDataBuffer); + Status = F2UCreateTextOpCode ((FRAMEWORK_EFI_IFR_TEXT *) FrameworkOpcodeBuffer, UefiUpdateDataBuffer); break; default: @@ -285,6 +311,199 @@ ThunkFrameworkUpdateDataToUefiUpdateData ( return EFI_SUCCESS; } + +STATIC +EFI_STATUS +GetPackageDataFromPackageList ( + IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList, + IN UINT32 PackageIndex, + OUT UINT32 *BufferLen, + OUT EFI_HII_PACKAGE_HEADER **Buffer + ) +{ + UINT32 Index; + EFI_HII_PACKAGE_HEADER *Package; + UINT32 Offset; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0}; + + ASSERT(HiiPackageList != NULL); + + if ((BufferLen == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Package = NULL; + Index = 0; + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); + while (Offset < PackageListLength) { + Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset); + CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + if (Index == PackageIndex) { + break; + } + Offset += PackageHeader.Length; + Index++; + } + if (Offset >= PackageListLength) { + // + // no package found in this Package List + // + return EFI_NOT_FOUND; + } + + *BufferLen = PackageHeader.Length; + *Buffer = Package; + return EFI_SUCCESS; +} + +/** + Check if Label exist in the IFR form package. + + @param + +**/ +EFI_STATUS +LocateLabel ( + IN CONST EFI_HII_PACKAGE_HEADER *Package, + IN EFI_FORM_LABEL Label, + OUT EFI_GUID *FormsetGuid, + OUT EFI_FORM_ID *FormId + ) +{ + UINTN Offset; + EFI_IFR_OP_HEADER *IfrOpHdr; + UINT8 ExtendOpCode; + UINT16 LabelNumber; + EFI_GUID InternalFormSetGuid; + EFI_FORM_ID InternalFormId; + BOOLEAN GetFormSet; + BOOLEAN GetForm; + + IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER)); + Offset = sizeof (EFI_HII_PACKAGE_HEADER); + + InternalFormId= 0; + ZeroMem (&InternalFormSetGuid, sizeof (EFI_GUID)); + GetFormSet = FALSE; + GetForm = FALSE; + + while (Offset < Package->Length) { + switch (IfrOpHdr->OpCode) { + case EFI_IFR_FORM_SET_OP : + CopyMem (&InternalFormSetGuid, &((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, sizeof (EFI_GUID)); + GetFormSet = TRUE; + break; + + case EFI_IFR_FORM_OP: + CopyMem (&InternalFormId, &((EFI_IFR_FORM *) IfrOpHdr)->FormId, sizeof (EFI_FORM_ID)); + GetForm = TRUE; + break; + + case EFI_IFR_GUID_OP : + ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode; + + if (ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) { + // + // Go to the next Op-Code + // + Offset += IfrOpHdr->Length; + IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length); + continue; + } + + CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16)); + if (LabelNumber == Label) { + ASSERT (GetForm && GetFormSet); + CopyGuid (FormsetGuid, &InternalFormSetGuid); + *FormId = InternalFormId; + return EFI_SUCCESS; + } + + + break; + default : + break; + } + + // + // Go to the next Op-Code + // + Offset += IfrOpHdr->Length; + IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length); + } + + return EFI_NOT_FOUND; +} + +/** + Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined. + + EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation + does not restrict labels with same label value to be duplicated in either FormSet + scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL + with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID + and Form ID is returned if such Label is found. + + + @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle. + @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or + There is no Form ID with value Label found in all Form Sets in the pacakge + list. + + @retval EFI_SUCCESS The first found Form ID is returned in FormId. +**/ +EFI_STATUS +ThunkLocateFormId ( + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + OUT EFI_GUID *FormsetGuid, + OUT EFI_FORM_ID *FormId + ) +{ + EFI_STATUS Status; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT32 Index; + UINTN BufferSize; + EFI_HII_PACKAGE_HEADER PackageHeader; + EFI_HII_PACKAGE_HEADER *Package; + UINT32 PackageLength; + + 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)) { + goto Done; + } + } + + for (Index = 0; ; Index++) { + Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package); + if (!EFI_ERROR (Status)) { + CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + if (PackageHeader.Type == EFI_HII_PACKAGE_FORM) { + Status = LocateLabel (Package, Label, FormsetGuid, FormId); + if (!EFI_ERROR(Status)) { + break; + } + } + } else { + break; + } + } + + +Done: + FreePool (HiiPackageList); + + return Status; +} EFI_STATUS EFIAPI HiiUpdateForm ( @@ -317,6 +536,8 @@ Returns: HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMapEntry; EFI_HII_UPDATE_DATA *UefiHiiUpdateData; EFI_HII_HANDLE UefiHiiHandle; + EFI_GUID FormsetGuid; + EFI_FORM_ID FormId; Status = EFI_SUCCESS; @@ -350,7 +571,10 @@ Returns: ThunkFrameworkUpdateDataToUefiUpdateData (Data, AddData, &UefiHiiUpdateData); - Status = IfrLibUpdateForm (UefiHiiHandle, NULL, 0, Label, AddData, UefiHiiUpdateData); + Status = ThunkLocateFormId (UefiHiiHandle, Label, &FormsetGuid, &FormId); + ASSERT_EFI_ERROR (Status); + + Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, AddData, UefiHiiUpdateData); ASSERT_EFI_ERROR (Status); if (UefiHiiUpdateData != NULL) { diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf index e90fe65d9c..9026256f49 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf @@ -33,6 +33,15 @@ # [Sources.common] + UefiIfrParserInternal.h + UefiIfrParserCommon.c + UefiIfrParserCommon.h + UefiIfrParser.c + UefiIfrParser.h + UefiIfrParserExpression.c + UefiIfrParserExpressionInternal.h + UefiIfrDefault.c + UefiIfrDefault.h Keyboard.c Fonts.c Package.c @@ -44,6 +53,8 @@ ConfigAccess.h Utility.c Utility.h + R8Lib.c + R8Lib.h [Packages] @@ -63,6 +74,7 @@ ExtendedHiiLib IfrSupportLib ExtendedIfrSupportLib + PrintLib [Protocols] gEfiHiiProtocolGuid @@ -73,6 +85,7 @@ gEfiHiiConfigRoutingProtocolGuid gEfiHiiConfigAccessProtocolGuid gEfiFormCallbackProtocolGuid + gEfiUnicodeCollation2ProtocolGuid [Depex] gEfiHiiImageProtocolGuid AND diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.c index e2e2ded7c3..09c571dfaa 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.c @@ -56,11 +56,11 @@ EFI_HII_THUNK_PRIVATE_DATA HiiThunkPrivateDataTempate = { }, }; -CONST EFI_HII_DATABASE_PROTOCOL *mUefiHiiDatabaseProtocol; -CONST EFI_HII_FONT_PROTOCOL *mUefiHiiFontProtocol; -CONST EFI_HII_IMAGE_PROTOCOL *mUefiHiiImageProtocol; -CONST EFI_HII_STRING_PROTOCOL *mUefiStringProtocol; -CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mUefiConfigRoutingProtocol; +CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; +CONST EFI_HII_FONT_PROTOCOL *mHiiFontProtocol; +CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol; +CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol; +CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol; EFI_STATUS @@ -96,35 +96,35 @@ Returns: Status = gBS->LocateProtocol ( &gEfiHiiDatabaseProtocolGuid, NULL, - (VOID **) &mUefiHiiDatabaseProtocol + (VOID **) &mHiiDatabase ); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol ( &gEfiHiiFontProtocolGuid, NULL, - (VOID **) &mUefiHiiFontProtocol + (VOID **) &mHiiFontProtocol ); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol ( &gEfiHiiImageProtocolGuid, NULL, - (VOID **) &mUefiHiiImageProtocol + (VOID **) &mHiiImageProtocol ); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol ( &gEfiHiiStringProtocolGuid, NULL, - (VOID **) &mUefiStringProtocol + (VOID **) &mHiiStringProtocol ); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, - (VOID **) &mUefiConfigRoutingProtocol + (VOID **) &mHiiConfigRoutingProtocol ); ASSERT_EFI_ERROR (Status); diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.h index 662f8b04e8..4ad9856141 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.h +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/HiiDatabase.h @@ -46,18 +46,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include -// -// There are some type redefinitions between Framework Ifr Support Library and -// UEFI HII Ifr Support Library. We undefine the duplicated Framework definition here -// so that the duplicated definitions in UEFI HII Ifr can be defined. -// In this Thunk Module, we will access all Framework definition with "FRAMEWORK_" prefix. -// -#undef IFR_OPTION -#undef EFI_HII_UPDATE_DATA - #include #include +#include + // // Macros // @@ -147,11 +140,11 @@ typedef struct { // // Extern Variables // -extern CONST EFI_HII_DATABASE_PROTOCOL *mUefiHiiDatabaseProtocol; -extern CONST EFI_HII_FONT_PROTOCOL *mUefiHiiFontProtocol; -extern CONST EFI_HII_IMAGE_PROTOCOL *mUefiHiiImageProtocol; -extern CONST EFI_HII_STRING_PROTOCOL *mUefiStringProtocol; -extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mUefiConfigRoutingProtocol; +extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; +extern CONST EFI_HII_FONT_PROTOCOL *mHiiFontProtocol; +extern CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol; +extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol; +extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol; // // Prototypes diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c index da0378f1ac..c22c5a6525 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Package.c @@ -86,8 +86,8 @@ LibExportPackageLists ( Size = 0; PackageListHdr = NULL; - Status = mUefiHiiDatabaseProtocol->ExportPackageLists ( - mUefiHiiDatabaseProtocol, + Status = mHiiDatabase->ExportPackageLists ( + mHiiDatabase, UefiHiiHandle, &Size, PackageListHdr @@ -100,8 +100,8 @@ LibExportPackageLists ( if (PackageListHeader == NULL) { return EFI_OUT_OF_RESOURCES; } else { - Status = mUefiHiiDatabaseProtocol->ExportPackageLists ( - mUefiHiiDatabaseProtocol, + Status = mHiiDatabase->ExportPackageLists ( + mHiiDatabase, UefiHiiHandle, &Size, PackageListHdr @@ -140,8 +140,8 @@ InsertStringPackagesToIfrPackageList ( ) { EFI_STATUS Status; - Status = mUefiHiiDatabaseProtocol->UpdatePackageList ( - mUefiHiiDatabaseProtocol, + Status = mHiiDatabase->UpdatePackageList ( + mHiiDatabase, UefiHiiHandle, StringPackageListHeader ); @@ -253,23 +253,21 @@ PrepareUefiPackageListFromFrameworkHiiPackages ( return PackageListHeader; } -EFI_GUID * -UefiGeneratePackageListGuidId ( - IN CONST EFI_HII_PACKAGES * Packages +VOID +GenerateGuidId ( + IN CONST EFI_GUID * InGuid, + OUT EFI_GUID * OutGuid ) { - EFI_GUID *Guid; UINT64 MonotonicCount; - Guid = AllocateCopyPool (sizeof (EFI_GUID), Packages->GuidId); + CopyMem (OutGuid, InGuid, sizeof (EFI_GUID)); gBS->GetNextMonotonicCount (&MonotonicCount); // // Use Monotonic Count as a psedo random number generator. // - *((UINT64 *) Guid) = *((UINT64 *) Guid) + MonotonicCount; - - return Guid; + *((UINT64 *) OutGuid) = *((UINT64 *) OutGuid) + MonotonicCount; } EFI_STATUS @@ -310,6 +308,9 @@ FindAndAddStringPackageToIfrPackageList( } +CONST EFI_GUID mAGuid = + { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e } }; + EFI_STATUS UefiRegisterPackageList( EFI_HII_THUNK_PRIVATE_DATA *Private, @@ -322,20 +323,35 @@ UefiRegisterPackageList( UINTN IfrPackNum; EFI_HII_PACKAGE_LIST_HEADER *UefiPackageListHeader; HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *HandleMappingEntry; - EFI_GUID *GuidId; + EFI_GUID GuidId; EFI_HANDLE UefiHiiDriverHandle; - GuidId = NULL; UefiHiiDriverHandle = NULL; Status = GetIfrAndStringPackNum (Packages, &IfrPackNum, &StringPackNum); ASSERT_EFI_ERROR (Status); + // + // Thunk Layer only handle the following combinations of IfrPack, StringPkg and FontPack + // + if (IfrPackNum > 1) { + return EFI_UNSUPPORTED; + } HandleMappingEntry = AllocateZeroPool (sizeof (*HandleMappingEntry)); ASSERT (HandleMappingEntry != NULL); HandleMappingEntry->Signature = HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY_SIGNATURE; HandleMappingEntry->FrameworkHiiHandle = Private->StaticHiiHandle++; + + // + // Packages->GuidId may be NULL. In such case, caller of FramworkHii->NewPack is registering + // package with StringPack and IfrPack. + // + if (Packages->GuidId == NULL) { + Packages->GuidId = &GuidId; + GenerateGuidId (&mAGuid, Packages->GuidId); + } + CopyGuid (&HandleMappingEntry->TagGuid, Packages->GuidId); if ((StringPackNum == 0) && (IfrPackNum != 0)) { @@ -344,7 +360,7 @@ UefiRegisterPackageList( // In Framework HII implementation, Packages->GuidId is used as an identifier to associate // a PackageList with only IFR to a Package list the with String package. // - GuidId = UefiGeneratePackageListGuidId (Packages); + GenerateGuidId (Packages->GuidId, &GuidId); } // @@ -354,9 +370,9 @@ UefiRegisterPackageList( if (IfrPackNum != 0) { InstallDefaultUefiConfigAccessProtocol (Packages, &UefiHiiDriverHandle, HandleMappingEntry); } - UefiPackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, GuidId); - Status = mUefiHiiDatabaseProtocol->NewPackageList ( - mUefiHiiDatabaseProtocol, + UefiPackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId); + Status = mHiiDatabase->NewPackageList ( + mHiiDatabase, UefiPackageListHeader, UefiHiiDriverHandle, &HandleMappingEntry->UefiHiiHandle @@ -413,7 +429,6 @@ Done: } FreePool (UefiPackageListHeader); - SafeFreePool (GuidId); return Status; } @@ -493,8 +508,8 @@ Returns: HandleMapEntry = FrameworkHiiHandleToMapDatabaseEntry (Private, Handle); if (HandleMapEntry->UefiHiiHandle != NULL) { - Status = mUefiHiiDatabaseProtocol->RemovePackageList ( - mUefiHiiDatabaseProtocol, + Status = mHiiDatabase->RemovePackageList ( + mHiiDatabase, HandleMapEntry->UefiHiiHandle ); ASSERT_EFI_ERROR (Status); diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/R8Lib.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/R8Lib.c new file mode 100644 index 0000000000..54693f7d35 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/R8Lib.c @@ -0,0 +1,244 @@ +/**@file + Copyright (c) 2007, Intel Corporation + + All rights reserved. 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 +#include "R8Lib.h" + +CHAR16 +NibbleToHexChar ( + IN UINT8 Nibble + ) +/*++ + + Routine Description: + Converts the low nibble of a byte to hex unicode character. + + Arguments: + Nibble - lower nibble of a byte. + + Returns: + Hex unicode character. + +--*/ +{ + Nibble &= 0x0F; + if (Nibble <= 0x9) { + return (CHAR16)(Nibble + L'0'); + } + + return (CHAR16)(Nibble - 0xA + L'A'); +} + + + +/** + Converts binary buffer to Unicode string. + At a minimum, any blob of data could be represented as a hex string. + + @param Str Pointer to the string. + @param HexStringBufferLength Length in bytes of buffer to hold the hex string. + Includes tailing '\0' character. If routine return + with EFI_SUCCESS, containing length of hex string + buffer. If routine return with + EFI_BUFFER_TOO_SMALL, containg length of hex + string buffer desired. + @param Buf Buffer to be converted from. + @param Len Length in bytes of the buffer to be converted. + + @retval EFI_SUCCESS Routine success. + @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small. + +**/ +EFI_STATUS +R8_BufToHexString ( + IN OUT CHAR16 *Str, + IN OUT UINTN *HexStringBufferLength, + IN UINT8 *Buf, + IN UINTN Len + ) +{ + // + // Porting Guide: + // This library interface is simply obsolete. + // Include the source code to user code. + // + UINTN Idx; + UINT8 Byte; + UINTN StrLen; + + // + // Make sure string is either passed or allocate enough. + // It takes 2 Unicode characters (4 bytes) to represent 1 byte of the binary buffer. + // Plus the Unicode termination character. + // + StrLen = Len * 2; + if (StrLen > ((*HexStringBufferLength) - 1)) { + *HexStringBufferLength = StrLen + 1; + return EFI_BUFFER_TOO_SMALL; + } + + *HexStringBufferLength = StrLen + 1; + // + // Ends the string. + // + Str[StrLen] = L'\0'; + + for (Idx = 0; Idx < Len; Idx++) { + + Byte = Buf[Idx]; + Str[StrLen - 1 - Idx * 2] = NibbleToHexChar (Byte); + Str[StrLen - 2 - Idx * 2] = NibbleToHexChar ((UINT8)(Byte >> 4)); + } + + return EFI_SUCCESS; +} + + + + +/** + Converts Unicode string to binary buffer. + The conversion may be partial. + The first character in the string that is not hex digit stops the conversion. + At a minimum, any blob of data could be represented as a hex string. + + @param Buf Pointer to buffer that receives the data. + @param Len Length in bytes of the buffer to hold converted + data. If routine return with EFI_SUCCESS, + containing length of converted data. If routine + return with EFI_BUFFER_TOO_SMALL, containg length + of buffer desired. + @param Str String to be converted from. + @param ConvertedStrLen Length of the Hex String consumed. + + @retval EFI_SUCCESS Routine Success. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data. + +**/ +EFI_STATUS +R8_HexStringToBuf ( + IN OUT UINT8 *Buf, + IN OUT UINTN *Len, + IN CHAR16 *Str, + OUT UINTN *ConvertedStrLen OPTIONAL + ) +{ + // + // Porting Guide: + // This library interface is simply obsolete. + // Include the source code to user code. + // + + UINTN HexCnt; + UINTN Idx; + UINTN BufferLength; + UINT8 Digit; + UINT8 Byte; + + // + // Find out how many hex characters the string has. + // + for (Idx = 0, HexCnt = 0; R8_IsHexDigit (&Digit, Str[Idx]); Idx++, HexCnt++); + + if (HexCnt == 0) { + *Len = 0; + return EFI_SUCCESS; + } + // + // Two Unicode characters make up 1 buffer byte. Round up. + // + BufferLength = (HexCnt + 1) / 2; + + // + // Test if buffer is passed enough. + // + if (BufferLength > (*Len)) { + *Len = BufferLength; + return EFI_BUFFER_TOO_SMALL; + } + + *Len = BufferLength; + + for (Idx = 0; Idx < HexCnt; Idx++) { + + R8_IsHexDigit (&Digit, Str[HexCnt - 1 - Idx]); + + // + // For odd charaters, write the lower nibble for each buffer byte, + // and for even characters, the upper nibble. + // + if ((Idx & 1) == 0) { + Byte = Digit; + } else { + Byte = Buf[Idx / 2]; + Byte &= 0x0F; + Byte = (UINT8) (Byte | Digit << 4); + } + + Buf[Idx / 2] = Byte; + } + + if (ConvertedStrLen != NULL) { + *ConvertedStrLen = HexCnt; + } + + return EFI_SUCCESS; +} + + + + +/** + Determines if a Unicode character is a hexadecimal digit. + The test is case insensitive. + + @param Digit Pointer to byte that receives the value of the hex + character. + @param Char Unicode character to test. + + @retval TRUE If the character is a hexadecimal digit. + @retval FALSE Otherwise. + +**/ +BOOLEAN +R8_IsHexDigit ( + OUT UINT8 *Digit, + IN CHAR16 Char + ) +{ + // + // Porting Guide: + // This library interface is simply obsolete. + // Include the source code to user code. + // + + if ((Char >= L'0') && (Char <= L'9')) { + *Digit = (UINT8) (Char - L'0'); + return TRUE; + } + + if ((Char >= L'A') && (Char <= L'F')) { + *Digit = (UINT8) (Char - L'A' + 0x0A); + return TRUE; + } + + if ((Char >= L'a') && (Char <= L'f')) { + *Digit = (UINT8) (Char - L'a' + 0x0A); + return TRUE; + } + + return FALSE; +} + + diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/R8Lib.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/R8Lib.h new file mode 100644 index 0000000000..a0903196e6 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/R8Lib.h @@ -0,0 +1,97 @@ +/**@file + Copyright (c) 2007, Intel Corporation + + All rights reserved. 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. + + +**/ + + + +/** + Converts binary buffer to Unicode string. + At a minimum, any blob of data could be represented as a hex string. + + @param Str Pointer to the string. + @param HexStringBufferLength Length in bytes of buffer to hold the hex string. + Includes tailing '\0' character. If routine return + with EFI_SUCCESS, containing length of hex string + buffer. If routine return with + EFI_BUFFER_TOO_SMALL, containg length of hex + string buffer desired. + @param Buf Buffer to be converted from. + @param Len Length in bytes of the buffer to be converted. + + @retval EFI_SUCCESS Routine success. + @retval EFI_BUFFER_TOO_SMALL The hex string buffer is too small. + +**/ +EFI_STATUS +R8_BufToHexString ( + IN OUT CHAR16 *Str, + IN OUT UINTN *HexStringBufferLength, + IN UINT8 *Buf, + IN UINTN Len + ) +; + + + + +/** + Converts Unicode string to binary buffer. + The conversion may be partial. + The first character in the string that is not hex digit stops the conversion. + At a minimum, any blob of data could be represented as a hex string. + + @param Buf Pointer to buffer that receives the data. + @param Len Length in bytes of the buffer to hold converted + data. If routine return with EFI_SUCCESS, + containing length of converted data. If routine + return with EFI_BUFFER_TOO_SMALL, containg length + of buffer desired. + @param Str String to be converted from. + @param ConvertedStrLen Length of the Hex String consumed. + + @retval EFI_SUCCESS Routine Success. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold converted data. + +**/ +EFI_STATUS +R8_HexStringToBuf ( + IN OUT UINT8 *Buf, + IN OUT UINTN *Len, + IN CHAR16 *Str, + OUT UINTN *ConvertedStrLen OPTIONAL + ) +; + + + + +/** + Determines if a Unicode character is a hexadecimal digit. + The test is case insensitive. + + @param Digit Pointer to byte that receives the value of the hex + character. + @param Char Unicode character to test. + + @retval TRUE If the character is a hexadecimal digit. + @retval FALSE Otherwise. + +**/ +BOOLEAN +R8_IsHexDigit ( + OUT UINT8 *Digit, + IN CHAR16 Char + ) +; + + diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Strings.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Strings.c index 0054ee43fc..85124c0316 100644 --- a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Strings.c +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/Strings.c @@ -267,8 +267,8 @@ Returns: if (AsciiLanguage == NULL) { return HiiLibGetString (HandleMapEntry->UefiHiiHandle, Token, StringBuffer, BufferLengthTemp); } else { - return mUefiStringProtocol->GetString ( - mUefiStringProtocol, + return mHiiStringProtocol->GetString ( + mHiiStringProtocol, AsciiLanguage, HandleMapEntry->UefiHiiHandle, Token, diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.c new file mode 100644 index 0000000000..2ba1ffc128 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.c @@ -0,0 +1,778 @@ +/** @file + Function and Macro defintions for to extract default values from UEFI Form package. + + Copyright (c) 2008, Intel Corporation + All rights reserved. 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 + +#include +#include + +#include +#include +#include +#include +#include + +#include "UefiIfrParser.h" +#include "UefiIfrDefault.h" + +// +// Extern Variables +// +extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; +extern CONST EFI_HII_FONT_PROTOCOL *mHiiFontProtocol; +extern CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol; +extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol; +extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol; + +extern EFI_GUID gZeroGuid; + +/** + 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)) { + return Status; + } + + // + // 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_FORM) { + // + // 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; + EFI_HANDLE DriverHandle; + + Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData); + if (EFI_ERROR (Status)) { + return Status; + } + + FormSet->HiiHandle = Handle; + CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID)); + + // + // Retrieve ConfigAccess Protocol associated with this HiiPackageList + // + Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle); + if (EFI_ERROR (Status)) { + return Status; + } + FormSet->DriverHandle = DriverHandle; + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiHiiConfigAccessProtocolGuid, + (VOID **) &FormSet->ConfigAccess + ); + if (EFI_ERROR (Status)) { + // + // Configuration Driver don't attach ConfigAccess protocol to its HII package + // list, then there will be no configuration action required + // + FormSet->ConfigAccess = NULL; + } + + // + // Parse the IFR binary OpCodes + // + Status = ParseOpCodes (FormSet); + if (EFI_ERROR (Status)) { + return Status; + } + return Status; +} + +/** + Set the data position at Offset with Width in Node->Buffer based + the value passed in. + + @param Node The Buffer Storage Node. + @param Value The input value. + @param Offset The offset in Node->Buffer for the update. + @param Width The length of the Value. + + @retval VOID + +**/ +VOID +SetNodeBuffer ( + OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node, + IN CONST EFI_HII_VALUE *Value, + IN UINTN Offset, + IN UINTN Width + ) +{ + ASSERT (Node->Signature == UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE); + ASSERT (Offset + Width <= Node->Size); + + CopyMem (Node->Buffer + Offset, &Value->Value.u8, Width); +} + + +/** + Reset Question to its default value. + + @param FormSet FormSet data structure. + @param DefaultId The Class of the default. + + @retval EFI_SUCCESS Question is reset to default value. + +**/ +EFI_STATUS +GetQuestionDefault ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN FORM_BROWSER_STATEMENT *Question, + IN UINT16 DefaultId, + IN UINT16 VarStoreId, + OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + QUESTION_DEFAULT *Default; + QUESTION_OPTION *Option; + EFI_HII_VALUE *HiiValue; + + Status = EFI_SUCCESS; + + // + // Statement don't have storage, skip them + // + if (Question->QuestionId == 0) { + return Status; + } + + if (Question->VarStoreId != VarStoreId) { + return Status; + } + + ASSERT (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER); + + // + // There are three ways to specify default value for a Question: + // 1, use nested EFI_IFR_DEFAULT (highest priority) + // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default) + // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority) + // + HiiValue = &Question->HiiValue; + + // + // EFI_IFR_DEFAULT has highest priority + // + if (!IsListEmpty (&Question->DefaultListHead)) { + Link = GetFirstNode (&Question->DefaultListHead); + while (!IsNull (&Question->DefaultListHead, Link)) { + Default = QUESTION_DEFAULT_FROM_LINK (Link); + + if (Default->DefaultId == DefaultId) { + if (Default->ValueExpression != NULL) { + // + // Default is provided by an Expression, evaluate it + // + Status = EvaluateExpression (FormSet, Form, Default->ValueExpression); + if (EFI_ERROR (Status)) { + return Status; + } + + CopyMem (HiiValue, &Default->ValueExpression->Result, sizeof (EFI_HII_VALUE)); + } else { + // + // Default value is embedded in EFI_IFR_DEFAULT + // + CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE)); + } + + SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth); + return EFI_SUCCESS; + } + + Link = GetNextNode (&Question->DefaultListHead, Link); + } + } + + // + // EFI_ONE_OF_OPTION + // + if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) { + if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + // + // OneOfOption could only provide Standard and Manufacturing default + // + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + Option = QUESTION_OPTION_FROM_LINK (Link); + + if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) || + ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG)) + ) { + CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE)); + + SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth); + return EFI_SUCCESS; + } + + Link = GetNextNode (&Question->OptionListHead, Link); + } + } + } + + // + // EFI_IFR_CHECKBOX - lowest priority + // + if (Question->Operand == EFI_IFR_CHECKBOX_OP) { + if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + // + // Checkbox could only provide Standard and Manufacturing default + // + if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) || + ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG)) + ) { + HiiValue->Value.b = TRUE; + } else { + HiiValue->Value.b = FALSE; + } + + SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth); + return EFI_SUCCESS; + } + } + + return Status; +} + + +/** + Reset Questions in a Form to their default value. + + @param FormSet FormSet data structure. + @param Form The Form which to be reset. + @param DefaultId The Class of the default. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +ExtractFormDefault ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN UINT16 DefaultId, + IN UINT16 VarStoreId, + OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Question; + + Link = GetFirstNode (&Form->StatementListHead); + while (!IsNull (&Form->StatementListHead, Link)) { + Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); + Link = GetNextNode (&Form->StatementListHead, Link); + + // + // Reset Question to its default value + // + Status = GetQuestionDefault (FormSet, Form, Question, DefaultId, VarStoreId, Node); + if (EFI_ERROR (Status)) { + continue; + } + + } + return EFI_SUCCESS; +} + + +/** + Destroy all the buffer allocated for the fileds of + UEFI_IFR_BUFFER_STORAGE_NODE. The Node itself + will be freed too. + + @param FormSet FormSet data structure. + @param DefaultId The Class of the default. + + @retval VOID + +**/ +VOID +DestroyDefaultNode ( + IN UEFI_IFR_BUFFER_STORAGE_NODE *Node + ) +{ + SafeFreePool (Node->Buffer); + SafeFreePool (Node->Name); + SafeFreePool (Node); +} + + +/** + Get the default value for Buffer Type storage named by + a Default Store and a Storage Store from a FormSet. + The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE + allocated by this function. It is inserted to the link list. + + @param DefaultStore The Default Store. + @param Storage The Storage. + @param FormSet The Form Set. + @param UefiDefaultsListHead The head of link list for the output. + + @retval EFI_SUCCESS Successful. + +**/ +EFI_STATUS +GetBufferTypeDefaultIdAndStorageId ( + IN FORMSET_DEFAULTSTORE *DefaultStore, + IN FORMSET_STORAGE *Storage, + IN FORM_BROWSER_FORMSET *FormSet, + OUT LIST_ENTRY *UefiDefaultsListHead + ) +{ + UEFI_IFR_BUFFER_STORAGE_NODE *Node; + LIST_ENTRY *Link; + FORM_BROWSER_FORM *Form; + EFI_STATUS Status; + + Node = AllocateZeroPool (sizeof (UEFI_IFR_BUFFER_STORAGE_NODE)); + ASSERT (Node != NULL); + + Node->Signature = UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE; + Node->Name = AllocateCopyPool (StrSize (Storage->Name), Storage->Name); + Node->DefaultId = DefaultStore->DefaultId; + CopyGuid (&Node->Guid, &Storage->Guid); + Node->Size = Storage->Size; + Node->Buffer = AllocateZeroPool (Node->Size); + // + // Extract default from IFR binary + // + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + Form = FORM_BROWSER_FORM_FROM_LINK (Link); + + Status = ExtractFormDefault (FormSet, Form, DefaultStore->DefaultId, Storage->VarStoreId, Node); + ASSERT_EFI_ERROR (Status); + + Link = GetNextNode (&FormSet->FormListHead, Link); + } + + InsertTailList (UefiDefaultsListHead, &Node->List); + + return EFI_SUCCESS; +} + + +/** + Get the default value for Buffer Type storage named by + a Default Store from a FormSet. + The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE + allocated by this function. The output can be multiple instances + of UEFI_IFR_BUFFER_STORAGE_NODE. It is inserted to the link list. + + @param DefaultStore The Default Store. + @param FormSet The Form Set. + @param UefiDefaultsListHead The head of link list for the output. + + @retval EFI_SUCCESS Successful. + +**/ +EFI_STATUS +GetBufferTypeDefaultId ( + IN FORMSET_DEFAULTSTORE *DefaultStore, + IN FORM_BROWSER_FORMSET *FormSet, + OUT LIST_ENTRY *UefiDefaultsListHead + ) +{ + LIST_ENTRY *StorageListEntry; + FORMSET_STORAGE *Storage; + EFI_STATUS Status; + + StorageListEntry = GetFirstNode (&FormSet->StorageListHead); + + while (!IsNull (&FormSet->StorageListHead, StorageListEntry)) { + Storage = FORMSET_STORAGE_FROM_LINK(StorageListEntry); + + if (Storage->Type == EFI_HII_VARSTORE_BUFFER) { + Status = GetBufferTypeDefaultIdAndStorageId (DefaultStore, Storage, FormSet, UefiDefaultsListHead); + } + + StorageListEntry = GetNextNode (&FormSet->StorageListHead, StorageListEntry); + } + + return EFI_SUCCESS; +} + + +/** + Get the default value for Buffer Type storage from the first FormSet + in the Package List specified by a EFI_HII_HANDLE. + + The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE. + They are inserted to the link list. + + @param UefiHiiHandle The handle for the package list. + @param UefiDefaultsListHead The head of link list for the output. + + @retval EFI_SUCCESS Successful. + +**/ +EFI_STATUS +UefiIfrGetBufferTypeDefaults ( + IN EFI_HII_HANDLE UefiHiiHandle, + OUT LIST_ENTRY **UefiDefaults + ) +{ + FORM_BROWSER_FORMSET *FormSet; + EFI_GUID FormSetGuid; + LIST_ENTRY *DefaultListEntry; + FORMSET_DEFAULTSTORE *DefaultStore; + EFI_STATUS Status; + + ASSERT (UefiDefaults != NULL); + + FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); + ASSERT (FormSet != NULL); + + CopyGuid (&FormSetGuid, &gZeroGuid); + Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet); + ASSERT_EFI_ERROR (Status); + + *UefiDefaults = AllocateZeroPool (sizeof (LIST_ENTRY)); + ASSERT (UefiDefaults != NULL); + InitializeListHead (*UefiDefaults); + + DefaultListEntry = GetFirstNode (&FormSet->DefaultStoreListHead); + while (!IsNull (&FormSet->DefaultStoreListHead, DefaultListEntry)) { + DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultListEntry); + + Status = GetBufferTypeDefaultId (DefaultStore, FormSet, *UefiDefaults); + ASSERT_EFI_ERROR (Status); + + DefaultListEntry = GetNextNode (&FormSet->DefaultStoreListHead, DefaultListEntry); + } + + DestroyFormSet (FormSet); + + return EFI_SUCCESS; +} + + +/** + Convert the UEFI Buffer Type default values to a Framework HII default + values specified by a EFI_HII_VARIABLE_PACK_LIST structure. + + @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE + which contains the default values retrived from + a UEFI form set. + @param DefaultMask The default mask. + The valid values are FRAMEWORK_EFI_IFR_FLAG_DEFAULT + and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING. + UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING + from specification to valid default class. + @param VariablePackList The output default value in a format defined in Framework. + + + @retval EFI_SUCCESS Successful. + @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or + FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING. +**/ +EFI_STATUS +UefiDefaultsToFrameworkDefaults ( + IN LIST_ENTRY *ListHead, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ) +{ + LIST_ENTRY *List; + UEFI_IFR_BUFFER_STORAGE_NODE *Node; + UINTN Size; + UINTN Count; + UINT16 DefaultId; + EFI_HII_VARIABLE_PACK *Pack; + EFI_HII_VARIABLE_PACK_LIST *PackList; + + if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_DEFAULT) { + DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + } else if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING) { + DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; + } else { + // + // UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING + // from specification to valid default class. + // + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + // + // Calculate the size of the output EFI_HII_VARIABLE_PACK_LIST structure + // + Size = 0; + Count = 0; + List = GetFirstNode (ListHead); + while (!IsNull (ListHead, List)) { + Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List); + + if (Node->DefaultId == DefaultId) { + Size += Node->Size; + Size += StrSize (Node->Name); + + Count++; + } + + List = GetNextNode (ListHead, List); + } + + Size = Size + Count * (sizeof (EFI_HII_VARIABLE_PACK_LIST) + sizeof (EFI_HII_VARIABLE_PACK)); + + *VariablePackList = AllocateZeroPool (Size); + ASSERT (*VariablePackList != NULL); + + List = GetFirstNode (ListHead); + + PackList = (EFI_HII_VARIABLE_PACK_LIST *) *VariablePackList; + Pack = (EFI_HII_VARIABLE_PACK *) (PackList + 1); + while (!IsNull (ListHead, List)) { + Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List); + + Size = 0; + if (Node->DefaultId == DefaultId) { + Size += Node->Size; + Size += StrSize (Node->Name); + Size += sizeof (EFI_HII_VARIABLE_PACK); + + // + // In UEFI, 0 is defined to be invalid for EFI_IFR_VARSTORE.VarStoreId. + // So the default storage of Var Store in VFR from a Framework module + // should be translated to 0xFFEE. + // + if (Node->StoreId == 0xFFEE) { + Pack->VariableId = 0; + } + // + // Initialize EFI_HII_VARIABLE_PACK + // + Pack->Header.Type = 0; + Pack->Header.Length = Size; + Pack->VariableId = Node->StoreId; + Pack->VariableNameLength = StrSize (Node->Name); + CopyMem (&Pack->VariableGuid, &Node->Guid, sizeof (EFI_GUID)); + + CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK), Node->Name, StrSize (Node->Name)); + CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength, Node->Buffer, Node->Size); + + Size += sizeof (EFI_HII_VARIABLE_PACK_LIST); + + // + // initialize EFI_HII_VARIABLE_PACK_LIST + // + PackList->VariablePack = Pack; + PackList->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *)((UINT8 *) PackList + Size); + + } + + List = GetNextNode (ListHead, List); + } + + + return EFI_SUCCESS; +} + + +/** + Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE. + + @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE + which contains the default values retrived from + a UEFI form set. + + + @retval EFI_SUCCESS Successful. + @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or + FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING. +**/ +VOID +FreeDefaultList ( + IN LIST_ENTRY *ListHead + ) +{ + LIST_ENTRY *Node; + UEFI_IFR_BUFFER_STORAGE_NODE *Default; + + Node = GetFirstNode (ListHead); + + while (!IsNull (ListHead, Node)) { + Default = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(Node); + + RemoveEntryList (Node); + + DestroyDefaultNode (Default); + + Node = GetFirstNode (ListHead); + } + + FreePool (ListHead); +} + diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.h new file mode 100644 index 0000000000..ee54e32e8e --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrDefault.h @@ -0,0 +1,101 @@ +/** @file + Header file for Function and Macro defintions for to extract default values from UEFI Form package. + + Copyright (c) 2008, Intel Corporation + All rights reserved. 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. + +**/ + +#ifndef _HII_THUNK_UEFI_IFR_DEFAULT_ +#define _HII_THUNK_UEFI_IFR_DEFAULT_ + + +#define UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(a) CR(a, UEFI_IFR_BUFFER_STORAGE_NODE, List, UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE) +#define UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE EFI_SIGNATURE_32 ('I', 'b', 'S', 'n') +typedef struct { + LIST_ENTRY List; + UINT32 Signature; + + EFI_GUID Guid; + CHAR16 *Name; + UINT16 DefaultId; + UINT16 StoreId; + UINTN Size; + UINT8 *Buffer; + +} UEFI_IFR_BUFFER_STORAGE_NODE; + +/** + Get the default value for Buffer Type storage from the first FormSet + in the Package List specified by a EFI_HII_HANDLE. + + The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE. + They are inserted to the link list. + + @param UefiHiiHandle The handle for the package list. + @param UefiDefaultsListHead The head of link list for the output. + + @retval EFI_SUCCESS Successful. + +**/ +EFI_STATUS +UefiIfrGetBufferTypeDefaults ( + EFI_HII_HANDLE UefiHiiHandle, + LIST_ENTRY **UefiDefaults +); + +/** + Convert the UEFI Buffer Type default values to a Framework HII default + values specified by a EFI_HII_VARIABLE_PACK_LIST structure. + + @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE + which contains the default values retrived from + a UEFI form set. + @param DefaultMask The default mask. + The valid values are FRAMEWORK_EFI_IFR_FLAG_DEFAULT + and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING. + UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING + from specification to valid default class. + @param VariablePackList The output default value in a format defined in Framework. + + + @retval EFI_SUCCESS Successful. + @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or + FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING. +**/ + +EFI_STATUS +UefiDefaultsToFrameworkDefaults ( + IN LIST_ENTRY *UefiIfrDefaults, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ) +; + +/** + Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE. + + @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE + which contains the default values retrived from + a UEFI form set. + + + @retval EFI_SUCCESS Successful. + @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or + FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING. +**/ +VOID +FreeDefaultList ( + IN LIST_ENTRY *UefiIfrDefaults + ) +; + +#endif + + diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrParser.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrParser.c new file mode 100644 index 0000000000..5074e961c0 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrParser.c @@ -0,0 +1,1641 @@ +/** @file +Parser for IFR binary encoding. + +Copyright (c) 2008, Intel Corporation +All rights reserved. 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 "UefiIfrParser.h" +#include "UefiIfrParserExpression.h" +#include "UefiIfrParserInternal.h" +#include "UefiIfrParserCommon.h" + + +UINT16 mStatementIndex; +UINT16 mExpressionOpCodeIndex; + +BOOLEAN mInScopeSubtitle; +BOOLEAN mInScopeSuppress; +BOOLEAN mInScopeGrayOut; +FORM_EXPRESSION *mSuppressExpression; +FORM_EXPRESSION *mGrayOutExpression; + +EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; +EFI_GUID gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID; + +/** + Initialize Statement header members. + + @param OpCodeData Pointer of the raw OpCode data. + @param FormSet Pointer of the current FormSe. + @param Form Pointer of the current Form. + + @return The Statement. + +**/ +FORM_BROWSER_STATEMENT * +CreateStatement ( + IN UINT8 *OpCodeData, + IN OUT FORM_BROWSER_FORMSET *FormSet, + IN OUT FORM_BROWSER_FORM *Form + ) +{ + FORM_BROWSER_STATEMENT *Statement; + EFI_IFR_STATEMENT_HEADER *StatementHdr; + + if (Form == NULL) { + // + // We are currently not in a Form Scope, so just skip this Statement + // + return NULL; + } + + Statement = &FormSet->StatementBuffer[mStatementIndex]; + mStatementIndex++; + + InitializeListHead (&Statement->DefaultListHead); + InitializeListHead (&Statement->OptionListHead); + InitializeListHead (&Statement->InconsistentListHead); + InitializeListHead (&Statement->NoSubmitListHead); + + Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE; + + Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; + + StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); + CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID)); + CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID)); + + if (mInScopeSuppress) { + Statement->SuppressExpression = mSuppressExpression; + } + + if (mInScopeGrayOut) { + Statement->GrayOutExpression = mGrayOutExpression; + } + + Statement->InSubtitle = mInScopeSubtitle; + + // + // Insert this Statement into current Form + // + InsertTailList (&Form->StatementListHead, &Statement->Link); + + return Statement; +} + + +/** + Initialize Question's members. + + @param OpCodeData Pointer of the raw OpCode data. + @param FormSet Pointer of the current FormSet. + @param Form Pointer of the current Form. + + @return The Question. + +**/ +FORM_BROWSER_STATEMENT * +CreateQuestion ( + IN UINT8 *OpCodeData, + IN OUT FORM_BROWSER_FORMSET *FormSet, + IN OUT FORM_BROWSER_FORM *Form + ) +{ + FORM_BROWSER_STATEMENT *Statement; + EFI_IFR_QUESTION_HEADER *QuestionHdr; + LIST_ENTRY *Link; + FORMSET_STORAGE *Storage; + NAME_VALUE_NODE *NameValueNode; + + Statement = CreateStatement (OpCodeData, FormSet, Form); + if (Statement == NULL) { + return NULL; + } + + QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); + CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID)); + CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID)); + CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16)); + + Statement->QuestionFlags = QuestionHdr->Flags; + + if (Statement->VarStoreId == 0) { + // + // VarStoreId of zero indicates no variable storage + // + return Statement; + } + + // + // Find Storage for this Question + // + Link = GetFirstNode (&FormSet->StorageListHead); + while (!IsNull (&FormSet->StorageListHead, Link)) { + Storage = FORMSET_STORAGE_FROM_LINK (Link); + + if (Storage->VarStoreId == Statement->VarStoreId) { + Statement->Storage = Storage; + break; + } + + Link = GetNextNode (&FormSet->StorageListHead, Link); + } + ASSERT (Statement->Storage != NULL); + + // + // Initialilze varname for Name/Value or EFI Variable + // + if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) || + (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) { + Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle); + ASSERT (Statement->VariableName != NULL); + + if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + // + // Insert to Name/Value varstore list + // + NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE)); + ASSERT (NameValueNode != NULL); + NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE; + NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName); + ASSERT (NameValueNode->Name != NULL); + NameValueNode->Value = AllocateZeroPool (0x10); + ASSERT (NameValueNode->Value != NULL); + NameValueNode->EditValue = AllocateZeroPool (0x10); + ASSERT (NameValueNode->EditValue != NULL); + + InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link); + } + } + + return Statement; +} + + +/** + Allocate a FORM_EXPRESSION node. + + @param Form The Form associated with this Expression + + @return Pointer to a FORM_EXPRESSION data structure. + +**/ +FORM_EXPRESSION * +CreateExpression ( + IN OUT FORM_BROWSER_FORM *Form + ) +{ + FORM_EXPRESSION *Expression; + + Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION)); + Expression->Signature = FORM_EXPRESSION_SIGNATURE; + InitializeListHead (&Expression->OpCodeListHead); + + return Expression; +} + + +/** + Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List. + + @param FormSet Pointer of the current FormSet + + @return Pointer to a FORMSET_STORAGE data structure. + +**/ +FORMSET_STORAGE * +CreateStorage ( + IN FORM_BROWSER_FORMSET *FormSet + ) +{ + FORMSET_STORAGE *Storage; + + Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE)); + Storage->Signature = FORMSET_STORAGE_SIGNATURE; + InitializeListHead (&Storage->NameValueListHead); + InsertTailList (&FormSet->StorageListHead, &Storage->Link); + + return Storage; +} + + +/** + Create ConfigHdr string for a storage. + + @param FormSet Pointer of the current FormSet + @param Storage Pointer of the storage + + @retval EFI_SUCCESS Initialize ConfigHdr success + +**/ +EFI_STATUS +InitializeConfigHdr ( + IN FORM_BROWSER_FORMSET *FormSet, + IN OUT FORMSET_STORAGE *Storage + ) +{ + EFI_STATUS Status; + UINTN StrBufferLen; + CHAR16 *Name; + + if (Storage->Type == EFI_HII_VARSTORE_BUFFER) { + Name = Storage->Name; + } else { + Name = NULL; + } + + StrBufferLen = 0; + Status = ConstructConfigHdr ( + Storage->ConfigHdr, + &StrBufferLen, + &Storage->Guid, + Name, + FormSet->DriverHandle + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Storage->ConfigHdr = AllocateZeroPool (StrBufferLen); + Status = ConstructConfigHdr ( + Storage->ConfigHdr, + &StrBufferLen, + &Storage->Guid, + Name, + FormSet->DriverHandle + ); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr); + Storage->SpareStrLen = 0; + + return EFI_SUCCESS; +} + + +/** + Initialize Request Element of a Question. ::= '&' | '&'