diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /Core/CORE_DXE/FrameworkHii | |
download | zprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz |
Diffstat (limited to 'Core/CORE_DXE/FrameworkHii')
-rw-r--r-- | Core/CORE_DXE/FrameworkHii/FrameworkHii.cif | 10 | ||||
-rw-r--r-- | Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl | 15 | ||||
-rw-r--r-- | Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c | 369 | ||||
-rw-r--r-- | Core/CORE_DXE/FrameworkHii/HIIDB.c | 3511 |
4 files changed, 3905 insertions, 0 deletions
diff --git a/Core/CORE_DXE/FrameworkHii/FrameworkHii.cif b/Core/CORE_DXE/FrameworkHii/FrameworkHii.cif new file mode 100644 index 0000000..f5ece83 --- /dev/null +++ b/Core/CORE_DXE/FrameworkHii/FrameworkHii.cif @@ -0,0 +1,10 @@ +<component> + name = "FrameworkHii" + category = ModulePart + LocalRoot = "Core\CORE_DXE\FrameworkHii\" + RefName = "FrameworkHii" +[files] +"FrameworkHii.sdl" +"HIIDB.c" +"FrameworkHiiUtils.c" +<endComponent> diff --git a/Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl b/Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl new file mode 100644 index 0000000..e10b1d4 --- /dev/null +++ b/Core/CORE_DXE/FrameworkHii/FrameworkHii.sdl @@ -0,0 +1,15 @@ +TOKEN + Name = "FrameworkHii_SUPPORT" + Value = "1" + Help = "Main switch to enable FrameworkHii support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +PATH + Name = "FrameworkHii_DIR" + Help = "Path to FrameworkHii Module in Project" +End + diff --git a/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c b/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c new file mode 100644 index 0000000..c0ec1b8 --- /dev/null +++ b/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c @@ -0,0 +1,369 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c 3 2/23/10 10:17p Felixp $ +// +// $Revision: 3 $ +// +// $Date: 2/23/10 10:17p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/FrameworkHiiUtils.c $ +// +// 3 2/23/10 10:17p Felixp +// SetBrowserData function is added +// +// 2 11/24/09 10:40a Felixp +// +// 1 10/09/09 6:10p Felixp +// +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: UefiHiiUtils.c +// +// Description: Framework HII 0.91 HII Utilities Protocol Implementation +// +//<AMI_FHDR_END> +//********************************************************************** +#include <AmiDxeLib.h> +#include <Protocol/HiiUtilities.h> +#include <Protocol/LoadedImage.h> +#include <Protocol/DevicePath.h> + +static EFI_HII_PROTOCOL *Hii=NULL; +static EFI_GUID HiiResourcesFfsSectionGuid= HII_RESOURCES_FFS_SECTION_GUID; + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: SetCallback +// +// Description: +// EFI_STATUS SetCallback(EFI_HII_IFR_PACK *pIfr, +// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo, +// CALLBACK_INFO **CallBackFound) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +static EFI_STATUS SetCallback( + EFI_LOADED_IMAGE_PROTOCOL *Image, + EFI_IFR_FORM_SET *FormSet, UINTN NumberOfCallbacks, + CALLBACK_INFO *CallbackInfo, CALLBACK_INFO **CallBackFound, + EFI_HANDLE *CallbackHandle +) +{ + UINTN i; + EFI_STATUS Status; + for(i=0; i<NumberOfCallbacks; i++) + { + if ( + FormSet->Class==CallbackInfo[i].Class + && FormSet->SubClass==CallbackInfo[i].SubClass + && (!CallbackInfo[i].pGuid || !guidcmp(&FormSet->Guid,CallbackInfo[i].pGuid)) + ) + { + if (CallbackInfo[i].pFormCallback) + { + EFI_HANDLE Handle=NULL; + Status=pBS->InstallProtocolInterface(&Handle, &gEfiFormCallbackProtocolGuid, EFI_NATIVE_INTERFACE, CallbackInfo[i].pFormCallback); + if (EFI_ERROR(Status)) return Status; + FormSet->CallbackHandle=(EFI_PHYSICAL_ADDRESS)Handle; + if (CallbackHandle) *CallbackHandle=Handle; + } + if (CallBackFound) *CallBackFound=&CallbackInfo[i]; + return EFI_SUCCESS; + } + } + if (CallBackFound) *CallBackFound=NULL; + return EFI_NOT_FOUND; +} + +static EFI_STATUS PublishPackages( + IN VOID *PackagePointers, IN UINTN NumberOfPackages, + IN EFI_GUID *PackageGuid, IN EFI_HANDLE DriverHandle OPTIONAL, + OUT EFI_HII_HANDLE *HiiHandle +){ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + EFI_HII_PACK_HEADER **Packages = PackagePointers; + + if ( !Hii + && EFI_ERROR(Status=pBS->LocateProtocol( + &gEfiHiiProtocolGuid, NULL, &Hii + )) + ) return Status; + + PackageList = Malloc( + sizeof(EFI_HII_PACKAGES)+sizeof(EFI_HII_PACK_HEADER*)*NumberOfPackages + ); + if(PackageList==NULL) return EFI_OUT_OF_RESOURCES; + PackageList->NumberOfPackages=NumberOfPackages; + PackageList->GuidId = PackageGuid; + pBS->CopyMem( + PackageList+1, Packages, sizeof(EFI_HII_PACK_HEADER*)*NumberOfPackages + ); + Status = Hii->NewPack(Hii, PackageList, HiiHandle); + pBS->FreePool(PackageList); + return Status; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: LoadStrings +// +// Description: +// EFI_STATUS LoadStrings(EFI_HANDLE ImageHandle, +// EFI_HII_HANDLE *HiiHandle) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +static EFI_STATUS LoadStrings( + EFI_HANDLE ImageHandle, EFI_HII_HANDLE *HiiHandle +) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *Image; + HII_RESOURCE_SECTION_HEADER *pSection; + UINTN SectionSize; + EFI_HII_PACK_HEADER *pPack; + + if (EFI_ERROR(Status=pBS->HandleProtocol( + ImageHandle, &gEfiLoadedImageProtocolGuid, &Image + )) + ) return Status; +#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1 +{ +#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_ + UINT8 *pData; + pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize); + if (!pData) return EFI_NOT_FOUND; + pSection = Malloc(SectionSize); + pBS->CopyMem(pSection,pData,SectionSize); + Status = EFI_SUCCESS; +} +#else +{ + Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize); + if (EFI_ERROR(Status)) return Status; +} +#endif + pPack = (EFI_HII_PACK_HEADER*)(pSection+1); + if (pPack->Type == EFI_HII_STRING){ + Status = PublishPackages( + &pPack, 1, + &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid, + NULL, HiiHandle + ); + }else{ + Status = EFI_INVALID_PARAMETER; + } + pBS->FreePool(pSection); + return Status; +} + +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: LoadResources +// +// Description: +// EFI_STATUS LoadResources(EFI_HANDLE ImageHandle, +// UINTN NumberOfCallbacks, CALLBACK_INFO *CallbackInfo, +// INIT_HII_PACK InitFunction) +// +// Input: +// +// Output: +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +static EFI_STATUS LoadResources( + EFI_HANDLE ImageHandle, UINTN NumberOfCallbacks, + CALLBACK_INFO *CallbackInfo, INIT_HII_PACK InitFunction +) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_LOADED_IMAGE_PROTOCOL *Image; + HII_RESOURCE_SECTION_HEADER *pSection; + UINTN SectionSize; + CALLBACK_INFO *pCallBackFound; + if (EFI_ERROR(Status=pBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, &Image))) return Status; +#if defined(EMBEDDED_RESOURCES) && EMBEDDED_RESOURCES==1 +{ +#define AMIRC_PESECTION_NAME 0x5f534552494d415f//_AMIRES_ + UINT8 *pData; + pData = FindPeSection(Image->ImageBase, AMIRC_PESECTION_NAME, &SectionSize); + if (!pData) return EFI_NOT_FOUND; + pSection = Malloc(SectionSize); + pBS->CopyMem(pSection,pData,SectionSize); +} +#else +{ + Status=ReadImageResource(ImageHandle,&HiiResourcesFfsSectionGuid,&pSection,&SectionSize); + if (EFI_ERROR(Status)) return Status; +} +#endif +{ + EFI_HII_PACK_HEADER **IfrPackagPtr, **GlobalPackagPtr, **SharedPackagPtr; + UINTN NumberOfIfrPackages, NumberOfGlobalPackages, NumberOfSharedPackages, i; + UINT8 *PackagePtrBuffer; + EFI_HII_PACK_HEADER *PackagePtr; + + PackagePtrBuffer = Malloc(3*pSection->NumberOfPackages*sizeof(EFI_HII_PACK_HEADER*)); + IfrPackagPtr = (EFI_HII_PACK_HEADER**)PackagePtrBuffer; + GlobalPackagPtr = IfrPackagPtr+pSection->NumberOfPackages; + SharedPackagPtr = GlobalPackagPtr+pSection->NumberOfPackages; + NumberOfIfrPackages = 0; + NumberOfGlobalPackages = 0; + NumberOfSharedPackages = 0; + + PackagePtr = (EFI_HII_PACK_HEADER*)(pSection+1); + while(PackagePtr < (EFI_HII_PACK_HEADER*)((UINT8*)pSection+SectionSize)){ + switch(PackagePtr->Type){ + case EFI_HII_IFR: + IfrPackagPtr[NumberOfIfrPackages++]=PackagePtr; + break; + case EFI_HII_FONT: case EFI_HII_KEYBOARD: + GlobalPackagPtr[NumberOfGlobalPackages++]=PackagePtr; + break; + default: + SharedPackagPtr[NumberOfSharedPackages++]=PackagePtr; + if (PackagePtr->Type==EFI_HII_STRING){ + while(PackagePtr->Length) + PackagePtr = (EFI_HII_PACK_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length); + PackagePtr = (EFI_HII_PACK_HEADER*)((UINT8*)PackagePtr+sizeof(EFI_HII_STRING_PACK)); + continue; + } + break; + } + PackagePtr = (EFI_HII_PACK_HEADER*)((UINT8*)PackagePtr+PackagePtr->Length); + } + Status = PublishPackages( + GlobalPackagPtr, NumberOfGlobalPackages, + &((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH*)(Image->FilePath))->NameGuid, + NULL, &HiiHandle + ); + for(i=0; i<NumberOfIfrPackages; i++){ + EFI_HANDLE CallbackHandle; + + SharedPackagPtr[NumberOfSharedPackages]=IfrPackagPtr[i]; + SetCallback( + Image, (EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1), + NumberOfCallbacks,CallbackInfo,&pCallBackFound,&CallbackHandle + ); + Status = PublishPackages( + SharedPackagPtr, NumberOfSharedPackages+1, + &((EFI_IFR_FORM_SET*)(IfrPackagPtr[i]+1))->Guid, + CallbackHandle, &HiiHandle + ); + if (pCallBackFound) pCallBackFound->HiiHandle=HiiHandle; + if (InitFunction) InitFunction(HiiHandle,pCallBackFound); + pCallBackFound=NULL; + } + pBS->FreePool(PackagePtrBuffer); + pBS->FreePool(pSection); +} + return EFI_SUCCESS; +} + +//TODO: header +static EFI_STATUS GetString( + IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, + IN OUT UINTN *StringSize, OUT EFI_STRING String +){ + if ( !Hii + && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiProtocolGuid, NULL, &Hii)) + ) return EFI_NOT_FOUND; + return Hii->GetString( + Hii, HiiHandle, StringId, TRUE, NULL, StringSize, String + ); +} + +//TODO header +static EFI_STATUS SetString( + IN EFI_HII_HANDLE HiiHandle, IN STRING_REF StringId, IN EFI_STRING String +){ + if ( !Hii + && EFI_ERROR(pBS->LocateProtocol(&gEfiHiiProtocolGuid, NULL, &Hii)) + ) return EFI_NOT_FOUND; + return Hii->NewString( + Hii, L" ", HiiHandle, &StringId, String + ); +} + +static EFI_STATUS GetBrowserData( + IN UINTN *BufferSize, OUT VOID *Buffer, + IN CONST EFI_GUID *VarStoreGuid, OPTIONAL + IN CONST CHAR16 *VarStoreName OPTIONAL +){ + return EFI_UNSUPPORTED; +} + +static EFI_STATUS SetBrowserData( + IN UINTN BufferSize, IN VOID *Buffer, + IN CONST EFI_GUID *VarStoreGuid, OPTIONAL + IN CONST CHAR16 *VarStoreName OPTIONAL +){ + return EFI_UNSUPPORTED; +} + +HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol = { + LoadResources, LoadStrings, PublishPackages, + GetBrowserData, SetBrowserData, GetString, SetString +}; + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2010, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//**********************************************************************
\ No newline at end of file diff --git a/Core/CORE_DXE/FrameworkHii/HIIDB.c b/Core/CORE_DXE/FrameworkHii/HIIDB.c new file mode 100644 index 0000000..b4bfbfc --- /dev/null +++ b/Core/CORE_DXE/FrameworkHii/HIIDB.c @@ -0,0 +1,3511 @@ +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2005, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** + +//********************************************************************** +// $Header: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/HIIDB.c 5 2/10/10 5:08p Felixp $ +// +// $Revision: 5 $ +// +// $Date: 2/10/10 5:08p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Core/CORE_DXE/FrameworkHii/HIIDB.c $ +// +// 5 2/10/10 5:08p Felixp +// Bug fix in HiiExtGetFormInfo function. +// +// 4 2/10/10 3:43p Felixp +// x64 compiler warnings are fixed. +// +// 3 12/29/09 2:38p Yakovlevs +// Fixed issue with hanging in TSE big number of setup questions. +// Changed size of Length fields in some HII internal structures from +// UIN16 to UINTN. +// Code clenup (removed not used variables changes to compile with W4) +// +// 2 12/04/09 2:16p Yakovlevs +// 1.Fixed potential NULL pointer use in function NewFontPack() +// 2.Fixed inconsistancy in VarStore management (requires updated HiiDb.h) +// +// 1 10/09/09 6:10p Felixp +// +// 45 6/03/09 10:58a Yakovlevs +// if Hii->RemovePack is called reset global pointers to NULL since they +// might pointing at data that was freed. +// +// 44 10/01/08 1:01p Yakovlevs +// fixed bug in HiiExtGetFormLabels() function. +// +// 43 1/09/08 10:49a Yakovlevs +// +// 42 9/05/07 9:18p Felixp +// +// 41 9/05/07 5:59p Yakovlevs +// Bug fixes in UpdateForm and RemovePack routines. +// +// 2 6/28/07 5:16p Yakovlevs +// Fixed FormUpdate Protocol Function, and some other minor bug fixes. +// +// 39 5/23/07 4:32p Pavell +// Reindexing formsets +// +// 38 3/18/07 3:10p Felixp +// GetSecondaryLanguages fix: return EFI_NOT_FOUND when no languages found +// +// 37 3/12/07 6:06p Yakovlevs +// Fixed NewKbPack function. +// +// 36 3/12/07 1:46p Yakovlevs +// Handled a situation when there are no Keyboard Layout data in HII +// Database. +// +// 35 3/07/07 8:21p Yakovlevs +// Added GetKeyboardLayout function implamentation. +// +// 34 1/23/07 12:23p Yakovlevs +// +// 33 12/21/06 1:57p Felixp +// +// 32 12/20/06 10:37a Felixp +// +// 31 12/18/06 5:42p Pavell +// Added a fix for variable size determination +// 30 11/15/06 5:55p Yakovlevs +// +// 29 11/02/06 6:45p Yakovlevs +// Fixed HiiTestString NON_SPACING attribute handling +// +// 27 10/31/06 11:15a Yakovlevs +// HiiTestString fixed to skip none spacing characters. +// +// 25 10/30/06 6:09p Yakovlevs +// HII Spec v 0.92 updates +// +// 24 9/27/06 7:44p Felixp +// Improvement in GetHiiString: +// If string is not found for the current system language language, try +// with the package primary language. +// +// 23 9/26/06 9:03a Felixp +// Multilanguage Support. Do not use hard-coded glyphs. Load font file +// instead. +// +// 22 9/18/06 6:23p Felixp +// Bug fix in HiiGetString: buffer overrun when Raw is FALSE +// +// 21 8/24/06 10:11a Felixp +// x64 support: warning/error fixes +// +// 20 8/04/06 5:18p Felixp +// Bug fix in NewFontPack function (wide glyph handling). +// +// 19 7/24/06 11:46a Yakovlevs +// Hii->ExportDatabase support added. +// +// 18 3/13/06 5:30p Felixp +// +// 17 10/03/05 2:47p Markw +// Fixed uninitialized variables. +// +// 16 7/20/05 6:43p Felixp +// GlyphToBlt modifed to support wide characters +// +// 15 7/19/05 8:17p Felixp +// NewString modified to support update for all languages when three +// spaces Language provided +// +// 13 7/13/05 9:46p Felixp +// +// 12 6/24/05 2:03p Yakovlevs +// +// 11 6/23/05 5:43p Yakovlevs +// Fixed "Missing String" message +// +// 10 5/27/05 12:16p Felixp +// bug fix in HiiGetString +// +// 9 2/28/05 6:21p Yakovlevs +// Fixed DateTime and Object Conditions issue; +// +// 8 3/17/05 1:57p Felixp +// implementation of HiiNewPackNew updated +// +// 7 3/04/05 12:52p Felixp +// +// 6 3/04/05 9:23a Mandal +// + +//********************************************************************** +//<AMI_FHDR_START> +// +// Name: <This File Name> +// +// Description: +// +//<AMI_FHDR_END> +//********************************************************************** +// +// Module Name: HIIDB.C +// +// Abstract: This file contains implementation of HII Database Protocol. +// +#include <HiiDb.h> +#include <Protocol/DevicePath.h> +#include <Protocol/HiiUtilities.h> +extern UINT8 *UsStdNarrowGlyphData; +extern HII_UTILITIES_PROTOCOL HiiUtilitiesProtocol; + +//================================================================================== +// Some globals we need +//================================================================================== + +//------------------------------------------ +//Prototypes +EFI_STATUS InitPrivateData(EFI_HANDLE MyImgHandle); +EFI_STATUS CreateLabelObjects(HII_LABEL *Label); +//EFI_STATUS HiiNewPack (IN EFI_HII_PROTOCOL *This, +// IN EFI_HII_PACK_LIST *Package, +// OUT EFI_HII_HANDLE *Handle); + +//------------------------------------------ +//GUIDs +EFI_GUID gEfiHiiProtocolGuidOld = EFI_HII_OLD_PROTOCOL_GUID; +EFI_GUID gEfiHiiProtocolGuidNew = EFI_HII_NEW_PROTOCOL_GUID; +static EFI_GUID gEfiExtHiiProtocolGuid = EFI_HII_EXT_PROTOCOL_GUID; +//------------------------------------------ +//Data Vars + +//Define String Database Key fields +#define STR_KEY 0 +#define STR_KEY_CNT 1 +//it is going to be combined key +//Token->size16;LangIdx->size32;Handle->size16; total = 8 byte->UINT64 +//Token->Least Segnificant Field Handle Most Significant Field +//the resulting Index for StringToken->23, LangIndex->2, Hii Handle=1 will be +// Handle|LangIdx |Token +// 0x0001|00000002|0023 -> easy to sort easy to find +static DBE_OFFSET_KEY_CONTEXT gStrOffsetInfo = {EFI_FIELD_OFFSET(HII_STR ,Token), 8 }; +static DBE_KEY_FIELD gStrKey=OFFSET_KEY(gStrOffsetInfo); + +//Any Language Printable string +static UINT16 gAnyLang[]=L"Any Language"; +//HII DATABASE global var +static HII_DB gHiiDb; + +/////////////////////////////////////////////////////////////////// +//in order to save some time when LocateHandle routine been called +//I have decide to save Current HandleInfo structure pionter +//here rather than locate it every time +static HII_HANDLE *mCurHnd=NULL; +static HII_LANG *mCurLang=NULL; +static UINTN mCurHid=0, mCurLid=0; + +/////////////////////////////////////////////////////////////////// +//in order to save some time when HiiGetLine routine been called +//I have decide to save Current StringInfo structure pionter +//here rather than locate it every time HiiGetLine been called +static HII_STR *mCurStr=NULL; + +/////////////////////////////////////////////////////////////////// +// save the varstore context based on the formset +static UINT16 CurrentVarId = 0; + +//================================================================================== +// Entry Point +//================================================================================== +//********************************************************************** +//<AMI_PHDR_START> +// +// Procedure: HiiDbEntryPoint() +// +// Description: Initialize HII Database (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) +// +// Input: EFI_HANDLE ImageHandle This Driver Image Handle. +// EFI_SYSTEM_TABLE *SystemTable Pointer to the EFI System Table +// +// Output: EFI_STATUS EFI_SUCCESS - Driver Loadded. +// Other - Driver Error +// +//<AMI_PHDR_END> +//********************************************************************** + +EFI_STATUS HiiDbEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){ + EFI_STATUS Status=0; + UINTN hCnt; + EFI_HANDLE *hBuf; +//----------------------------------- + InitAmiLib(ImageHandle, SystemTable); + + //Only one HII Driver has to be in the system + Status=pBS->LocateHandleBuffer(ByProtocol, &gEfiHiiProtocolGuidOld, NULL, &hCnt, &hBuf); + + //If there was no error, report that we has been already started + if (!EFI_ERROR(Status)) { + if (!hBuf)pBS->FreePool(hBuf); //Don't forget to free the memory + return EFI_ALREADY_STARTED; + } + + Status=InitPrivateData(ImageHandle); + if(EFI_ERROR(Status)) return Status; + + Status = pBS->InstallMultipleProtocolInterfaces(&gHiiDb.HiiHandle, + &gEfiHiiProtocolGuidOld,&gHiiDb.HiiProtocolOld, + &gEfiHiiProtocolGuidNew,&gHiiDb.HiiProtocolNew, + &gEfiExtHiiProtocolGuid,&gHiiDb.HiiExtProtocol, + &gHiiUtilitiesProtocolGuid, &HiiUtilitiesProtocol, + NULL); + return Status; +} + +/////////////////////////////////////////////////////////////////// +// Common Worker Functions +/////////////////////////////////////////////////////////////////// +//************************************************************************* +//<AMI_PHDR_START> +// +// Name: GetDefaultLang +// +// Description: +// EFI_STATUS GetDefaultLang(OUT CHAR16 *DefaultLang) returns the default +// system language in the string specified by DefaultLang. +// +// Input: +// OUT CHAR16 *DefaultLang +// Pointer to the null-terminated Unicode string. +// +// Output: +// EFI_NOT_FOUND, if the default language could not be found. +// Otherwise, EFI_SUCCESS. +// +// Modified: +// +// Referrals: +// +// Notes: +// +//<AMI_PHDR_END> +//************************************************************************* +//Get System Default Language +EFI_STATUS GetDefaultLang(CHAR16 *DefaultLang){ + EFI_GUID EfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; + EFI_STATUS Status=0; + UINT8 al[3]; + UINTN i=sizeof(al); +//----------------------- + Status=pRS->GetVariable(L"Lang",&EfiGlobalVariableGuid,NULL,&i,al); + if (EFI_ERROR(Status)) return Status; + + for(i=0; i<sizeof(al) ;i++) DefaultLang[i]=al[i]; + DefaultLang[sizeof(al)]=0; + return Status; +} + +//----------------------------------------------------------------- +//This Function will look in Item List and try to find mutch for Item of Size. +//if it finds it will return Pointer to the matching Item and update Index if not - NULL +EFI_STATUS LocateItem(T_ITEM_LIST *ItemLst, VOID *Item, UINTN Size, OUT UINTN *Index){ + UINTN i; +//----------------- + for(i=0; i<ItemLst->ItemCount; i++){ + if(!MemCmp(ItemLst->Items[i],Item,Size)) { + if(Index)*Index=i; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +/////////////////////////////////////////////////////////////////// +//Will return Lenth of the screen representation of Str with respect +//of wide narrow and non spacing glyphs it using +//Len excluding '0' char (\n) +UINT16 GetScrLen(CHAR16 *Str, UINT16 Len){ + UINTN i; + UINT16 u,sl=0; + HII_N_FONT *fnt; +//-------------------------------------- + for(i=0;i<Len;i++){ + u=Str[i]; + if(u<0x20 || u>=0xfff0)continue; + fnt=gHiiDb.FontDb[u]; + if(fnt){ + if(fnt->Attr & GLYPH_NON_SPACING) continue; + if(fnt->Attr & GLYPH_WIDE) sl+=2; + else sl++; + } else sl++; //we will print empty rect for non existent glyph + } + return sl; +} + +/////////////////////////////////////////////////////////////////// +//Will allocate Mem for the length of the string and Copy "Str" there +UINT16* StrAlloc(UINT16 *Str,UINT16 *StrLen OPTIONAL, UINT16 *ScrLen OPTIONAL){ + UINT16 len; + UINT16 *str; +//------------------------------------- + len=(UINT16)Wcslen(Str);//terminator not included + str=(UINT16*)Malloc((len+1)*sizeof(UINT16)); + if(!str)return NULL; + Wcscpy(str,Str); + if(StrLen)*StrLen=len+1; + if(ScrLen)*ScrLen=GetScrLen(Str,len); + return str; +} + +/////////////////////////////////////////////////////////////////// +//This will Change Language Attributes +//VOID SetLangAttr(UINTN Index, UINT32 Attr){ +// HII_LANG *lang; +//-------------------- +// lang=(HII_LANG*)gHiiDb.LangDb.ResDsc[Index]; +// lang->Attr=Attr; +//} + +/////////////////////////////////////////////////////////////////// +//this will find and return HII_LANG "Index", +//if "Language" is stored In Hii Handle Database +HII_LANG* LocateLang(UINT16 *Language, UINTN *Index){ + EFI_STATUS Status; + UINTN idx; +//------------------------ + if( !mCurLang || MemCmp(&mCurLang->sName[0],Language,sizeof(mCurLang->sName)) ) + { + Status=LocateItem(&gHiiDb.LangDb,Language,sizeof(UINT16)*4,&idx); + if(EFI_ERROR(Status)){ + mCurLang=NULL; //flush Language Cache + mCurLid=0; //make index to generate exception if used + } else { + mCurLang=gHiiDb.LangDb.Items[idx]; + mCurLid=idx; + } + } + if(mCurLang && Index)*Index=mCurLid; + return mCurLang; +} + +HII_HANDLE *LocateHandleGuid(EFI_GUID *Guid, UINTN *Index){ + HII_HANDLE *phnd=NULL; + UINTN i; +//------------------------------- + for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){ + phnd=gHiiDb.HandleDb.Items[i]; + if(!MemCmp(&phnd->Guid,Guid,sizeof(EFI_GUID)))break; + else phnd=NULL; + } + if(phnd && Index)*Index=i; + return phnd; +} + +/////////////////////////////////////////////////////////////////// +//This function will Locate another Handle with the same Guid as +//passed Handle. +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//This function is Obsolete but I need it for compliance with Intel's +//Setup because they using same guid more than once per Ifr and Strings pare. +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +VOID LocateSameGuidHandle(UINTN CurIdx, UINTN *IdxBuffer, UINTN *IdxCount){ + HII_HANDLE *phnd=NULL,*chnd=gHiiDb.HandleDb.Items[CurIdx]; + UINTN i, c=0; +//---------------------------- + for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){ + if(i==CurIdx) continue; + phnd=gHiiDb.HandleDb.Items[i]; + if(!MemCmp(&phnd->Guid,&chnd->Guid,sizeof(EFI_GUID))){ + IdxBuffer[c]=i; + c++; + }else phnd=NULL; + } + *IdxCount=c; +} + +/////////////////////////////////////////////////////////////////// +//if on passed handle in any string function there are no +//strings associated with we need to find another handle with +//the same guid having strings on it +HII_HANDLE *LocateStrHandleGuid(UINTN CurIdx, UINTN *Index){ + HII_HANDLE *phnd=NULL,*chnd=gHiiDb.HandleDb.Items[CurIdx]; + UINTN i; +//---------------------------- + for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){ + if(i==CurIdx) continue; + phnd=gHiiDb.HandleDb.Items[i]; + if(!MemCmp(&phnd->Guid,&chnd->Guid,sizeof(EFI_GUID)) && phnd->HasStr){ + if(Index)*Index=i; + break; + }else phnd=NULL; + } + return phnd; +} + +/////////////////////////////////////////////////////////////////// +//this will find and return HII_HANDLE "Index", +//if "Handle" is stored In Hii Handle Database +static HII_HANDLE* LocateHandle(EFI_HII_HANDLE Handle, UINTN *Index){ + EFI_STATUS Status; + UINTN idx; +//------------------------ + if((!mCurHnd) || (mCurHnd->Handle!=Handle)){ + Status=LocateItem(&gHiiDb.HandleDb,&Handle,sizeof(EFI_HII_HANDLE),&idx); + if(EFI_ERROR(Status)){ + mCurHnd=NULL; //flush Handle Cache + mCurHid=-1; //make index to generate exception if used + } else { + mCurHnd=gHiiDb.HandleDb.Items[idx]; + mCurHid=idx; + } + } + if(mCurHnd && Index)*Index=mCurHid; + return mCurHnd; +} + +/////////////////////////////////////////////////////////////////// +//this will find and return HII_HANDLE "Index", +//if "Handle" is stored in Handle Database +//or Append Handle Database with this Handle if not and return a new "Index" +EFI_STATUS LocateHandleAdd(EFI_HII_HANDLE Handle, EFI_GUID *GuidId, UINTN *Index){ + EFI_STATUS Status=0; + HII_HANDLE *phnd; +//---------------- + phnd=LocateHandle(Handle,Index); + if(!phnd){ + phnd=MallocZ(sizeof(HII_HANDLE)); + if(!phnd)return EFI_OUT_OF_RESOURCES; + pBS->CopyMem(&phnd->Guid,GuidId,sizeof(EFI_GUID)); + phnd->Handle=Handle; + Status=AppendItemLst(&gHiiDb.HandleDb,phnd); + if(EFI_ERROR(Status)) return Status; + *Index=gHiiDb.HandleDb.ItemCount-1; + } + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +//this will find and return HII_LANG "Index", +//if "Language" is stored in Handle Database +//or Append Handle Database with this Handle if not and return a new "Index" +EFI_STATUS LocateLangAdd(UINT16 *Language, UINT16 *PrintLanguage, UINTN *Index){ + EFI_STATUS Status; + HII_LANG *lang; +//------------------ + //Check if we have the Language installed already + lang=LocateLang(Language,Index); + if(!lang){ + lang=MallocZ(sizeof(HII_LANG)); + if(!lang)return EFI_OUT_OF_RESOURCES; + pBS->CopyMem(&lang->sName,Language,sizeof(UINT16)*4); + if(PrintLanguage){ + lang->lName=StrAlloc(PrintLanguage,NULL,NULL); + if(!lang->lName) return EFI_OUT_OF_RESOURCES; + } + Status=AppendItemLst(&gHiiDb.LangDb,lang); + if(EFI_ERROR(Status)) return Status; + if(Index)*Index=gHiiDb.LangDb.ItemCount-1; + } + return EFI_SUCCESS; +} + + +/////////////////////////////////////////////////////////////////// +//This will check if Lang Index is present in Secondary Lang List +//on this Handle +/////////////////////////////////////////////////////////////////// +EFI_STATUS LocateSecLangAdd(HII_HANDLE *Hnd, UINTN *SecLangIdx, BOOLEAN AddIt){ + UINTN i; +//------------------------------ + for(i=0; i<Hnd->SecLang.ItemCount; i++){ + if(*SecLangIdx==(UINTN)(Hnd->SecLang.Items[i])) return EFI_SUCCESS; + } + if(AddIt)return AppendItemLst(&Hnd->SecLang,(VOID*)(*SecLangIdx)); + else return EFI_NOT_FOUND; +} + + +/////////////////////////////////////////////////////////////////// +//================================================================= +//HII Database Protocol Functions +//================================================================= +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// Font related +/////////////////////////////////////////////////////////////////// +EFI_STATUS NewFontPack(IN EFI_HII_FONT_PACK *Package) +{ + UINTN i; + UINT16 u; + EFI_NARROW_GLYPH *ng; + EFI_WIDE_GLYPH *wg; +//-------------------------- + + //Set Pointer to the beginning of Package Data. + ng=(EFI_NARROW_GLYPH*)(Package+1); + + if(Package->NumberOfNarrowGlyphs){ + HII_N_FONT *fnt; + //--------------------------- + //Allocate Space for Number of Narrow Glyphs + fnt=(HII_N_FONT*)Malloc(sizeof(HII_N_FONT)*Package->NumberOfNarrowGlyphs); + if(!fnt)return EFI_OUT_OF_RESOURCES; + + for(i=0; i<Package->NumberOfNarrowGlyphs; i++){ + u=ng[i].UnicodeWeight; +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + //we will populate only empty spots in FontD or oposite +//made SDL token for that + if(!gHiiDb.FontDb[u]){ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + //fnt=(HII_FONT*)Malloc(sizeof(HII_FONT)); + pBS->CopyMem((VOID*)&fnt[i], &ng[i].Attributes,sizeof(HII_N_FONT)); + gHiiDb.FontDb[u]=&fnt[i]; + } + } + } + + + if(Package->NumberOfWideGlyphs){ + UINTN j,k; + HII_W_FONT *fnt; + //--------------- + //Allocate Space for Number of Wide Glyphs + wg=(EFI_WIDE_GLYPH*)(ng+Package->NumberOfNarrowGlyphs); + fnt=(HII_W_FONT*)Malloc((sizeof(HII_W_FONT))*Package->NumberOfWideGlyphs); + if(!fnt)return EFI_OUT_OF_RESOURCES; + + for(i=0; i<Package->NumberOfWideGlyphs; i++){ + u=wg[i].UnicodeWeight; + if(!gHiiDb.FontDb[u]){ + fnt[i].Attr=wg[i].Attributes; + for(j=0,k=0; j<NG_SIZE;j++, k+=2){ + fnt[i].GlData[k]=wg[i].GlyphCol1[j]; + fnt[i].GlData[k+1]=wg[i].GlyphCol2[j]; + } + gHiiDb.FontDb[u]=(HII_N_FONT*)&fnt[i]; + } + } + } + return EFI_SUCCESS; +} + + + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiTestString(IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize) +{ + EFI_STATUS Status=0; + UINT32 i; + UINT32 bs=0; + HII_N_FONT *fnt; +//------------------------------ + if(!This) return EFI_INVALID_PARAMETER; + if ((!FirstMissing)||(!StringToTest)||(!GlyphBufferSize)) return EFI_INVALID_PARAMETER; + + i=*FirstMissing; + while (StringToTest[i]!=0){ + fnt=gHiiDb.FontDb[ StringToTest[i] ]; + if(fnt){ + if(fnt->Attr& GLYPH_NON_SPACING ){ + i++; + continue; + } + if(fnt->Attr&GLYPH_WIDE) bs+=WG_SIZE; + else bs+=NG_SIZE; + i++; + } else { + Status=EFI_NOT_FOUND; + break; + } + } + *FirstMissing=i; + *GlyphBufferSize=bs; + return Status; +} + +static UINT8 gGE[NG_SIZE]= + {0x00,0x00,0x00,0x7E,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x7E,0x00,0x00,0x00};// \ +// 0x00,0x00,0x00,0x7E,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x7E,0x00,0x00,0x00}; + +static EFI_WIDE_GLYPH gGB; +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetGlyph(IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus) +{ + UINTN i, bs=NG_SIZE; + HII_N_FONT *fnt;//=gHiiDb.FontDb[Source[j]]; +// HII_GL_COL *gc1=NULL, *gc2=NULL; +// BOOLEAN w=FALSE; +//------------------------------------------ + if(!This) return EFI_INVALID_PARAMETER; + + if((!GlyphBuffer)||(!Index)||(!Source)||(!BitWidth)) return EFI_INVALID_PARAMETER; + fnt=gHiiDb.FontDb[Source[*Index]]; + + if(!fnt) { + if(InternalStatus)*InternalStatus=(UINT32)-1; + //If after calling TestString somebody will call us with invalid Unicode Char + pBS->CopyMem(&gGB.GlyphCol1[0],&gGE, NG_SIZE); + *BitWidth=GLYPH_W; + *GlyphBuffer=(UINT8*)&gGB; + (*Index)++; + return EFI_NOT_FOUND; + } + + //first char must not be the non-spacing character + if(fnt->Attr&GLYPH_NON_SPACING) return EFI_INVALID_PARAMETER; + + if(fnt->Attr&GLYPH_WIDE){ + *BitWidth=GLYPH_W*2; + bs=WG_SIZE; + } else *BitWidth=GLYPH_W; + + pBS->SetMem(&gGB,sizeof(EFI_WIDE_GLYPH),0); + do{ + fnt=gHiiDb.FontDb[Source[*Index]]; + for(i=0;i<bs;i++) gGB.GlyphCol1[i]|=fnt->GlData[i]; + (*Index)++; + } while(fnt->Attr&GLYPH_NON_SPACING); + *GlyphBuffer=(UINT8*)&gGB; + if(InternalStatus)*InternalStatus=0; + + return EFI_SUCCESS; +} + + +/////////////////////////////////////////////////////////////////// +//!!!! this function suppose to take care of thing with mixed size gpyphs +EFI_STATUS HiiGlyphToBlt(IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_UGA_PIXEL Foreground, + IN EFI_UGA_PIXEL Background, + IN UINTN Count,//Number of NARROW Glyps left in BltBuffer + //or count from the end of the buffer in terms of NARROW glyphs + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_UGA_PIXEL *BltBuffer) +{ +// UINTN x,y;//,i,o; +// UINT8 k = Width > GLYPH_W ? 2 : 1; +//------------------------------------ +// if(!This) return EFI_INVALID_PARAMETER; +// if( !(Width==GLYPH_W || Width==(GLYPH_W*2)) || Height!=GLYPH_H )return EFI_INVALID_PARAMETER; +/* for (y=0,o=0; y<Height; y++){ + for(i=0; i<Width/GLYPH_W; i++){ + for (x=0; x<GLYPH_W; x++){ + if ( GlyphBuffer[y*k+i] & (0x80 >> x)) BltBuffer[y*GLYPH_W*Count+x+o]=Foreground; + else BltBuffer[y*GLYPH_W*Count+x+o]=Background; + } + o=GLYPH_W; + } + } + + return EFI_SUCCESS; + UINTN X; + UINTN Y; +*/ + UINT8 Mask; + UINTN Index, Line, Part; + UINTN TotalParts = Width/GLYPH_W; + EFI_NARROW_GLYPH *Glyph = (EFI_NARROW_GLYPH *)GlyphBuffer; + if(!This) return EFI_INVALID_PARAMETER; + if( !(Width==GLYPH_W || Width==GLYPH_W*2) || Height!=GLYPH_H || Count<TotalParts)return EFI_INVALID_PARAMETER; + for (Line = 0, Index=0; Line < Height; Line++, Index+=GLYPH_W * (Count-TotalParts)) { + for(Part=0; Part<TotalParts; Part++){ + for (Mask = 0x80; Mask > 0; Mask>>=1, Index++) { + if (Glyph->GlyphCol1[Line*TotalParts+Part] & Mask) + BltBuffer[Index] = Foreground; + else + BltBuffer[Index] = Background; + } + } + } +/*/// + BltBuffer[Index] = (Glyph->GlyphCol1[y] & (1 << x)) ? Foreground : Background; + if (Width > GLYPH_W) + BltBuffer[Index+GLYPH_W] = (Glyph->GlyphCol1[GLYPH_H+y] & (1 << x)) ? Foreground : Background; +/// + EFI_NARROW_GLYPH *Glyph = (EFI_NARROW_GLYPH *)GlyphBuffer; + for (y = 0; y < Height; y++) { + for (x = 0; x < GLYPH_W; x++) { + UINTN Index = y * GLYPH_W * Count + (GLYPH_W - x - 1); + for(i=0; i<Width/GLYPH_W; i++) + if ((Glyph->GlyphCol1[i*GLYPH_H+y] & (1 << x)) != 0) + BltBuffer[Index+GLYPH_W*i] = Foreground; + else + BltBuffer[Index+GLYPH_W*i] = Background; + } + }*/ + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +// String related +/////////////////////////////////////////////////////////////////// +HII_STR *LocateString(HII_HANDLE *PHnd, UINTN LangIdx, STRING_REF Token/*, UINTN HandleIdx OPTIONAL*/){ + UINTN li=LangIdx, j; + HII_STR sd = {0,0,0,0,NULL}; + INT8 v; + VOID **cs; +//----------------- + //if CurrentString must be refreshed + if(!mCurStr || mCurStr->LangIdx!=LangIdx || mCurStr->Token!=Token || mCurStr->Handle!=PHnd->Handle) + { + + //--------------------- + do { + sd.Handle=PHnd->Handle; + sd.LangIdx=(UINT32)li; + sd.Token=Token; + + DbeLocateKey(&gHiiDb.StringDb,STR_KEY,(VOID*)&sd,(VOID**)&cs,&v,&j); + + if(v)mCurStr=NULL; + else { + mCurStr=(HII_STR*)(*cs); + break; + } + + //if we were looking for any language and failed + //just get Primary Package Language + if(!li)li=PHnd->PriLang; + else break; + } while(v); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this patch was made to keep compatibility with Intel's implemntation +//of BDS - DevicerManagerVfrBin and FrontPageVfrBin uses the same Guid +//and Same String Pack expecting valid strings on from one StringPack +//when passing different GUIDs????????? +/* if(!mCurStr){ + HII_HANDLE *phnd; + UINTN i,sgib[10]={0,0,0,0,0,0,0,0,0,0};//same GUID index Buffer + //---------------------------------- + LocateSameGuidHandle(HandleIdx,&sgib[0],&c); + for(i=0; i<c;i++){ + li=LangIdx; + phnd=gHiiDb.HandleDb.Items[sgib[i]]; + do { + sd.Handle=phnd->Handle; + sd.LangIdx=(UINT32)li; + sd.Token=Token; + + DbeLocateKey(&gHiiDb.StringDb,STR_KEY,(VOID*)&sd,(VOID**)&cs,&v,&j); + + if(v)mCurStr=NULL; + else { + mCurStr=(HII_STR*)(*cs); + break; + } + //if we were looking for any language and faild + //just get Primary Package Language + if(!li)li=PHnd->PriLang; + else break; + } while(v); + if(mCurStr)break; + } + } +*/ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + } + return mCurStr; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS ReplaceString(HII_STR *StrData, UINT16 *Replacement) +{ + UINT16 *str; + UINT16 len,slen; +//----------------------------- + str=StrAlloc(Replacement, &len, &slen); + if(!str)return EFI_OUT_OF_RESOURCES; + + if(StrData->NewStr.StrPtr)pBS->FreePool(StrData->NewStr.StrPtr); + + StrData->NewStr.StrLen=len; + StrData->NewStr.ScrLen=slen; + StrData->NewStr.StrPtr=str; + + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS AddString(UINTN LangIdx, HII_HANDLE *PHandle, UINT16 *String, BOOLEAN Initial, STRING_REF *Token) +{ + HII_STR *str; +//------------------------------------- + str=MallocZ(sizeof(HII_STR)); + if(!str) return EFI_OUT_OF_RESOURCES; + + if(Initial){ + str->String.StrPtr=StrAlloc(String,&str->String.StrLen,&str->String.ScrLen); + if(!(str->String.StrPtr))return EFI_OUT_OF_RESOURCES; + } else { + str->NewStr.StrPtr=StrAlloc(String,&str->NewStr.StrLen, &str->NewStr.ScrLen); + if(!(str->NewStr.StrPtr))return EFI_OUT_OF_RESOURCES; + } + + str->LangIdx=(UINT32)LangIdx; + //if Token is provided, use it. Otherwise assign new one. + if (Token && *Token) str->Token=*Token; + else + { + str->Token=PHandle->NextStrToken; + PHandle->NextStrToken++; + if (Token) *Token = str->Token; + } + str->Handle=PHandle->Handle; + + return DbeInsert(&gHiiDb.StringDb,(VOID*)str); +} + +EFI_STATUS UpdateString(IN UINTN li, + IN HII_HANDLE *phnd, + IN STRING_REF *Reference, + IN CHAR16 *NewString) +{ + EFI_STATUS Status; + //Check if String with this Token# already present in String Db + if((*Reference)==0){ + Status=AddString(li,phnd,NewString,FALSE,Reference); + if(EFI_ERROR(Status)) return Status; + } else { + HII_STR *str; + if (*Reference >= phnd->NextStrToken) return EFI_INVALID_PARAMETER; + str=LocateString(phnd,li,*Reference); + //if str is NULL, it means that string with this token has been created + //for a different language + Status= (str) ? ReplaceString(str,NewString) : AddString(li,phnd,NewString,FALSE,Reference); + } + return Status; + +} +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiNewString(IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN STRING_REF *Reference, + IN CHAR16 *NewString) +{ + UINTN li=0, hi=0; + HII_LANG *lang; + HII_HANDLE *phnd; + EFI_STATUS Status=0; + UINT16 dl[4]={0x20,0x20,0x20,0}, *pdl;//Any Lang +//------------------------------- + if(!This || !Reference || !NewString) return EFI_INVALID_PARAMETER; + //first Check if the Handle is valid. + phnd=LocateHandle(Handle,&hi); + if(!phnd) return EFI_INVALID_PARAMETER; + + if(!phnd->HasStr){ + phnd=LocateStrHandleGuid(hi,&hi); + if(!phnd) return EFI_INVALID_PARAMETER; + } + + if(!Language){ + pdl=&dl[0]; + if(EFI_ERROR( GetDefaultLang(pdl))){ + pdl=(UINT16*)gHiiDb.LangDb.Items[phnd->PriLang]; + } + } else pdl=Language; + + //dl has a language string "xxx" + lang=LocateLang(pdl,&li); + + if (!li) + {//language index 0 referes to language " ", which means we have to update + //string for all languages + //update string for primary language + Status = UpdateString(phnd->PriLang,phnd,Reference,NewString); + //update string for all secondary languages + for(li=0; !EFI_ERROR(Status) && li<phnd->SecLang.ItemCount; li++) + Status = UpdateString((UINTN)phnd->SecLang.Items[li],phnd,Reference,NewString); + return Status; + } + + if(!lang) return EFI_INVALID_PARAMETER; + + //If language is valid but not mutch Pack PriLang + if(phnd->PriLang!=li){ + Status=LocateSecLangAdd(phnd,&li,FALSE); + if(EFI_ERROR(Status))li=phnd->PriLang; + //lang=(HII_LANG*)gHiiDb.LangDb.Items[li]; + } + return UpdateString(li,phnd,Reference,NewString); +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS GetLanguageFromPack(EFI_HII_STRING_PACK *Pack, UINTN *LangIndex){ + UINT16 *sn, *ln; + UINT8 *ofs=(UINT8*)Pack;//(Pack+1); +//------------------------- + sn=(UINT16*)(ofs+Pack->LanguageNameString); + ln=(UINT16*)(ofs+Pack->PrintableLanguageName); + return LocateLangAdd(sn,ln,LangIndex); +} + +/////////////////////////////////////////////////////////////////// +BOOLEAN IsLastStrPack(EFI_HII_STRING_PACK *Pack){ + if(Pack->Header.Type==EFI_HII_STRING && + Pack->Header.Length == 0 && Pack->Attributes == 0 && + Pack->LanguageNameString == 0 && Pack->NumStringPointers == 0 && + Pack->PrintableLanguageName == 0 ) return TRUE; + return FALSE; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetPrimaryLanguage(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString) +{ + HII_HANDLE *phnd; + HII_LANG *lang; + UINTN hi; + UINT16 *ls,*bp; +//---------------------- + if(!This || !LanguageString) return EFI_INVALID_PARAMETER; + + phnd=LocateHandle(Handle,&hi); + if(!phnd) return EFI_INVALID_PARAMETER; + if(!phnd->HasStr){ + phnd=LocateStrHandleGuid(hi,&hi); + if(!phnd) return EFI_INVALID_PARAMETER; + } +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//??????????????????????????????????????? + //if for some reson Somebody submit just IFR vith no Strings + //there are no way to determine language so I just put there 0 -Any Language + //but Intel's code expect me to return something like "eng" + //so I will return Default System Lang. +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + ls=Malloc(sizeof(UINT16)*3*(phnd->SecLang.ItemCount+1)+1); //4 characters + if(!ls) return EFI_OUT_OF_RESOURCES; + + bp=ls; + lang=gHiiDb.LangDb.Items[phnd->PriLang]; + pBS->CopyMem(ls,&lang->sName,sizeof(UINT16)*3); + bp+=3; + + for(hi=0;hi<phnd->SecLang.ItemCount; hi++){ + lang=gHiiDb.LangDb.Items[(UINTN)phnd->SecLang.Items[hi]]; + pBS->CopyMem(bp,&lang->sName,sizeof(UINT16)*3); + bp+=3; + } + *bp=0; + *LanguageString=ls; + + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +// +EFI_STATUS HiiGetSecondaryLanguages(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString) +{ + UINTN id,i; + HII_HANDLE *phnd; + HII_LANG *lang; + UINT16 *ls; +//---------------------- + if(!This) return EFI_INVALID_PARAMETER; + + phnd=LocateHandle(Handle,NULL); + if(!phnd) return EFI_INVALID_PARAMETER; + + //Some how caller managed to scrue up with parameters. + lang=LocateLang(PrimaryLanguage,&id);//Lang provided does not mutch with what we've recorded + if( !lang || phnd->PriLang!=id ) return EFI_INVALID_PARAMETER; + + if(phnd->SecLang.ItemCount>0){ + UINT16 *l; + //---------------- + ls=Malloc(sizeof(UINT16)*3*phnd->SecLang.ItemCount+1); + if(!ls) return EFI_OUT_OF_RESOURCES; + l=ls; + for(i=0; i<phnd->SecLang.ItemCount; i++){ + //we are not returning Any Language str " " + //And Any Lang String has index 0 upon initialization + if((UINTN)(phnd->SecLang.Items[i])){ + lang=(HII_LANG*)gHiiDb.LangDb.Items[(UINTN)(phnd->SecLang.Items[i])]; + pBS->CopyMem(l,&lang->sName[0],sizeof(UINT16)*3);//4 unicode chars; + l+=3; + } + }//resulting string will be consist of N*3xUINT16+TERMINATOR + *l=0x0000; //put terminator at the end of set of sec lang + *LanguageString=ls; + }else { *LanguageString=NULL; return EFI_NOT_FOUND;} + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +//This is a worker function to avoid dubliceted code in HiiGetString, +//HiiGetLine and ExtHiiGetStrInfo +HII_STR *GetHiiString(EFI_HII_HANDLE Handle, UINT16 *Lang, STRING_REF Token){ + UINTN li,hi; + UINT16 dl[4]={0x20,0x20,0x20,0}, *pdl; + HII_HANDLE *phnd; + HII_STR *str; +//------------------------------ + phnd=LocateHandle(Handle,&hi); + if(!phnd) return NULL; + + if(!phnd->HasStr){ + phnd=LocateStrHandleGuid(hi,&hi); + if(!phnd) return NULL; + } + + if(!Lang){ + pdl=&dl[0]; + if(EFI_ERROR(GetDefaultLang(pdl)))pdl=(UINT16*)gHiiDb.LangDb.Items[phnd->PriLang]; + } else pdl=Lang; + + //dl has a language string it " " or "xxx" + //lang=LocateLang(pdl,&li); + if(!LocateLang(pdl,&li)) return NULL; + str=LocateString(phnd,li,Token); + + // If String is not found and language is not specified, + // let's try with the primary package language. + if (!str && !Lang) str=LocateString(phnd,0,Token); + + return str; +} + + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetStringNew(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLength, //in units of UINT16 + OUT EFI_STRING StringBuffer) +{ + HII_STR *str; + UINTN j,i; + UINT16 *ps, sl; +//-------------------------- + + if( !This || !BufferLength || *BufferLength && !StringBuffer ) return EFI_INVALID_PARAMETER; + + str=GetHiiString(Handle,LanguageString,Token); + if(!str) return EFI_INVALID_PARAMETER; + + if(str->NewStr.StrPtr){ + ps=str->NewStr.StrPtr; + sl=str->NewStr.StrLen; + } else { + ps=str->String.StrPtr; + sl=str->String.StrLen; + } + //str->StrLen in UINT16 units + if(*BufferLength<sl*sizeof(UINT16)) { + *BufferLength=sl*sizeof(UINT16); + return EFI_BUFFER_TOO_SMALL; + } + + if(Raw){ + pBS->CopyMem(&StringBuffer[0],ps,sl*sizeof(UINT16)); + *BufferLength=sl*sizeof(UINT16); + } else { + for(i=0,j=0;i<(UINTN)(sl-1);i++){ + //replace <CR> with <Space> + //if(ps[i]==0x0013) + // StringBuffer[j]=0x0020; + //else { + //skip all Special and Control Characters. + if((ps[i]>=0xFFF0 && ps[i]<=0xFFFF)) +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//It is amazing how Intel's engineers not in compliance with +//their own Specs. +//"If (Raw) TRUE, the string is returned unedited in the internal storage format described +//above. If FALSE, the string returned is edited by replacing !!<cr>!! with <space> and by +//removing special characters such as the ??<wide>?? prefix." +// ||(ps[i]>=0x0000 && ps[i]<=0x001F)) +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + continue; + //Copy the rest of chars + else StringBuffer[j]=ps[i]; + //} + j++; + } + StringBuffer[j]=0;//Terminate String!! + *BufferLength=(UINT16)((j+1)*sizeof(UINT16)); + } + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetStringOld(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, //in units of UINT16 + OUT EFI_STRING StringBuffer) +{ + EFI_STATUS Status; + UINTN bl; +//----------------- + if(BufferLength==NULL) return EFI_INVALID_PARAMETER; + + bl=(UINTN)(*BufferLength); + Status=HiiGetStringNew(This,Handle,Token,Raw,LanguageString,&bl,StringBuffer); + (*BufferLength)=(UINT16)bl; + + if((Status==EFI_BUFFER_TOO_SMALL) && (bl > 0xFFFF)) Status=EFI_INVALID_PARAMETER; + + return Status; +} + + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetLine(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer) +{ + HII_STR *str; + UINTN j,i; + UINT16 *ps, sl; + BOOLEAN cr=FALSE; +//-------------------------- + + if( !This || !BufferLength || !StringBuffer ) return EFI_INVALID_PARAMETER; + + str=GetHiiString(Handle,LanguageString,Token); + if(!str) return EFI_INVALID_PARAMETER; + + if(str->NewStr.StrPtr){ + ps=str->NewStr.StrPtr; + sl=str->NewStr.StrLen; + } else { + ps=str->String.StrPtr; + sl=str->String.StrLen; + } + + //I don't know should I remove a special chars or not + // So I will for now + for(j=0,i=*Index; (i<sl || i<LineWidth); i++ ){ + //replace <CR> with <Space> + if(ps[i]==0x0013){ + if(cr) { //if <CR> hit second time in a row - terminate string + StringBuffer[j]=0x0000; + *Index=(UINT16)i; + break; + } else { //else replece it with space an set "cr" flag + StringBuffer[j]=0x0020; + cr=TRUE; + } + }else{ + cr=FALSE; //if we here - reset "cr" flarg + //skip all Special and Control Characters. + if((ps[i]>=0xFFF0 && ps[i]<=0xFFFF)||(ps[i]<=0x001F)) + continue; //will not increase "j" the buffer index + //Copy the rest of chars into the Buffer + else + StringBuffer[j]=ps[i]; + } + j++; + } + StringBuffer[j]=0;//Terminate String!! + *BufferLength=(UINT16)((j+1)*sizeof(UINT16)); + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiResetStrings(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle) +{ + HII_STR *str; + UINTN i,hi;//,j,gbi[10],gc=0; + HII_HANDLE *phnd; +//------------------------ + + if(!This) return EFI_INVALID_PARAMETER; + phnd=LocateHandle(Handle,&hi); + if(!phnd) return EFI_INVALID_PARAMETER; + + if(!phnd->HasStr){ + phnd=LocateStrHandleGuid(hi,&hi); + if(!phnd) return EFI_INVALID_PARAMETER; + } + //LocateSameGuidHandle(hi, &gbi[0], &gc); + + //for(j=0; j<=gc; j++){ + for(i=0; i<gHiiDb.StringDb.RecordCount;i++){ + //if(!phnd->HasStr) break; + DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,i,&str); + if(str->Handle==phnd->Handle){ + if(str->NewStr.StrPtr){ + pBS->FreePool(str->NewStr.StrPtr); + str->NewStr.StrPtr=NULL; + str->NewStr.StrLen=0; + str->NewStr.ScrLen=0; + //Cleanup Dtabase from RECORDS which was addes + //after initial Package + if(!str->String.StrPtr){ + DbeDelete(&gHiiDb.StringDb, str, TRUE); + i--;//we ned to step on the same data index + continue; + //since we have delited current one + //phnd->NextStrToken--; + } + + } + } + if(str->Handle>phnd->Handle) break; + } + phnd->NextStrToken=phnd->StrCount; + + // if(j<gc)phnd=gHiiDb.HandleDb.Items[gbi[j]]; + //} + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS NewStringPack(IN EFI_HII_STRING_PACK *Package, + UINTN HandleId) +{ + UINTN i,lid; + UINT8 *ofs; + UINT16 *str; + RELOFST *ps;//string pointer + EFI_HII_STRING_PACK *cp=Package; + EFI_STATUS Status=0; + BOOLEAN f=TRUE; + HII_HANDLE *phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[HandleId]; +//-------------------------------- + while(!IsLastStrPack(cp)){ + ps=(RELOFST*)(cp+1); + ofs=(UINT8*)cp; + //Check if Language exists already + Status=GetLanguageFromPack(cp,&lid); + if(EFI_ERROR(Status)) return Status; + if(f){//if this is first string pack make this lang Primary + phnd->PriLang=(UINT32)lid; + f=FALSE; + } else { + //All other languages if any will be Secondary languages + Status=LocateSecLangAdd(phnd,&lid,TRUE); + if(EFI_ERROR(Status)) return Status; + } + + for(i=0; i<Package->NumStringPointers; i++){ + phnd->NextStrToken=(STRING_REF)i; + if(!ps[i]) continue; + str=(UINT16*)(ofs+ps[i]); + Status=AddString(lid,phnd,str,TRUE,NULL); + if(EFI_ERROR(Status)) return Status; + } + + + cp=(EFI_HII_STRING_PACK*)((UINT8*)cp+cp->Header.Length); + } + phnd->StrCount=(STRING_REF)Package->NumStringPointers; + phnd->HasStr=TRUE; + return Status; +} + + +/////////////////////////////////////////////////////////////////// +// IFR Releated Functions +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +//this one will calculate length in bytes for the buffer designed +//to receive a copy of form instance +//UINT16 GetFormLen(HII_FORM *Form){ +// HII_LABEL *lbl; +// UINTN i; +// UINT16 len=Form->BufferLength; +//------------------------ +// for(i=0; i<Form->Labels.ItemCount; i++){ +// lbl=Form->Labels.Items[i]; +// if(lbl->Erased) len-=lbl->OrgDataLength; +// len+=lbl->UpdDataLength; +// } +// return len; +//} + +/////////////////////////////////////////////////////////////////// +//this one will calculate length in bytes for the buffer designed +//to receive a copy of FormSet instance +//UINT16 GetFormSetLen(HII_FORMSET *FormSet){ +// UINT16 len=0; +// UINTN i; +// HII_FORM *frm; +//------------------ +// for(i=0; i<FormSet->Forms.ItemCount; i++){ +// frm=FormSet->Forms.Items[i]; +// len+=GetFormLen(frm); +// } +// return len+FormSet->FormSetData->Header.Length+FormSet->EndFormSet->Header.Length; +//} + +UINTN GetDataLen( UINT8 *OpCode, UINTN *Count, BOOLEAN Remove){ + UINTN i; + UINTN len=0; + UINT8 *p=OpCode; +//------------------------ + for(i=0; i<*Count; i++){ +// if( !Remove && +// ( (*p)==EFI_IFR_END_FORM_OP || (*p)==EFI_IFR_LABEL_OP ) +// ){ +// i=i; +// } + if( ( Remove && ( (*p)==EFI_IFR_END_FORM_OP || (*p)==EFI_IFR_LABEL_OP ) +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + //when adding data I expect that caller knows what he is doing and + //passes me correct Data Count. Guess what? This is not TRUE in Intel's Setup. + //Intel uses Zeroed buffer to fill with desired Opcodes, set Data count to 0xFF and here we go. + //In this case if in buffer we will found junk which satisfy conditions below + //we can seriousely scrue up!!!!! +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + || ((*p)==0 || (*p)>EFI_IFR_VARSTORE_SELECT_PAIR_OP ))){ + *Count=i; + break; + } + len = len + ((EFI_IFR_OP_HEADER*)p)->Length; + p=OpCode+len; + } + return len; +} + + +/////////////////////////////////////////////////////////////////// +//this will copy form from HII DB private storage to decignated Buffer +VOID CopyForm(UINT8* Buffer, HII_FORM *Form, UINTN *BytesCnt){ + UINTN i,cnt=0; + HII_LABEL *lbl=NULL; + UINT8 *bp=Buffer; +//---------------- + + //Now First Label has data starting from opcode next to FORM_OP + //and lbl->Label of very first label in the list actualy FORM_OP + //so don't need following code + + //if(Form->Labels.ItemCount)lbl=(HII_LABEL*)Form->Labels.Items[0]; + //1. copy form till first label (including LABEL OPCODE) + //if(lbl)//Total Bufferlength including EOF opcode + // cnt=(UINT8*)(lbl->Label)-(UINT8*)Form->FormData; + //else + // cnt=Form->BufferLength-Form->EndForm->Header.Length; + + //pBS->CopyMem(bp,Form->FormData,For); + //bp+=cnt; //Advance buffer pointer; + //(*BytesCnt)=cnt; + (*BytesCnt)=0; + //Keep circling trough Labels copying corresponded data + for(i=0;i<Form->Labels.ItemCount;i++){ + lbl=(HII_LABEL*)Form->Labels.Items[i]; + //copy Label OpCode + pBS->CopyMem(bp,lbl->Label,lbl->Label->Header.Length); + bp+=lbl->Label->Header.Length; + (*BytesCnt)+=lbl->Label->Header.Length; + + //if Label was updated copy Update data first... + if(lbl->LabelData){ + pBS->CopyMem(bp,lbl->LabelData,lbl->DataLength); + bp+=lbl->DataLength; + (*BytesCnt)+=lbl->DataLength; + } + } + //Copy EOF opcode + cnt=Form->EndForm->Header.Length; + pBS->CopyMem(bp,Form->EndForm,cnt); + (*BytesCnt)+=cnt; + return; +} + +/////////////////////////////////////////////////////////////////// +//will copy entire formset data excluding Pcakage Header +VOID CopyFormSet(UINT8* Buffer, HII_FORMSET *FormSet, UINTN *BytesCnt){ + UINTN i; + UINT8 *bp=Buffer,*pp; + UINTN cnt; + HII_FORM *frm; +//---------------- + bp=Buffer; + //Copy Formset OpCode... + pBS->CopyMem(bp,FormSet->FormSetData,FormSet->FormSetData->Header.Length); + bp+=FormSet->FormSetData->Header.Length; + *BytesCnt=FormSet->FormSetData->Header.Length; + //Copy any information that we might have from end of FormSet Opcode + //to the befinning of FOrm OpCode VARSTORE for example. + if(FormSet->Forms.ItemCount){ + pp=(UINT8*)FormSet->FormSetData+FormSet->FormSetData->Header.Length; + frm=FormSet->Forms.Items[0]; + cnt=(UINTN)((UINT8*)frm->FormData-pp); + pBS->CopyMem(bp,pp,cnt); + bp+=cnt; + *BytesCnt+=cnt; + } + + for(i=0; i<FormSet->Forms.ItemCount; i++){ + frm=FormSet->Forms.Items[i]; + CopyForm(bp,frm,&cnt); + bp+=cnt; + *BytesCnt+=cnt; + } + //copy END_OF_FORM_SET OP here + cnt=FormSet->EndFormSet->Header.Length; + pBS->CopyMem(bp,&FormSet->EndFormSet->Header.OpCode,cnt); + *BytesCnt+=cnt; + return; +} + + + +/////////////////////////////////////////////////////////////////// +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +// Cache Form and Formset +HII_FORM *LocateForm(HII_FORMSET *FormSet, EFI_FORM_ID FormId){ + EFI_STATUS Status=0; + UINTN fid; +//---------------------------------------------- + Status=LocateItem(&FormSet->Forms,&FormId,sizeof(EFI_FORM_ID),&fid); + if(EFI_ERROR(Status)) return NULL; + + return (HII_FORM*)FormSet->Forms.Items[fid]; +} + +/////////////////////////////////////////////////////////////////// +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +// Cache Form and Formset +HII_FORMSET *LocateFormSet(UINTN HandleIdx, UINTN* FormSetIdx){ + EFI_STATUS Status=0; + UINTN fsid; +//-------------------------- + Status=LocateItem(&gHiiDb.IfrDb,&((UINT32)HandleIdx),sizeof(UINT32),&fsid); + if(EFI_ERROR(Status)) return NULL; + if(FormSetIdx!=NULL)*FormSetIdx=fsid; + return (HII_FORMSET*)gHiiDb.IfrDb.Items[fsid]; +} + + +HII_LABEL *LocateFormLabel(HII_FORM *Form, EFI_FORM_LABEL LabelId, UINTN *LabelIdx){ + EFI_STATUS Status=0; + UINTN lid; +//---------------------------------------------- + Status=LocateItem(&Form->Labels,&LabelId, sizeof(EFI_FORM_LABEL),&lid); + if(EFI_ERROR(Status)) return NULL; + + *LabelIdx=lid; + return (HII_LABEL*)Form->Labels.Items[lid]; +} + +HII_LABEL *LocateFormSetLabel(HII_FORMSET *FormSet, EFI_FORM_LABEL LabelId, UINTN *LabelIdx){ + EFI_STATUS Status=0; + UINTN lid; +//---------------------------------------------- + Status=LocateItem(&FormSet->Labels,&LabelId, sizeof(EFI_FORM_LABEL),&lid); + if(EFI_ERROR(Status)) return NULL; + + if(LabelIdx)*LabelIdx=lid; + return (HII_LABEL*)FormSet->Labels.Items[lid]; +} + + +/////////////////////////////////////////////////////////////////// +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//This MUST be here to make Shell working +static UINT8 gDummyVfr[] = { + //Header + 0x2c, 0x00, 0x00, 0x00, //Actual Length of Data Buffer + 0x03, 0x00, //Type; + // start of IFR data + /*O*/ 0x0E, //Opcode=EFI_IFR_FORM_SET_OP + /*L*/ 0x24, //Length + //Offset=8 + /*G*/ 0xBC, 0x30, 0x0C, 0x9E, 0x06, 0x3F, 0xA6, 0x4B, 0x82, 0x88, 0x09, 0x17, 0x9B, 0x85, 0x5D, 0xBE, //GUID + /*S*/ 0x02, 0x00, //FormSet Title + /*S*/ 0x00, 0x00, //Help + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//Callback + 0x00, 0x00, //Class + 0x00, 0x00, //SubClass + 0x00, 0x00, //NvDataSize + /*O*/ 0x0D, //OpCOde=EFI_IFR_END_FORM_SET_OP + /*L*/ 0x02, +}; +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetFormsNew(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLength, + OUT UINT8 *Buffer) +{ + UINTN hid; + HII_FORMSET *fs; + HII_FORM *frm; + HII_HANDLE *phnd; + UINTN len; +//-------------------------------------- + if(This==NULL && BufferLength==NULL) return EFI_INVALID_PARAMETER; + //phnd=LocateHandle(Handle, &hid); + //TODO: Felix: by the HII Spec. we should return EFI_INVALID_PARAMETER + //However, Intel Device Manager expects EFI_NOT_FOUND + //(it hangs if it is something else) + phnd=LocateHandle(Handle, &hid); + if(!phnd) return EFI_NOT_FOUND; + + fs=LocateFormSet(hid, NULL); + if(!fs){ + if(!FormId){ + //Technically I must Return NOT_FOUND ERROR but... +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this patch was made to keep Shell working. Shell and HII coexistance is +//based on assumption that "It must be some IFR pack associated with String pack" +//If this statement FALSE Shell will hang in INFINITE LOOP!!!! +//////////////////////////////////////////////////////////////////////// +//this comments I took from Intel's HII Database Driver +// "If someone is passing in a string only, create a dummy IfrPack with a Guid +// to enable future searching of this data." +//////////////////////////////////////////////////////////////////////// + if(*BufferLength< sizeof(gDummyVfr)) { + *BufferLength=sizeof(gDummyVfr); + return EFI_BUFFER_TOO_SMALL; + } + *BufferLength=sizeof(gDummyVfr); + pBS->CopyMem(Buffer,&gDummyVfr[0],sizeof(gDummyVfr)); + //copy handle guid here Shell expect it to mutch with some standart guids + pBS->CopyMem((VOID*)(Buffer+8),(VOID*)&(phnd->Guid),sizeof(EFI_GUID)); + return EFI_SUCCESS; + } else return EFI_NOT_FOUND; +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + } + + if(!FormId){//we must return whole FormSet + //STUPID SHELL expect me to return formset with EFI_HII_PACK_HEADER + // why? I don't know! + len=fs->BufferLength+sizeof(EFI_HII_PACK_HEADER); + } else { + frm=LocateForm(fs,FormId); + if(!frm) return EFI_NOT_FOUND; + len=frm->BufferLength; + } + + if(*BufferLength<len){ + *BufferLength=len; + return EFI_BUFFER_TOO_SMALL; + } + *BufferLength=len; + + //If "FormId" we must return whole FormSet + if(!FormId){ + //STUPID SHELL expect me to return formset with EFI_HII_PACK_HEADER + //Create it + *((UINT32*)Buffer)=(UINT32)len; + *((UINT16*)(Buffer+4))=3;//IFR Type + CopyFormSet(Buffer+6,fs,&hid); + } + else + CopyForm(Buffer,frm,&hid); + + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiGetFormsOld(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINT16 *BufferLength, + OUT UINT8 *Buffer) +{ + EFI_STATUS Status=0; + UINTN bl; +//-------------------------------- + if(BufferLength==NULL) return EFI_INVALID_PARAMETER; + + bl=(UINTN)(*BufferLength); + Status=HiiGetFormsNew(This,Handle,FormId,&bl,Buffer); + (*BufferLength)=(UINT16)bl; + + if((Status==EFI_BUFFER_TOO_SMALL) && (bl > 0xFFFF)) Status=EFI_INVALID_PARAMETER; + return Status; +} + + +/////////////////////////////////////////////////////////////////// +//Will free all memory blocks associated with Label->Objects structures +VOID DeleteLabelObjects(HII_LABEL *Label){ + UINTN i; + HII_OBJECT *obj; +//------------------ + for(i=0;i<Label->Objects.ItemCount; i++){ + obj=Label->Objects.Items[i]; + ClearItemLst(&obj->Conditions,FALSE); + ClearItemLst(&obj->Options,FALSE); + } + ClearItemLst(&Label->Objects,TRUE); +} + + + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiUpdateForm(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + IN BOOLEAN AddData, + IN EFI_HII_UPDATE_DATA *Data) +{ + EFI_STATUS Status=0; + UINTN hid,lid; + HII_FORMSET *fs; + HII_FORM *frm; + HII_LABEL *lbl; + UINTN len,cnt; + UINT8 *ub; + EFI_IFR_OP_HEADER *op; +//------------------------- + if(!This || !Data ) return EFI_INVALID_PARAMETER; + + if(!LocateHandle(Handle, &hid)) return EFI_INVALID_PARAMETER; + + //Find Formset + fs=LocateFormSet(hid, NULL); + if(!fs) return EFI_INVALID_PARAMETER; + + //Find Label + //FormUpdate= TRUE means just change Form Title!!! + if(Data->FormUpdate){ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//In Intel's HII implementation Data->FormValue field is missing + //Find Form using UPDATE Data +// frm=LocateForm(fs,Data->FormValue); +// if(!frm) return EFI_NOT_FOUND; + //Update Form Title +// frm->FormData->FormTitle=Data->FormTitle; +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + } + + // + if(Data->DataCount){ + //Find Label + lbl=LocateFormSetLabel(fs, Label, &lid); + if(!lbl) return EFI_NOT_FOUND; + frm=lbl->OwnerForm; + cnt=Data->DataCount; + if(AddData){ + op=(EFI_IFR_OP_HEADER*)&Data->Data; + if(!op->OpCode || !op->Length) return EFI_INVALID_PARAMETER; + //Calculate size of UPDATE data + len=GetDataLen((UINT8*)op,&cnt,FALSE); + ub=Malloc(len+lbl->DataLength); + if(!ub) return EFI_OUT_OF_RESOURCES; + +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + //Copy Update Data in Private Buffer + pBS->CopyMem(ub,op,len); + //Copy Old Data in same Private Buffer + if(lbl->LabelData)pBS->CopyMem((VOID*)(ub+len),lbl->LabelData,lbl->DataLength); +//for coimpatibility with Intel's setup I've change order in which the chanks of opcodes +// been copied in a new label buffer - New data will be added after the old data + //if(lbl->LabelData)pBS->CopyMem(ub,lbl->LabelData,lbl->DataLength); + //pBS->CopyMem((VOID*)(ub+lbl->DataLength),op,len); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + + //Update Buffer parameters in every structure affected by update + lbl->DataLength = lbl->DataLength + len; + lbl->DataCount = lbl->DataCount + Data->DataCount; + if(lbl->Updated && lbl->LabelData)pBS->FreePool(lbl->LabelData); + lbl->LabelData=(EFI_IFR_OP_HEADER*)ub; + fs->BufferLength = fs->BufferLength + len; + frm->BufferLength = frm->BufferLength + len; + //Delete Old Data + DeleteLabelObjects(lbl); + }else{ + //we will not erase an empty Label! + if(lbl->LabelData){ + op=lbl->LabelData; + if(Data->DataCount>=lbl->DataCount){ + cnt=lbl->DataCount; + len=lbl->DataLength; + } else len=GetDataLen((UINT8*)op,&cnt,TRUE); + + //if after erasing no data has left, no need to allocate new buffer + if((INTN)(lbl->DataLength-len)>0){ + ub=Malloc(lbl->DataLength-len); + if(!ub) + return EFI_OUT_OF_RESOURCES; + //Copy rest of Old Data in Private Buffer + pBS->CopyMem(ub,(UINT8*)lbl->LabelData+len,lbl->DataLength-len); + } else ub=NULL; + + //Update Buffer parameters in every structure affected by update + lbl->DataLength = lbl->DataLength - len; + lbl->DataCount = lbl->DataCount - cnt; + if(lbl->Updated && lbl->LabelData)pBS->FreePool(lbl->LabelData); + lbl->LabelData=(EFI_IFR_OP_HEADER*)ub; + fs->BufferLength = fs->BufferLength - len; + frm->BufferLength = frm->BufferLength - len; + DeleteLabelObjects(lbl); + } + } + //Populate pointers on Label Objects from Label Dtat Buffer + if(lbl->LabelData!=NULL)Status=CreateLabelObjects(lbl); + if(EFI_ERROR(Status))return Status; + lbl->Updated=TRUE; + + if(lbl->UpdateCallBack) lbl->UpdateCallBack(Label, Handle,AddData); + } + + if(Data->FormSetUpdate){ + fs->FormSetData->CallbackHandle=Data->FormCallbackHandle; + } + + return EFI_SUCCESS; +} + +EFI_STATUS InitDefStorage(HII_FORMSET *FormSet){ + EFI_STATUS Status; + HII_STORE *st; + static CHAR8 *ss="Setup";//{'S','e','t','u','p',0}; + CHAR8 *pn;//pointer to var name; +//------------------------------------------------ + st=MallocZ(sizeof(HII_STORE)); + if(!st)return EFI_OUT_OF_RESOURCES; + + Status=AppendItemLst(&FormSet->Storages,st); + + st->VarStore=MallocZ(sizeof(EFI_IFR_VARSTORE)+6); + if(!st->VarStore)return EFI_OUT_OF_RESOURCES; + + //Init Default VarStore Structure VarId is Always 0x0000 + st->VarStore->Header.Length=sizeof(EFI_IFR_VARSTORE)+6; + st->VarStore->Header.OpCode=EFI_IFR_VARSTORE_OP; + st->VarStore->Size=FormSet->FormSetData->NvDataSize; + + //Copy formset GUID here + pBS->CopyMem(&st->VarStore->Guid,&FormSet->FormSetData->Guid,sizeof(EFI_GUID)); + + pn=(CHAR8*)st->VarStore; + pn+=sizeof(EFI_IFR_VARSTORE); + pBS->CopyMem(pn,ss,6); + + return EFI_SUCCESS; +} + +//Selects Var Store Object +HII_STORE *LocateStorage(HII_FORMSET *FormSet, UINT16 VarId, UINTN *StoreId OPTIONAL){ + UINTN i; + HII_STORE *st; +//--------------------- + for(i=0; i<FormSet->Storages.ItemCount; i++){ + st=(HII_STORE*)FormSet->Storages.Items[i]; + if(st->VarStore->VarId==VarId) { + if(StoreId)*StoreId=i; + return st; + } + } + return NULL; +} + + +EFI_STATUS CreateLabelObjects(HII_LABEL *Label) +{ + EFI_IFR_OP_HEADER *op; + UINTN i,j=0, k; + HII_OBJECT *obj=NULL; + HII_STORE *st1=NULL, *st2=NULL; + static T_ITEM_LIST clst={0,0,NULL},olst={0,0,NULL}; //temp conditions and objects list list + static T_ITEM_LIST supprstores = {0, 0, NULL}; + EFI_STATUS Status; + BOOLEAN cf=FALSE; //conditions flag + BOOLEAN Suppress = FALSE; +//------------------------------------------- + op=Label->LabelData; + + obj=NULL; + //st1=(HII_STORE*)Label->OwnerForm->Owner->Storages.Items[0]; + st1 = LocateStorage(Label->OwnerForm->Owner, CurrentVarId, NULL); + if(!st1) { st1=(HII_STORE*)Label->OwnerForm->Owner->Storages.Items[0]; CurrentVarId = 0; } + st2=NULL; + for(i=0;i<Label->DataCount;i++){ + //Select Default Storage so Store1 + switch(op->OpCode){ + //Storage Select Opcodes + case EFI_IFR_VARSTORE_SELECT_OP: + { + EFI_IFR_VARSTORE_SELECT *vs=(EFI_IFR_VARSTORE_SELECT*)op; + HII_STORE *st=LocateStorage(Label->OwnerForm->Owner,vs->VarId,NULL); + // preserve the varstore selection - to be reset only by the next varstore select + // or a new formset + //------------------------ + if(st) { st1=st; CurrentVarId = vs->VarId; } + } + break; + case EFI_IFR_VARSTORE_SELECT_PAIR_OP: + { + EFI_IFR_VARSTORE_SELECT_PAIR *v2=(EFI_IFR_VARSTORE_SELECT_PAIR*)op; + HII_STORE *s1=LocateStorage(Label->OwnerForm->Owner,v2->VarId,NULL); + HII_STORE *s2=LocateStorage(Label->OwnerForm->Owner,v2->SecondaryVarId,NULL); + //------------------------ + if(s1) { st1=s1; CurrentVarId = v2->VarId; } + if(s2) st2=s2; + } + break; + //Condition OpCodes + case EFI_IFR_GRAYOUT_IF_OP: + case EFI_IFR_SUPPRESS_IF_OP: + case EFI_IFR_INCONSISTENT_IF_OP: + //if we found some logical expression and local ovject list(olst) has some objects + //we must add this objects with no conditions to the Label->Objects list + //and clear local object list to start fill it with objects who has conditions. + if(!cf){ + for(j=0;j<olst.ItemCount;j++){ + obj=olst.Items[j]; + Status=AppendItemLst(&Label->Objects,obj); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + } + ClearItemLst(&olst,FALSE); + obj=NULL; + } + cf=TRUE; + if( op->OpCode == EFI_IFR_SUPPRESS_IF_OP) Suppress = TRUE; + else Suppress = FALSE; + /////////////////////////////////////////////////////////////////////// + //Do not add break instruction here it is not present for a reason!!!! + /////////////////////////////////////////////////////////////////////// + case EFI_IFR_AND_OP: + case EFI_IFR_OR_OP: + case EFI_IFR_NOT_OP: + case EFI_IFR_EQ_ID_VAL_OP: + case EFI_IFR_EQ_ID_ID_OP: + case EFI_IFR_EQ_ID_LIST_OP: + case EFI_IFR_EQ_VAR_VAL_OP: + //Add Opcode to the temp Condition list; + Status=AppendItemLst(&clst,op); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status;//out of resources + + if(op->OpCode == EFI_IFR_EQ_ID_VAL_OP && Suppress) + { + Status = AppendItemLst(&supprstores, st1); + ASSERT(!EFI_ERROR(Status)); + } + break; + //end of conditions OpCode + case EFI_IFR_END_IF_OP: + //this is definetely end of object presentation, + //but some times it might be no object to add conditions info to + if(!olst.ItemCount){ + for(j=0; j<clst.ItemCount;j++) { + Status=AppendItemLst(&Label->Conditions,clst.Items[j]); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + } + } + for(j=0;j<olst.ItemCount;j++){ + obj=olst.Items[j]; + //I'm trying to allocate exactly as mutch memory as I need for Conditions.Items[] array. + //If you initialize ItemList.InitialCount with some specific value>0, then next call to + //Append ItemLst function will allocate this number of entries for ItemList.Items[] Array. + obj->Conditions.InitialCount=clst.ItemCount; + Status=AppendItemLst(&obj->Conditions,clst.Items[0]); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + pBS->CopyMem(&obj->Conditions.Items[1],&clst.Items[1],sizeof(VOID*)*(clst.ItemCount-1)); + obj->Conditions.ItemCount=clst.ItemCount; + for(k = 0; k < supprstores.ItemCount; k++) + { + Status=AppendItemLst(&obj->SuppressStores,supprstores.Items[k]); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + } + + Status=AppendItemLst(&Label->Objects,obj); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + } + ClearItemLst(&clst,FALSE); //don't need to free data - it's VFR pointers! + ClearItemLst(&olst,FALSE); + ClearItemLst(&supprstores,FALSE); + obj=NULL; + cf=FALSE; + Suppress = FALSE; + break; + //visual opcodes + case EFI_IFR_SUBTITLE_OP: + case EFI_IFR_TEXT_OP: + case EFI_IFR_INVENTORY_OP: + case EFI_IFR_GRAPHIC_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_REF_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_STRING_OP: + case EFI_IFR_SAVE_DEFAULTS_OP: + case EFI_IFR_RESTORE_DEFAULTS_OP: + case EFI_IFR_HIDDEN_OP: + //continiouse + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_ORDERED_LIST_OP: + ASSERT(!obj); //obj pointer must be cleared when we enter there + if(obj)return EFI_INVALID_PARAMETER; + obj=MallocZ(sizeof(HII_OBJECT)); + ASSERT(obj);//Allocation Problems! + if(!obj) return EFI_OUT_OF_RESOURCES; + obj->ObjectCode=op; + obj->Store1=st1; + obj->Store2=st2; + Status=AppendItemLst(&olst,obj); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + //in case of DATE or Time opcode advance by 2 opcodes + if(op->OpCode==EFI_IFR_TIME_OP || op->OpCode==EFI_IFR_DATE_OP){ + op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length); + op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length); + i+=2; + } + obj=NULL; + break; + case EFI_IFR_ONE_OF_OPTION_OP: + ASSERT(olst.ItemCount); + if(!olst.ItemCount) return EFI_INVALID_PARAMETER; + obj=(HII_OBJECT*)olst.Items[olst.ItemCount-1]; + if(!obj) return EFI_INVALID_PARAMETER; //obj must be allocated! + Status=AppendItemLst(&obj->Options,op); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status;//out of resources + break; + case EFI_IFR_END_ONE_OF_OP: + obj=NULL; + break; + + }//end switch; + //Advance to next opcode + op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length); + } + //If there were no any Condition Opcodes contents of the ObjectList(olst) was not copied to the Label.Objects + for(j=0;j<olst.ItemCount;j++){ + obj=olst.Items[j]; + Status=AppendItemLst(&Label->Objects,obj); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status)) return Status; + } + ClearItemLst(&olst,FALSE); + return EFI_SUCCESS; +} + +//This Routine is called to parse FormVfr and Create Objects which must be shown on the screen; +EFI_STATUS CreateFormObjects(HII_FORM *Form){ + UINTN i; + EFI_STATUS Status = EFI_SUCCESS; +//--------------------------------- + + for(i=0; i<Form->Labels.ItemCount; i++){ + Status=CreateLabelObjects((HII_LABEL*)Form->Labels.Items[i]); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status))return Status; + } + return Status; +} + +EFI_STATUS NewKbdPack(EFI_HII_KEYBOARD_PACK *Package, + UINTN HandleId) +{ + EFI_STATUS Status; + HII_KB_LAYOUT_DATA *kbld; +//-------------------- + //Get Some Memory to accomodate Kb Layout Buffer + kbld=Malloc(sizeof(EFI_KEY_DESCRIPTOR)*Package->DescriptorCount+sizeof(HII_KB_LAYOUT_DATA)); + ASSERT(kbld); + if(kbld==NULL) return EFI_OUT_OF_RESOURCES; + + kbld->HandleIndex=HandleId; //just in case to find HII_HANDLE structure assotiated with this PACK + kbld->KeyDscCount=Package->DescriptorCount; + //We will store KB Layout Data right after the HII_KB_LAYOUT_DATA structure itself + kbld->KeyDsc=(EFI_KEY_DESCRIPTOR*)(kbld+1); + MemCpy((VOID*)kbld->KeyDsc, (VOID*)Package->Descriptor, sizeof(EFI_KEY_DESCRIPTOR)*kbld->KeyDscCount); + + //Add saved KB Layout Data to the HII DB + Status=AppendItemLst((T_ITEM_LIST*)&gHiiDb.KeybdDb.KblInitCount,(VOID*)kbld); + ASSERT_EFI_ERROR(Status); + + //Set recently submitted KB Layout as the current one + gHiiDb.KeybdDb.ActiveLayout=gHiiDb.KeybdDb.KblCount-1; + + return Status; +} + +EFI_STATUS NewIfrPack(EFI_HII_IFR_PACK *Package, + UINTN HandleId) +{ + EFI_STATUS Status; + EFI_IFR_OP_HEADER *op; +// INT32 id=0; + HII_FORM *cf=NULL; + HII_FORMSET *cfs=NULL; + HII_LABEL *cl=NULL; + HII_STORE *st=NULL; + HII_HANDLE *phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[HandleId]; + UINT8 *p; + BOOLEAN la=FALSE;//label active flag - helps count OPCODES and Label.dLength +//--------------------------------------------- + //Copy Data to a new Storage =(EFI_IFR_OP_HEADER*)(Package+1); + p=Malloc(Package->Header.Length); + if(!p) return EFI_OUT_OF_RESOURCES; + pBS->CopyMem(p,Package,Package->Header.Length); + + op=(EFI_IFR_OP_HEADER*)(p+sizeof(EFI_HII_PACK_HEADER)); + //Parse IFR and crete Working set of data + //Every IFR Pack must start from FORM_SET_OP + while(/*(op->OpCode!=EFI_IFR_END_FORM_SET_OP)||*/((UINTN)op<((UINTN)p)+Package->Header.Length)){ + switch (op->OpCode){ + //Take care of Forms Sets + case EFI_IFR_FORM_SET_OP: + CurrentVarId = 0; + cfs=MallocZ(sizeof(HII_FORMSET)); + if(!cfs) return EFI_OUT_OF_RESOURCES; + //cfs->BufferLength=0; it is 0 + cfs->FormSetData=(EFI_IFR_FORM_SET*)op; + cfs->HandleId=(UINT32)HandleId; + cfs->Handle=phnd->Handle; + //Setup Initial Storage var + Status=InitDefStorage(cfs); + if(EFI_ERROR(Status)) return Status; + break; + case EFI_IFR_VARSTORE_OP: + if(!cfs) return EFI_INVALID_PARAMETER; + st=MallocZ(sizeof(HII_STORE)); + if(!st) return EFI_OUT_OF_RESOURCES; + Status=AppendItemLst(&cfs->Storages,st); + st->VarStore=(EFI_IFR_VARSTORE*)op; + break; + case EFI_IFR_END_FORM_SET_OP: + if(!cfs)return EFI_INVALID_PARAMETER; //found EFI_IFR_END_FORM_SET_OP without EFI_IFR_FORM_SET_OP + //cfs->BufferLength=(UINT16)((UINT8*)op+op->Length-(UINT8*)cfs->FormSetData); + CurrentVarId = 0; + cfs->EndFormSet=(EFI_IFR_END_FORM_SET*)op; + cfs->HandleId=(UINT32)HandleId; + cfs->BufferLength = cfs->BufferLength + op->Length; + Status=AppendItemLst(&gHiiDb.IfrDb,(VOID*)cfs); + if(EFI_ERROR(Status)) return Status; + cfs=NULL; + break; + //Take care of Forms and Labels + case EFI_IFR_FORM_OP: + case EFI_IFR_LABEL_OP: + { + EFI_IFR_OP_HEADER *nxt; + //---------------------------- + if(op->OpCode==EFI_IFR_FORM_OP){ + //it must be some FORM_SET OpCode before we met FORM OpCode + if(!cfs) return EFI_INVALID_PARAMETER; + cf=MallocZ(sizeof(HII_FORM)); + if(!cf) return EFI_OUT_OF_RESOURCES; + //cf->BufferLength=0; + cf->FormData=(EFI_IFR_FORM*)op; + cf->FormId=cf->FormData->FormId; + cf->Owner=cfs; + } + if(!cf && !cfs )return EFI_INVALID_PARAMETER; //Form mus be present + cl=MallocZ(sizeof(HII_LABEL)); + if(!cl) return EFI_OUT_OF_RESOURCES; + + cl->OwnerForm=cf; + cl->Label=(EFI_IFR_LABEL*)op; + //it must be a valid opcode next... + nxt=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length); + if(nxt->OpCode!=EFI_IFR_END_FORM_OP && nxt->OpCode!=EFI_IFR_LABEL_OP)cl->LabelData=nxt; + + if(op->OpCode==EFI_IFR_FORM_OP){ + cl->LabelId=0xFACE; //Fake LabelID + } else { + cl->LabelId=cl->Label->LabelId; + Status=AppendItemLst(&cfs->Labels,cl); + if(EFI_ERROR(Status)) return Status; + } + + Status=AppendItemLst(&cf->Labels,cl); + if(EFI_ERROR(Status)) return Status; + + la=TRUE; + } + break; + case EFI_IFR_END_FORM_OP: + if(!cf)return EFI_INVALID_PARAMETER; //found EFI_IFR_END_FORM_OP without EFI_IFR_FORM_OP + //cf->BufferLength=(UINT16)((UINT8*)op+op->Length-(UINT8*)cf->FormData); + cf->EndForm=(EFI_IFR_END_FORM*)op; + cf->BufferLength = cf->BufferLength + op->Length; + Status=AppendItemLst(&cfs->Forms,cf); + if(EFI_ERROR(Status)) return Status; + Status=CreateFormObjects(cf); + cf=NULL; + la=FALSE; + break; + //Labels Has Left + /*case EFI_IFR_LABEL_OP:{ + EFI_IFR_OP_HEADER *nxt; + //--------------------------- + if(!cf && !cfs )return EFI_INVALID_PARAMETER; //Form mus be present + cl=MallocZ(sizeof(HII_LABEL)); + if(!cl) return EFI_OUT_OF_RESOURCES; + + cl->Label=(EFI_IFR_LABEL*)op; + cl->LabelId=cl->Label->LabelId; + cl->OwnerForm=cf; + nxt=(EFI_IFR_OP_HEADER*)(cl->Label+1); + //it must be a valid opcode next... + if(nxt->OpCode!=EFI_IFR_END_FORM_OP && nxt->OpCode!=EFI_IFR_LABEL_OP)cl->LabelData=nxt; + + Status=AppendItemLst(&cf->Labels,cl); + if(EFI_ERROR(Status)) return Status; + + Status=AppendItemLst(&cfs->Labels,cl); + if(EFI_ERROR(Status)) return Status; + la=TRUE; + break; + } + */ + default : + if(la){ + cl->DataCount++; + cl->DataLength = cl->DataLength + op->Length; + } + } //Switch + if(cfs)cfs->BufferLength = cfs->BufferLength + op->Length; + if(cf)cf->BufferLength = cf->BufferLength + op->Length; + op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length); + } + phnd->Ifr=p; + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +// Common Interface functions +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiNewPackNew(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *Packages, + OUT EFI_HII_HANDLE *Handle) +{ + UINTN i; + EFI_HII_PACK_HEADER *hdr, **hdrptr; + EFI_STATUS Status=0; + UINTN c=0,hid=0; + HII_HANDLE *phnd=NULL; + BOOLEAN sp=0,vp=0,hp=0; +//----------------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + + hdrptr=(EFI_HII_PACK_HEADER**)(Packages+1); + for(i=0; i<Packages->NumberOfPackages; i++){ + hdr=hdrptr[i]; + switch(hdr->Type){ + case EFI_HII_FONT: + Status=NewFontPack((EFI_HII_FONT_PACK*)hdr); + if(EFI_ERROR(Status)) return Status; + break; + case EFI_HII_STRING: + if(sp)return EFI_INVALID_PARAMETER; + phnd=LocateHandleGuid(Packages->GuidId,&hid); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this is wrong !!! + //here we are trying to check if somebody using passed GuidId registered Ifr with us + //it should not be like this but Intel's Setup Browser uses same GuidId sor 2 different + //Ifr instances. To maintain compatibility I'll try to patch code... + if(!phnd || phnd->HasStr){ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Packages->GuidId,&hid); + if(Status) return Status; + else c++; + phnd=gHiiDb.HandleDb.Items[hid]; + } + Status=NewStringPack((EFI_HII_STRING_PACK*)hdr, hid); + if(EFI_ERROR(Status)) return Status; + sp=TRUE; + break; + case EFI_HII_IFR: + if(vp)return EFI_INVALID_PARAMETER; + phnd=LocateHandleGuid(Packages->GuidId,&hid); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this is wrong !!!//same goes gor IFR + if(!phnd || phnd->Ifr){ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Packages->GuidId,&hid); + if(Status) return Status; + else c++; + phnd=gHiiDb.HandleDb.Items[hid]; + } + + Status=NewIfrPack((EFI_HII_IFR_PACK*)hdr, hid); + if(EFI_ERROR(Status)) return Status; + vp=TRUE; + break; + case EFI_HII_KEYBOARD: + Status=NewKbdPack((EFI_HII_KEYBOARD_PACK*)hdr, hid); + break; + case EFI_HII_HANDLES: + if(hp)return EFI_INVALID_PARAMETER; +//TODO + hp=TRUE; + break; + case EFI_HII_VARIABLE: +//TODO + break; + case EFI_HII_DEVICE_PATH: +//TODO + break; + default: return EFI_INVALID_PARAMETER; + }//switch + } + if(c)gHiiDb.NextHiiHandle++; + + if(phnd)*Handle=phnd->Handle; + else *Handle=0; + + return Status; +} + +EFI_STATUS HiiNewPackOld (IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACK_LIST *Package, + OUT EFI_HII_HANDLE *Handle) +{ + EFI_STATUS Status=0; + UINTN c=0,hid; + HII_HANDLE *phnd=NULL; +//---------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + + //Check if we have this GUID ib GuidDb already + //For Font and Keyboadr Data HAndle is allways = 0 + if(Package->FontPack) Status=NewFontPack(Package->FontPack); + if(EFI_ERROR(Status)) return Status; + + if(Package->StringPack){ + phnd=LocateHandleGuid(Package->GuidId,&hid); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this is wrong !!! + //here we are trying to check if somebody using passed GuidId registered Ifr with us + //it should not be like this but Intel's Setup Browser uses same GuidId sor 2 different + //Ifr instances. To maintain compatibility I'll try to patch code... + if(!phnd || phnd->HasStr){ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +// if(!phnd){ + Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Package->GuidId,&hid); + if(Status) return Status; + else c++; + phnd=gHiiDb.HandleDb.Items[hid]; + } + + //if(phnd->HasStr) return EFI_INVALID_PARAMETER; + Status=NewStringPack(Package->StringPack, hid); + if(EFI_ERROR(Status)) return Status; + } + + if(Package->IfrPack){ + phnd=LocateHandleGuid(Package->GuidId,&hid); +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this is wrong !!! + //here we are trying to check if somebody using passed GuidId registered Ifr with us + //it should not be like this but Intel's Setup Browser uses same GuidId sor 2 different + //Ifr instances. To maintain compatibility I'll try to patch code... + if(!phnd || phnd->Ifr){ +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +// if(!phnd){ + Status=LocateHandleAdd(gHiiDb.NextHiiHandle,Package->GuidId,&hid); + if(Status) return Status; + else c++; + phnd=gHiiDb.HandleDb.Items[hid]; + } + + //if(phnd->HasIfr) return EFI_INVALID_PARAMETER; + Status=NewIfrPack(Package->IfrPack, hid); + if(EFI_ERROR(Status)) return Status; + } +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//nothing is done for keyboard layout functions +//this is empty spot in spec! +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO + if(c)gHiiDb.NextHiiHandle++; + + if(phnd)*Handle=phnd->Handle; + else *Handle=0; + + return Status; +} + +/////////////////////////////////////////////////////////////////// +//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO//TODO +//this function even not in spec yet so UNSUPPORT it!!! +// here is an explanation I've got from Initial's Source +// "This function allows to extract the NV Image +// that represents the default storage image" +//Still Unclear what to do with it +EFI_STATUS HiiGetDefaultImageOld(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + IN OUT UINT16 *BufferLength, + IN OUT UINT8 *Buffer) +{ + HII_HANDLE *phnd; + HII_FORMSET *fs; + EFI_IFR_OP_HEADER *op; + UINTN hi,fsi,i,t=0,cv=0; + UINT8 *fsb;//formset buffer + BOOLEAN ol=FALSE; + EFI_STATUS Status; +//--------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + + phnd=LocateHandle(Handle,&hi); + if(!phnd || !phnd->Ifr) return EFI_INVALID_PARAMETER; + + fs=LocateFormSet(hi,&fsi); + if(!fs) return EFI_INVALID_PARAMETER; + + if(*BufferLength<fs->FormSetData->NvDataSize){ + *BufferLength=fs->FormSetData->NvDataSize; + return EFI_BUFFER_TOO_SMALL; + } + *BufferLength=fs->FormSetData->NvDataSize; + i=*BufferLength; + + if (DefaultMask & EFI_IFR_FLAG_DEFAULT) + Status=pRS->GetVariable(L"SetupDefaultOverride",&phnd->Guid,NULL,&i,Buffer); + else { + if (DefaultMask & EFI_IFR_FLAG_MANUFACTURING) + Status=pRS->GetVariable(L"SetupManufacturingOverride",&phnd->Guid,NULL,&i,Buffer); + else { + DefaultMask = DefaultMask | EFI_IFR_FLAG_DEFAULT; + Status=pRS->GetVariable(L"Setup",&phnd->Guid,NULL,&i,Buffer); + } + } + + fsb=Malloc(fs->BufferLength); + if(!fsb) return EFI_OUT_OF_RESOURCES; + CopyFormSet(fsb,fs,&i); + + op=(EFI_IFR_OP_HEADER*)fsb; + while(op->OpCode!=EFI_IFR_END_FORM_SET_OP){ + switch(op->OpCode){ + case EFI_IFR_ORDERED_LIST_OP: + ol=TRUE; + i=((EFI_IFR_ONE_OF*)op)->QuestionId; + t=((EFI_IFR_ONE_OF*)op)->Width; + break; + case EFI_IFR_ONE_OF_OP: + ol=FALSE; + i=((EFI_IFR_ONE_OF*)op)->QuestionId; + t=((EFI_IFR_ONE_OF*)op)->Width; + break; + case EFI_IFR_ONE_OF_OPTION_OP:{ + EFI_IFR_ONE_OF_OPTION *ifro=(EFI_IFR_ONE_OF_OPTION*)op; + //----------------- + if(!cv){ + if(ol){ + //pBS->CopyMem(&Buffer[i],&((EFI_IFR_ONE_OF_OPTION*)op)->Value, 1); + pBS->CopyMem(&Buffer[i],&ifro->Value, 1); + i++; + } else { + //if (((EFI_IFR_ONE_OF_OPTION*)op)->Flags & DefaultMask) + // pBS->CopyMem(&Buffer[i],&((EFI_IFR_ONE_OF_OPTION*)op)->Value,t); + if (ifro->Flags & DefaultMask) + pBS->CopyMem(&Buffer[i],&ifro->Value,t); + } + } + } break; + case EFI_IFR_END_OP: + t=0; + break; + case EFI_IFR_CHECKBOX_OP:{ + EFI_IFR_CHECK_BOX *ifrc=(EFI_IFR_CHECK_BOX*)op; + //-------------------- + if(!cv){ + //if(((EFI_IFR_CHECK_BOX*)op)->Flags & DefaultMask) + // Buffer[((EFI_IFR_CHECK_BOX*)op)->QuestionId] = 1; + //else + // Buffer[((EFI_IFR_CHECK_BOX*)op)->QuestionId] = 0; + if(ifrc->Flags & DefaultMask) + Buffer[ifrc->QuestionId] = 1; + else + Buffer[ifrc->QuestionId] = 0; + } + } break; + case EFI_IFR_NUMERIC_OP:{ + EFI_IFR_NUMERIC *ifrn=(EFI_IFR_NUMERIC*)op; + //-------------------------- + //if (!cv)pBS->CopyMem(&Buffer[((EFI_IFR_NUMERIC*)op)->QuestionId], + // &((EFI_IFR_NUMERIC*)op)->Default,((EFI_IFR_NUMERIC*)op)->Width); + if (!cv){ + pBS->CopyMem(&Buffer[ifrn->QuestionId], &ifrn->Default,ifrn->Width); + } + } break; + + case EFI_IFR_VARSTORE_SELECT_OP: + case EFI_IFR_VARSTORE_SELECT_PAIR_OP: + cv=((EFI_IFR_VARSTORE_SELECT*)op)->VarId; + break; + } + op=(EFI_IFR_OP_HEADER*)((UINT8*)op+op->Length); + } + pBS->FreePool(fsb); + return EFI_SUCCESS; +} +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiFindHandles(IN EFI_HII_PROTOCOL *This, + //spec not says in what units assume, for now, it is in EFI_HII_HANDLE + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle) +{ + UINTN i; + HII_HANDLE *hnd; +//------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + + if(*HandleBufferLength<gHiiDb.HandleDb.ItemCount*sizeof(EFI_HII_HANDLE)){ + *HandleBufferLength = (UINT16)gHiiDb.HandleDb.ItemCount*sizeof(EFI_HII_HANDLE); + return EFI_BUFFER_TOO_SMALL; + } + *HandleBufferLength = (UINT16)gHiiDb.HandleDb.ItemCount*sizeof(EFI_HII_HANDLE); + for (i=0; i<gHiiDb.HandleDb.ItemCount; i++){ + hnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[i]; + Handle[i]=hnd->Handle; + } + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +// Will remove all stuff associated with form set on particular handle +// including all Update Data and Free all memory used to store private data +// This function assumes "HandleIdx" is valid. +VOID RemoveFormSet(UINTN HandleIdx){ + HII_FORMSET *fst; + HII_FORM *frm; + HII_LABEL *lbl; + UINTN i,j,fsi; +//-------------------------------- + while(TRUE) { //it might be more then one formset with the same Handle + fst=LocateFormSet(HandleIdx, &fsi); + if(!fst) return; //Not a single form set was registred with this Handle + + for(i=0;i<fst->Forms.ItemCount;i++){ + frm=(HII_FORM*)fst->Forms.Items[i]; + for(j=0;j<frm->Labels.ItemCount;j++){ + lbl=frm->Labels.Items[j]; + DeleteLabelObjects(lbl); + if(lbl->LabelData && lbl->Updated) pBS->FreePool(lbl->LabelData); + } + ClearItemLst(&frm->Labels,TRUE); + } + ClearItemLst(&fst->Labels,FALSE); + ClearItemLst(&fst->Forms,TRUE); + DeleteItemLst(&gHiiDb.IfrDb,fsi,TRUE); + } +} + +/////////////////////////////////////////////////////////////////// +// Will remove all String records associated with "HandleIdx" for +// all languages. This function assumes "HandleIdx" is valid. +VOID RemoveStrings(UINTN HandleIdx){ + HII_HANDLE *hnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[HandleIdx]; + HII_STR *str; + INTN i; +//----------------------- + for(i=0; (UINTN)i<gHiiDb.StringDb.RecordCount; i++){ + DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,(UINTN)i,&str); + if(str->Handle==hnd->Handle){ + if(str->String.StrPtr)pBS->FreePool(str->String.StrPtr); + if(str->NewStr.StrPtr)pBS->FreePool(str->NewStr.StrPtr); + DbeDelete(&gHiiDb.StringDb,str,TRUE); + i--; + continue; + } + if(str->Handle>hnd->Handle) break; + } +} + + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiRemovePack(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle) + +{ + UINTN hid; + HII_HANDLE *phnd; + HII_FORMSET *fs; + UINTN i; +//-------------------- + if(!This) return EFI_INVALID_PARAMETER; + + //Here we will try to remove Pack from DB + phnd=LocateHandle(Handle,&hid); + if(!phnd) return EFI_INVALID_PARAMETER; + + //So we found requested Handle, now remove all stuff associated with it. + //Remove IFRs + if(phnd->Ifr){ + RemoveFormSet(hid); + pBS->FreePool(phnd->Ifr); + } + //Remove Strings + if(phnd->HasStr)RemoveStrings(hid); + + //Free Items[] buffer if it was allocated + //if no Secondary Languages installed for this HII_HANDLE nothing has to be done + if(phnd->SecLang.ItemCount)ClearItemLst(&phnd->SecLang,FALSE); + + //reindexing remaining formsets to take care of + //removed HII_HANDLE record from HiiDB.HandleDb[] + for(i=0; i<gHiiDb.IfrDb.ItemCount; i++) { + fs=gHiiDb.IfrDb.Items[i]; + if(fs->HandleId>hid) fs->HandleId--; + } + + DeleteItemLst(&gHiiDb.HandleDb, hid, TRUE); + + //The current saved handle might be pointing on the one been removed. + //so reset them to initial values. + mCurHnd=NULL; + mCurLang=NULL; + mCurHid=0; + mCurLid=0; + mCurStr=NULL; + + return EFI_SUCCESS; +} + +/////////////////////////////////////////////////////////////////// +//HelperFunction to calculate size needed to dump the database +//excluding EFI_HII_DATA_TABLE header +UINTN GetHandleExpBuffSize(HII_HANDLE *HiiHandle, UINTN HndIndex){ + UINTN sz=0, i, li=(UINTN)-1; + HII_FORMSET *fs=NULL; + HII_STR *str=NULL; + HII_STORE *st=NULL; +//------------------------------------- + + //This is an order of data structures as provided in Intel's implementation + //DevPath Data stuff Dummy so far just reserve space for DP_PACK and END_OF_DP + sz+=sizeof(EFI_HII_DEVICE_PATH_PACK)+sizeof(EFI_DEVICE_PATH_PROTOCOL); + + //Find Formset we are working with + fs=LocateFormSet(HndIndex, NULL); + + if(!fs) sz+= sizeof(gDummyVfr); //no formset no VAR data just Dummy Formset + else { + //Variable data + for(i=0; i<fs->Storages.ItemCount; i++){ + //-------------------- + st=fs->Storages.Items[i]; + if(st->VarStore->Size){ + UINT8 *p; + UINTN ind = 0, vsize = 0; + UINT16 VarName[256] = {0}; + //--------------------- + sz+=sizeof(EFI_HII_VARIABLE_PACK); + //sz+=st->VarStore->Size; + p=(UINT8*)(st->VarStore+1); + while(*p){ + p++; + vsize+=sizeof(UINT16); + } + vsize+=sizeof(UINT16);//NULL terminator + sz+=vsize; + + p=(UINT8*)(st->VarStore+1); + while(*p && ind < sizeof(VarName)){ + VarName[ind] = (CHAR16)*p; + p++; ind++; + } + vsize=0; + pRS->GetVariable(VarName,&st->VarStore->Guid,NULL,&vsize,NULL); + if(vsize) + sz+=vsize; + else + sz += st->VarStore->Size; + } + } + if(fs->Storages.ItemCount > 0) + sz+=sizeof(EFI_HII_VARIABLE_PACK); // !! added dummy VARIABLE PACK + + //formset data size + sz+=fs->BufferLength+sizeof(EFI_HII_PACK_HEADER);// !! changed to += + } + + //string data size + if(HiiHandle->HasStr){ + for(i=0; i<gHiiDb.StringDb.RecordCount; i++){ + DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,(UINTN)i,&str); + if(str->Handle==HiiHandle->Handle){ + if((li==-1)||(li!=str->LangIdx)){ + li=str->LangIdx; + sz+=sizeof(EFI_HII_STRING_PACK); //new pack for new language + } + //the StrLen stored in UNICODECHAR units + if(str->NewStr.StrPtr)sz+=str->NewStr.StrLen*sizeof(CHAR16)+sizeof(RELOFST); + else sz+=str->String.StrLen*sizeof(CHAR16)+sizeof(RELOFST); + } + if((str->Handle>HiiHandle->Handle)||(i==gHiiDb.StringDb.RecordCount-1)){ + sz+=sizeof(EFI_HII_STRING_PACK);//terminator pack + break; + } + } + } + return sz; +} + + +UINT32 CountStrOfLang(HII_HANDLE *HiiHandle, UINTN StartIdx, UINTN LangIdx ){ + UINTN i; + UINT32 cnt=0; + HII_STR *str; +//---------------------- + for (i=StartIdx; i<gHiiDb.StringDb.RecordCount;i++){ + DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,i,&str); + if(str->Handle==HiiHandle->Handle){ + if(str->LangIdx==LangIdx)cnt++; + else break; + } else break; + } + return cnt; +} + + +VOID ExportHandleData(IN HII_HANDLE *HiiHandle, IN UINTN HndIndex, + IN EFI_HII_DATA_TABLE *DataTbl, IN OUT UINT8 **BufferPointer) +{ + UINTN sz=0, i; + HII_FORMSET *fs; + HII_STR *str; + HII_STORE *st; + UINT8 *p1=*BufferPointer, *p2; + EFI_STATUS Status; +//------------------------------------- + + //This is an order of data structures as provided in Intel's implementation + //DevPath Data stuff Dummy so far END_OF_DP + DataTbl->DevicePathOffset=(UINT32)(p1-(UINT8*)DataTbl); + + ((EFI_HII_DEVICE_PATH_PACK*)p1)->Header.Type=EFI_HII_DEVICE_PATH; + + //points to the space after EFI_HII_DEVICE_PATH_PACK structure + p2=(p1+sizeof(EFI_HII_DEVICE_PATH_PACK)); + + ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Type=0xFF; + ((EFI_DEVICE_PATH_PROTOCOL*)p2)->SubType=0xFF; +// ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Length=0; + ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Length[0]=0; + ((EFI_DEVICE_PATH_PROTOCOL*)p2)->Length[1]=0; + ((EFI_HII_DEVICE_PATH_PACK*)p1)->Header.Length=(UINT32)(p2-p1+sizeof(EFI_DEVICE_PATH_PROTOCOL)); + + p1=p2+sizeof(EFI_DEVICE_PATH_PROTOCOL); + + //Find Formset we are working with + fs=LocateFormSet(HndIndex, NULL); + if(!fs) { + //No formset no VAR data + DataTbl->VariableDataOffset=0; + + //Copy a Dummy formset to be compatible with Intel + DataTbl->IfrDataOffset=(UINT32)(p1-(UINT8*)DataTbl); + + pBS->CopyMem(p1,&gDummyVfr[0],sizeof(gDummyVfr)); + //copy handle guid here Shell expect it to mutch with some standart guids + pBS->CopyMem((VOID*)(p1+8),(VOID*)&HiiHandle->Guid,sizeof(EFI_GUID)); + //Adjust the pointer + p1+=sizeof(gDummyVfr); + } else { + //Variable data + DataTbl->VariableDataOffset=(UINT32)(p1-(UINT8*)DataTbl); + for(i=0; i<fs->Storages.ItemCount; i++){ + //-------------------- + st=fs->Storages.Items[i]; + if(st->VarStore->Size){ + UINT8 *p; + //--------------------- + p2=p1+sizeof(EFI_HII_VARIABLE_PACK); + ((EFI_HII_VARIABLE_PACK*)p1)->Header.Type=EFI_HII_VARIABLE; + //pBS->CopyMem((VOID*)&(((EFI_HII_VARIABLE_PACK*)p1)->VariableGuid), + // &st->VarStore.Guid, sizeof(EFI_GUID)); + + ((EFI_HII_VARIABLE_PACK*)p1)->VariableGuid=st->VarStore->Guid; + ((EFI_HII_VARIABLE_PACK*)p1)->VariableId=st->VarStore->VarId; + + p=(UINT8*)(st->VarStore+1); + while(*p){ + *p2=*p; + p++; + p2+=sizeof(UINT16); + //per spec VariableLength goes in Bytes + ((EFI_HII_VARIABLE_PACK*)p1)->VariableNameLength+=sizeof(UINT16); + } + p2+=sizeof(UINT16); //Null terminaterd + ((EFI_HII_VARIABLE_PACK*)p1)->VariableNameLength+=sizeof(UINT16); + //Copy contents of the variable at present p2 + p=p1+sizeof(EFI_HII_VARIABLE_PACK); + sz=st->VarStore->Size; + Status=pRS->GetVariable((UINT16*)p,&st->VarStore->Guid,NULL,&sz,p2); + + DataTbl->NumberOfVariableData++; + //don't forget to update size of Var Data in Pack Header + ((EFI_HII_VARIABLE_PACK*)p1)->Header.Length=(UINT32)(p2+sz-p1); + + p1=p2+sz; + } + } + if(!DataTbl->NumberOfVariableData)DataTbl->VariableDataOffset=0; + else { // !! Add zero-terminating EFI HII variable + ((EFI_HII_VARIABLE_PACK*)p1)->Header.Type=EFI_HII_VARIABLE; + ((EFI_HII_VARIABLE_PACK*)p1)->Header.Length = sizeof(EFI_HII_VARIABLE_PACK); + p1 += sizeof(EFI_HII_VARIABLE_PACK); + } + //Formset goes data here + DataTbl->IfrDataOffset=(UINT32)(p1-(UINT8*)DataTbl); + p2=p1+sizeof(EFI_HII_PACK_HEADER); + ((EFI_HII_PACK_HEADER*)p1)->Length=(UINT32)fs->BufferLength+sizeof(EFI_HII_PACK_HEADER); + ((EFI_HII_PACK_HEADER*)p1)->Type=EFI_HII_IFR; + + i=0; + CopyFormSet(p2,fs,&i); + p1=p2+i; + } + //If HIIHandle Data don't have Strings make p2==p1 since we are returning p2 value + p2=p1; + //string data goes here + if(HiiHandle->HasStr){ + UINT8 *p=p1; + UINT32 li=(UINTN)-1; + //----------------- + DataTbl->StringDataOffset=(UINT32)(p1-(UINT8*)DataTbl); + for(i=0; i<gHiiDb.StringDb.RecordCount; i++){ + DbeGoToIndex(&gHiiDb.StringDb,STR_KEY,(UINTN)i,&str); + if(str->Handle==HiiHandle->Handle){ + + if((li==-1)||(li!=str->LangIdx)){ + //p1 points on the EFI_HII_STRING_PACK + p1=p; + ((EFI_HII_STRING_PACK*)p1)->Header.Type=EFI_HII_STRING; + DataTbl->NumberOfLanguages++; + //p2 points on the RELOFS array + p2=p1+sizeof(EFI_HII_STRING_PACK); + + li=str->LangIdx; + + ((EFI_HII_STRING_PACK*)p1)->NumStringPointers=CountStrOfLang(HiiHandle,i,li); + //p points on the UnicodeString; + p=p2+((EFI_HII_STRING_PACK*)p1)->NumStringPointers*sizeof(UINT32); + ((EFI_HII_STRING_PACK*)p1)->LanguageNameString=(UINT32)((UINTN)p-(UINTN)p1); + ((EFI_HII_STRING_PACK*)p1)->PrintableLanguageName=((EFI_HII_STRING_PACK*)p1)->LanguageNameString + +4*sizeof(CHAR16); + ((EFI_HII_STRING_PACK*)p1)->Header.Length=sizeof(EFI_HII_STRING_PACK)+ + ((EFI_HII_STRING_PACK*)p1)->NumStringPointers*sizeof(UINT32); + + } + //update offset table + *((UINT32*)p2)=(UINT32)((UINTN)p-(UINTN)p1); + //the StrLen stored in UNICODECHAR units including NULL CHAR16 + if(str->NewStr.StrPtr){ + pBS->CopyMem(p, str->NewStr.StrPtr, str->NewStr.StrLen*sizeof(CHAR16)); + p+=str->NewStr.StrLen*sizeof(CHAR16); + ((EFI_HII_STRING_PACK*)p1)->Header.Length+=str->NewStr.StrLen*sizeof(CHAR16); + } else { + pBS->CopyMem(p, str->String.StrPtr, str->String.StrLen*sizeof(CHAR16)); + p+=str->String.StrLen*sizeof(CHAR16); + ((EFI_HII_STRING_PACK*)p1)->Header.Length+=str->String.StrLen*sizeof(CHAR16); + } + p2+=sizeof(UINT32); + } + //don't forget to put terminator pack at the very end of the string data + if((str->Handle > HiiHandle->Handle) || (i==gHiiDb.StringDb.RecordCount-1)){ + //Create a terminator pack + p1=p; + ((EFI_HII_STRING_PACK*)p1)->Header.Type=EFI_HII_STRING; + p2=p1+sizeof(EFI_HII_STRING_PACK); + break; + } + } + } + + *BufferPointer=p2; + +} + + + +/////////////////////////////////////////////////////////////////// +EFI_STATUS HiiExport(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer ) +{ + UINTN sz, i; + HII_HANDLE *phnd=NULL; + EFI_HII_EXPORT_TABLE *expt=NULL; + EFI_HII_DATA_TABLE *cdt=NULL; + UINT8 *bp=NULL; +//---------------- + if(!This) return EFI_INVALID_PARAMETER; + + sz=sizeof(EFI_HII_EXPORT_TABLE); + + //Calculate buffer Size + for(i=0; i<gHiiDb.HandleDb.ItemCount; i++){ + phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[i]; + if(Handle && Handle!=phnd->Handle) continue; + sz+=GetHandleExpBuffSize(phnd,i) + sizeof(EFI_HII_DATA_TABLE); + } + //Check the buffer size provided + if(sz > *BufferSize){ + *BufferSize=sz; + return EFI_BUFFER_TOO_SMALL; + } + pBS->SetMem(Buffer, sz, 0); + //Export Table + expt=(EFI_HII_EXPORT_TABLE*)Buffer; + if((UINTN)This == (UINTN)&gHiiDb.HiiProtocolOld) expt->Revision=gEfiHiiProtocolGuidOld; + else expt->Revision=gEfiHiiProtocolGuidNew; + + bp=(UINT8*)(expt+1); + + //Start dumping the data + for(i=0 ; i<gHiiDb.HandleDb.ItemCount; i++){ + + phnd=(HII_HANDLE*)gHiiDb.HandleDb.Items[i]; + if(Handle && Handle!=phnd->Handle) continue; + //CurrentDataTable + cdt=(EFI_HII_DATA_TABLE*)bp; + bp+=sizeof(EFI_HII_DATA_TABLE); + + sz=GetHandleExpBuffSize(phnd,i); + + cdt->HiiHandle=phnd->Handle; + cdt->PackageGuid=phnd->Guid; + cdt->DataTableSize=(UINT32)(sz+sizeof(EFI_HII_DATA_TABLE)); + + ExportHandleData(phnd, i, cdt, &bp); +//debug+ just to test how bp gets incremented + ASSERT((UINTN)cdt+sizeof(EFI_HII_DATA_TABLE)+sz==(UINTN)bp); +//debug- + expt->NumberOfHiiDataTables++; + } + + return EFI_SUCCESS; +} + +EFI_STATUS GetVarStoreData(HII_FORMSET *FormSet, HII_STORE *VarData, UINT8* Buffer, UINTN DefaultMask){ + HII_LABEL *lbl; + HII_OBJECT *obj; + HII_FORM *frm; + EFI_IFR_OP_HEADER *op; + UINTN i,x,j,k,offs,len; +//------------------ + + for(i=0; i<FormSet->Forms.ItemCount; i++){ + frm=FormSet->Forms.Items[i]; + for(x=0; x< frm->Labels.ItemCount; x++){ + //iterate trough the Labels to get each HII_OBJECT + lbl=frm->Labels.Items[x]; + for(j=0; j<lbl->Objects.ItemCount; j++){ + //iterate trough the Objects to see if + obj=lbl->Objects.Items[j]; + + if( VarData->VarStore->VarId!=obj->Store1->VarStore->VarId || + MemCmp(&VarData->VarStore->Guid, &obj->Store1->VarStore->Guid, sizeof(EFI_GUID)) + ) continue; + + //we focused at the Object which has the same VarStore Properies as passed "VarData" + //So parse the object to see if it has any default flags set + op=obj->ObjectCode; + switch(op->OpCode){ + + //ONE_OF and ORDERED_LIST has almost the same encoding + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + { + EFI_IFR_ONE_OF_OPTION *opt; + //----------------------- + offs=((EFI_IFR_ONE_OF*)op)->QuestionId; + len=((EFI_IFR_ONE_OF*)op)->Width; + +//DEBUG CODE to check if update runs out of bound + if(offs>=VarData->VarStore->Size) { + ASSERT_EFI_ERROR(EFI_BUFFER_TOO_SMALL); + return EFI_BUFFER_TOO_SMALL; + } +//DEBUG CODE to check if update runs out of bound + + for(k=0; k<obj->Options.ItemCount; k++){ + opt=(EFI_IFR_ONE_OF_OPTION*)obj->Options.Items[k]; + //for ORDERED_LIST it would not be any Defaults + if(op->OpCode==EFI_IFR_ORDERED_LIST_OP){ + pBS->CopyMem(&Buffer[offs],&opt->Value, 1); + offs++; + +//DEBUG CODE to check if update runs out of bound + if(offs>=VarData->VarStore->Size) return EFI_BUFFER_TOO_SMALL; +//DEBUG CODE to check if update runs out of bound + + } else { + UINTN f=(UINTN)opt->Flags; + //------------------ + if (f & DefaultMask) { + pBS->CopyMem(&Buffer[offs],&opt->Value,len); + break; + } + } + } + }break; + + case EFI_IFR_CHECKBOX_OP: + { + EFI_IFR_CHECK_BOX *cb=(EFI_IFR_CHECK_BOX*)obj->ObjectCode; + UINTN f=(UINTN)cb->Flags; + //-------------------- + offs=cb->QuestionId; + +//DEBUG CODE to check if update runs out of bound + if(offs>=VarData->VarStore->Size) return EFI_BUFFER_TOO_SMALL; +//DEBUG CODE to check if update runs out of bound + + if(f & DefaultMask) Buffer[offs] = 1; + else Buffer[offs] = 0; + + } break; + + case EFI_IFR_NUMERIC_OP: + { + EFI_IFR_NUMERIC *num =(EFI_IFR_NUMERIC*)obj->ObjectCode; + //-------------------------- + offs=num->QuestionId; + len=num->Width; + +//DEBUG CODE to check if update runs out of bound + if(offs>=VarData->VarStore->Size) return EFI_BUFFER_TOO_SMALL; +//DEBUG CODE to check if update runs out of bound + + pBS->CopyMem(&Buffer[offs],&num->Default,len); + } break; + + } //switch(obj->ObjectCode->Opcode) + + } //for(j) loop + }//for(x) loop + } //for(i) loop + return EFI_SUCCESS; +} + + + +EFI_STATUS HiiGetDefaultImageNew(IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList) +{ + EFI_STATUS Status=EFI_NOT_FOUND; + UINTN i, j, k, hidx, vnl=0, tbsz=0; + HII_HANDLE *phnd; + EFI_HII_VARIABLE_PACK_LIST *vpl, *fvpl=NULL, *pvpl=NULL; + HII_FORMSET *fs; + HII_STORE *st; + UINT8 *pdb, *pnb; +//---------------------------------- + + //Check Parameters + if(This==NULL || VariablePackList==NULL || !Handle ) return EFI_INVALID_PARAMETER; + + //Find the handle + phnd=LocateHandle(Handle, &hidx); + if(phnd==NULL) return EFI_NOT_FOUND; + + //If no VarStores associated with passed Handle will return NULL + *VariablePackList=NULL; + + //If Handle Exists then find a FormSet associated with this Handle + fs=LocateFormSet(hidx, NULL); + //No formset found => no IFR data + if(fs==NULL) return EFI_NOT_FOUND; + + //Collect the Variable data + for(i=0, hidx=0; i<fs->Storages.ItemCount; i++){ + st=fs->Storages.Items[i]; + if(!st->VarStore->Size) continue; + + Status=EFI_SUCCESS; + hidx++; + //get the variable name length in bytes(ASCII) + vnl=st->VarStore->Header.Length-sizeof(EFI_IFR_VARSTORE); + //determine how much memory we need to accomodate + //EFI_VARIABLE_PACK_LIST + EFI_VARIABLE_PACK + VarName + VarData + vpl=MallocZ(sizeof(EFI_HII_VARIABLE_PACK_LIST)+ //EFI_VARIABLE_PACK_LIST + sizeof(EFI_HII_VARIABLE_PACK)+ //EFI_VARIABLE_PACK + (vnl*sizeof(UINT16))+ //EFI_VARIABLE_PACK has VarName in UINT16 + st->VarStore->Size); //Size of actual NV Var Data + + tbsz+=(sizeof(EFI_HII_VARIABLE_PACK_LIST)+ //EFI_VARIABLE_PACK_LIST + sizeof(EFI_HII_VARIABLE_PACK)+ //EFI_VARIABLE_PACK + (vnl*sizeof(UINT16))+ //EFI_VARIABLE_PACK has VarName in UINT16 + st->VarStore->Size); //Size of actual NV Var Data + + if(!vpl) return EFI_OUT_OF_RESOURCES; + + //determine where in VPL buffer Actual VAriable data suppose to start + pdb=(UINT8*)vpl+sizeof(EFI_HII_VARIABLE_PACK_LIST)+sizeof(EFI_HII_VARIABLE_PACK)+(vnl*sizeof(UINT16)); + + GetVarStoreData(fs,st,pdb,DefaultMask); + + //if this is the first structure in the list remember it we must return it's address + if(fvpl==NULL)fvpl=vpl; + //if PreviouseVariablePackList ptr was initialized update pointer to next VPL with current VPL + if(pvpl!=NULL)pvpl->NextVariablePack=vpl; + //reinitialize PreviouseVariablePackList ptr with current VPL pointer + pvpl=vpl; + + //Update context of the VariablePack pointer to the next data byte afer itself(per .92 spec) + vpl->VariablePack = (EFI_HII_VARIABLE_PACK*)(vpl+1); + + //Now fill out fields of HII_VARIABLE_PACK structure + vpl->VariablePack->Header.Type=EFI_HII_VARIABLE; + vpl->VariablePack->Header.Length=(UINT32)(sizeof(EFI_HII_VARIABLE_PACK)+(vnl*sizeof(UINT16))+st->VarStore->Size); + vpl->VariablePack->VariableId=st->VarStore->VarId; + vpl->VariablePack->VariableNameLength=(UINT32)(vnl*sizeof(UINT16)); // per spec length in bytes. + pBS->CopyMem(&vpl->VariablePack->VariableGuid, &st->VarStore->Guid, sizeof(EFI_GUID)); + //now copy Variable name "pdb" points at the befinning of VarName buffer + pdb=(UINT8*)vpl+sizeof(EFI_HII_VARIABLE_PACK_LIST)+sizeof(EFI_HII_VARIABLE_PACK); + pnb=(UINT8*)(st->VarStore+1); + //since in VARIABLE_PACKAGE VAR NAME is UNICODE simple MemCpy wouldn't do. + for(j=0,k=0; j<vnl; j++, k+=2) { + pdb[k]=pnb[j]; + } + } + + //Per Spec we have to dump all data in single buffer. + //Update the IN/OUT parameter + if(tbsz) { + *VariablePackList=Malloc(tbsz); + if(*VariablePackList==NULL) return EFI_OUT_OF_RESOURCES; + } else *VariablePackList=NULL; + vpl=fvpl; + pdb=(UINT8*)(*VariablePackList); + while (vpl){ + //copy Var_PACK_LIST + VARPACK to the Common Buffer + pBS->CopyMem(pdb,vpl,sizeof(EFI_HII_VARIABLE_PACK_LIST)+vpl->VariablePack->Header.Length); + pvpl=(EFI_HII_VARIABLE_PACK_LIST*)pdb; + pvpl->VariablePack=(EFI_HII_VARIABLE_PACK*)(pdb+sizeof(EFI_HII_VARIABLE_PACK_LIST)); + + pdb+=(sizeof(EFI_HII_VARIABLE_PACK_LIST)+vpl->VariablePack->Header.Length); + if(vpl->NextVariablePack!=NULL)pvpl->NextVariablePack=(EFI_HII_VARIABLE_PACK_LIST*)pdb; + + pvpl=vpl; + vpl=vpl->NextVariablePack; + + pBS->FreePool(pvpl); + } + + return Status; +} + + +/////////////////////////////////////////////////////////////////// +//Keyboard +EFI_STATUS HiiGetKeyboardLayout(IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor) +{ + HII_KB_LAYOUT_DATA *kbld; +//------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + + if(!gHiiDb.KeybdDb.KblCount) return EFI_NOT_FOUND; + + kbld=gHiiDb.KeybdDb.KbLayout[gHiiDb.KeybdDb.ActiveLayout]; + + //we got small buffer + if(*DescriptorCount<kbld->KeyDscCount) { + *DescriptorCount=kbld->KeyDscCount; + return EFI_BUFFER_TOO_SMALL; + } + + MemCpy((VOID*)Descriptor, (VOID*)kbld->KeyDsc, sizeof(EFI_KEY_DESCRIPTOR)*kbld->KeyDscCount); + + return EFI_SUCCESS; +} + + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//EXTENDED HII INTERFACE +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +EFI_STATUS HiiExtGetStringInfo( + IN EXT_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN CHAR16 *Lang, + OUT EXT_STR_INFO **ExtStrInfo) +{ + HII_STR *str; +//----------------------------------------- + if(!This || !ExtStrInfo ) return EFI_INVALID_PARAMETER; + + str=GetHiiString(Handle,Lang,Token); + if(!str) return EFI_NOT_FOUND; + + if(str->NewStr.StrPtr)*ExtStrInfo=&str->NewStr; + else *ExtStrInfo=&str->String; + + return EFI_SUCCESS; +} + + +EFI_STATUS HiiExtGetFormInfo(IN EXT_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + OUT HII_FORM **ExtFormInfo) +{ + HII_FORM *frm; + UINTN hi; + HII_HANDLE *phnd; + HII_FORMSET *fs; +//----------------------------------------- + if(!This || !ExtFormInfo ) return EFI_INVALID_PARAMETER; + + phnd=LocateHandle(Handle,&hi); + ASSERT(phnd); + if(!phnd)return EFI_NOT_FOUND; + + fs=LocateFormSet(hi,NULL); + ASSERT(fs); + if(!fs)return EFI_NOT_FOUND; + + frm=LocateForm(fs,FormId); + ASSERT(frm); + if(!frm)return EFI_NOT_FOUND; + *ExtFormInfo=frm; + + return EFI_SUCCESS; +} + + +EFI_STATUS HiiExtRegisterLabelUpdateCallback(IN EXT_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL LabelId, + IN HII_LABEL_UPDATE_CALLBACK CallBack) +{ + UINTN hi; + HII_LABEL *lbl; + HII_FORMSET *fs; +//---------------------------------- + if(!This || !CallBack ) return EFI_INVALID_PARAMETER; + + if(!LocateHandle(Handle, &hi)) return EFI_INVALID_PARAMETER; + + //Find Formset + fs=LocateFormSet(hi, NULL); + if(!fs) return EFI_INVALID_PARAMETER; + + lbl=LocateFormSetLabel(fs,LabelId,NULL); + if(!lbl) return EFI_NOT_FOUND; + + lbl->UpdateCallBack=CallBack; + + return EFI_SUCCESS; +} + +EFI_STATUS HiiExtUnregisterLabelUpdateCallback(IN EXT_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL LabelId) +{ + UINTN hi; + HII_LABEL *lbl; + HII_FORMSET *fs; +//---------------------------------- + if(!This) return EFI_INVALID_PARAMETER; + + if(!LocateHandle(Handle, &hi)) return EFI_INVALID_PARAMETER; + + //Find Formset + fs=LocateFormSet(hi, NULL); + if(!fs) return EFI_INVALID_PARAMETER; + + lbl=LocateFormSetLabel(fs,LabelId,NULL); + if(!lbl) return EFI_NOT_FOUND; + + lbl->UpdateCallBack=NULL; + + return EFI_SUCCESS; +} + +EFI_STATUS HiiExtGetFormSetInfo(IN EXT_HII_PROTOCOL *This, + IN UINT16 ClassMask, //if ==0xFFFF all Classes + IN UINT16 SubClass, //if ==0xFFFF all SubClasses + OUT T_ITEM_LIST *FormSetList) +{ + UINTN i; + HII_FORMSET *fs; +//------------------------------ + if(!This || !FormSetList) return EFI_INVALID_PARAMETER; + + //Make sure the list is empty + ClearItemLst(FormSetList,FALSE); + for(i=0; i<gHiiDb.IfrDb.ItemCount;i++){ + fs=gHiiDb.IfrDb.Items[i]; + if(SubClass!=0xFFFF && SubClass!=fs->FormSetData->SubClass) continue; + if((fs->FormSetData->Class & ClassMask)==fs->FormSetData->Class) AppendItemLst(FormSetList,fs); + } + return EFI_SUCCESS; +} + +EFI_STATUS HiiExtGetFormLabels(IN EXT_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormID, + OUT T_ITEM_LIST *LabelList) +{ + UINTN i; + HII_FORMSET *fs; + HII_FORM *frm; + HII_LABEL *lbl; + EFI_STATUS Status; +//----------------------------------------- + if(!This || !LabelList ) return EFI_INVALID_PARAMETER; + + if(!LocateHandle(Handle,&i)) return EFI_INVALID_PARAMETER;; + + fs=LocateFormSet(i,NULL); + ASSERT(fs); + if(!fs)return EFI_NOT_FOUND; + + frm=LocateForm(fs,FormID); + ASSERT(frm); + if(!frm)return EFI_NOT_FOUND; + + ClearItemLst(LabelList,FALSE); + for(i=1;i<frm->Labels.ItemCount;i++){ + lbl=frm->Labels.Items[i]; + Status=AppendItemLst(LabelList,lbl); + ASSERT(!EFI_ERROR(Status)); + if(EFI_ERROR(Status))return Status; + } + return EFI_SUCCESS; +} + + +/////////////////////////////////////////////////////////////////// +//Init All Private Data +EFI_STATUS InitPrivateData(EFI_HANDLE MyImgHandle){ + EFI_STATUS Status=0; + //HII_LANG *al;//any lang +//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST + EFI_HII_PACK_LIST *pl=Malloc(sizeof(EFI_HII_PACK_LIST)); + // {BB2F3C9D-C7A1-4283-8AE2-4F4362990E2E} + static EFI_GUID pguid={ 0xbb2f3c9d, 0xc7a1, 0x4283, 0x8a, 0xe2, 0x4f, 0x43, 0x62, 0x99, 0x0e, 0x2e }; + EFI_HII_HANDLE fph;//,sth; +// UINT16 bl; +// UINT8 *fsb; +//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST +//----------------------------- + pBS->SetMem(&gHiiDb, sizeof(HII_DB),0 ); + + gHiiDb.ImageHandle=MyImgHandle; + gHiiDb.NextHiiHandle=1; //Zero Handle is Invalid it must be 1 based + + //Create Any Langguage Entry - empty string L" " + Status=LocateLangAdd(L" ",L"Any Language",NULL); + if(EFI_ERROR(Status)) return Status; + + //Create and Initialize String Database + gHiiDb.StringDb.KeyCount=STR_KEY_CNT; + gHiiDb.StringDb.InitialCount=STRING_DB_MAX_COUNT; + gHiiDb.StringDb.KeyField=&gStrKey; + gHiiDb.StringDb.MemoryType=EfiBootServicesData; + gHiiDb.StringDb.RecordCount=0; + gHiiDb.StringDb.IndexArray=MallocZ(sizeof(VOID*)*gHiiDb.StringDb.InitialCount*gHiiDb.StringDb.KeyCount); + if(!gHiiDb.StringDb.IndexArray) return EFI_OUT_OF_RESOURCES; + + //Init Protocol Instance here + gHiiDb.HiiProtocolOld.NewPack=HiiNewPackOld; + gHiiDb.HiiProtocolNew.NewPack=HiiNewPackNew; + + gHiiDb.HiiProtocolOld.RemovePack=HiiRemovePack; + gHiiDb.HiiProtocolNew.RemovePack=HiiRemovePack; + + gHiiDb.HiiProtocolOld.FindHandles=HiiFindHandles; + gHiiDb.HiiProtocolNew.FindHandles=HiiFindHandles; + + gHiiDb.HiiProtocolOld.GetDefaultImage=HiiGetDefaultImageOld; + gHiiDb.HiiProtocolNew.GetDefaultImage=HiiGetDefaultImageNew; + + gHiiDb.HiiProtocolOld.TestString=HiiTestString; + gHiiDb.HiiProtocolNew.TestString=HiiTestString; + + gHiiDb.HiiProtocolOld.GetGlyph=HiiGetGlyph; + gHiiDb.HiiProtocolNew.GetGlyph=HiiGetGlyph; + + gHiiDb.HiiProtocolOld.GlyphToBlt=HiiGlyphToBlt; + gHiiDb.HiiProtocolNew.GlyphToBlt=HiiGlyphToBlt; + + gHiiDb.HiiProtocolOld.NewString=HiiNewString; + gHiiDb.HiiProtocolNew.NewString=HiiNewString; + + gHiiDb.HiiProtocolOld.GetPrimaryLanguages=HiiGetPrimaryLanguage; + gHiiDb.HiiProtocolNew.GetPrimaryLanguages=HiiGetPrimaryLanguage; + + gHiiDb.HiiProtocolOld.GetSecondaryLanguages=HiiGetSecondaryLanguages; + gHiiDb.HiiProtocolNew.GetSecondaryLanguages=HiiGetSecondaryLanguages; + + gHiiDb.HiiProtocolOld.GetString=HiiGetStringOld; + gHiiDb.HiiProtocolNew.GetString=HiiGetStringNew; + + gHiiDb.HiiProtocolOld.GetLine=HiiGetLine; + gHiiDb.HiiProtocolNew.GetLine=HiiGetLine; + + gHiiDb.HiiProtocolOld.GetForms=HiiGetFormsOld; + gHiiDb.HiiProtocolNew.GetForms=HiiGetFormsNew; + + gHiiDb.HiiProtocolOld.UpdateForm=HiiUpdateForm; + gHiiDb.HiiProtocolNew.UpdateForm=HiiUpdateForm; + + gHiiDb.HiiProtocolOld.GetKeyboardLayout=HiiGetKeyboardLayout; + gHiiDb.HiiProtocolNew.GetKeyboardLayout=HiiGetKeyboardLayout; + + gHiiDb.HiiProtocolOld.ResetStrings=HiiResetStrings; + gHiiDb.HiiProtocolNew.ResetStrings=HiiResetStrings; + + gHiiDb.HiiProtocolOld.ExportDatabase=HiiExport; + gHiiDb.HiiProtocolNew.ExportDatabase=HiiExport; + + //Now do Extended Hii Interface + gHiiDb.HiiExtProtocol.ExtGetStringInfo=HiiExtGetStringInfo; + gHiiDb.HiiExtProtocol.ExtGetFormInfo=HiiExtGetFormInfo; + gHiiDb.HiiExtProtocol.ExtGetFormsetInfo=HiiExtGetFormSetInfo; + gHiiDb.HiiExtProtocol.ExtRegLblCallBack=HiiExtRegisterLabelUpdateCallback; + gHiiDb.HiiExtProtocol.ExtUnregLblCallBack=HiiExtUnregisterLabelUpdateCallback; + gHiiDb.HiiExtProtocol.ExtGetFormLabels=HiiExtGetFormLabels; + + //------------------------------------ + //init Font Data + pl->FontPack=(EFI_HII_FONT_PACK*)&UsStdNarrowGlyphData; + pl->GuidId=&pguid; + pl->IfrPack=NULL;//(EFI_HII_IFR_PACK*)&FrontPageVfrBin; + pl->KeyboardPack=NULL; + pl->StringPack=NULL;//(EFI_HII_STRING_PACK*)&FrontPageStrings; +///// Load Font Pack +{ +#define FONT_FFS_FILE_GUID { 0xdac2b117, 0xb5fb, 0x4964, { 0xa3, 0x12, 0xd, 0xcc, 0x77, 0x6, 0x1b, 0x9b } } +static EFI_GUID guidFontFile = FONT_FFS_FILE_GUID; + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_PROTOCOL *pFV; + UINTN DataSize; + EFI_GUID *pSectionGuid = NULL; + UINT32 Authentication; + EFI_HANDLE *pHandle; + UINTN Number,i; + Status = pBS->LocateHandleBuffer(ByProtocol,&guidFV, NULL, &Number, &pHandle); + for(i=0;i<Number; i++) + { + Status=pBS->HandleProtocol(pHandle[i], &guidFV, &pFV); + if (EFI_ERROR(Status)) continue; + pSectionGuid=NULL; + DataSize=0; + Status=pFV->ReadSection ( + pFV,&guidFontFile, + EFI_SECTION_FREEFORM_SUBTYPE_GUID,0, &pSectionGuid, &DataSize, + &Authentication + ); + if (!EFI_ERROR(Status)) + { + pl->FontPack=(EFI_HII_FONT_PACK*)((UINT32*)(pSectionGuid+1)+1); + break; + } + } + Status=HiiNewPackOld((EFI_HII_PROTOCOL*)&gHiiDb.HiiProtocolOld,pl,&fph); + pBS->FreePool(pSectionGuid); +} +//////////////////// + if(EFI_ERROR(Status)) return Status; + +//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST +/* pl->FontPack=NULL; + pl->IfrPack=NULL; + pl->KeyboardPack=NULL; + pl->StringPack=(EFI_HII_STRING_PACK*)&SetupStrings; + + Status=HiiNewPack(&gHiiDb.HiiProtocol,pl,&sth); + if(EFI_ERROR(Status)) return Status; + + fsb=NULL; + bl=0; + Status=HiiGetForms(&gHiiDb.HiiProtocol,fph,0,&bl,fsb); + if(Status==EFI_BUFFER_TOO_SMALL); + else if(EFI_ERROR(Status)) return Status; + fsb=Malloc(bl); + if(!fsb) return EFI_OUT_OF_RESOURCES; + Status=HiiGetForms(&gHiiDb.HiiProtocol,fph,0,&bl,fsb); + + //Now, I'll try to ges some strings from FrontPageDb + { + UINT16 mystr[81]; + EFI_STRING plan, slan; + EFI_IFR_FORM_SET *fs=(EFI_IFR_FORM_SET*)fsb; + UINT32 gb,i=0; + //----------------------------------- + + Status=HiiGetPrimaryLanguage(&gHiiDb.HiiProtocol,fph,&plan); + //it might be more than 1 Sec Lang. + Status=HiiGetSecondaryLanguages(&gHiiDb.HiiProtocol,fph,plan,&slan); + + + bl=80; + + Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->FormSetTitle,TRUE,slan,&bl,&mystr[0]); + + Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->FormSetTitle,TRUE,plan,&bl,&mystr[0]); + + Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->Help,TRUE,slan,&bl,&mystr[0]); + + Status=HiiGetString(&gHiiDb.HiiProtocol,fph,fs->Help,TRUE,plan,&bl,&mystr[0]); + + Status=HiiTestString(&gHiiDb.HiiProtocol,&mystr[0],&i,&gb); + + } + +*/ +//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST//TEST + pBS->FreePool(pl); +// +// return pBS->InstallMultipleProtocolInterfaces( gHiiDb.ImageHandle, +// &gEfiHiiProtocolGuid,&gHiiDb.HiiProtocol,NULL,NULL); + return EFI_SUCCESS; +} + +//********************************************************************** +//********************************************************************** +//** ** +//** (C)Copyright 1985-2005, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 6145-F Northbelt Pkwy, Norcross, GA 30071 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//********************************************************************** +//********************************************************************** |