diff options
author | qwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-01-21 09:47:43 +0000 |
---|---|---|
committer | qwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524> | 2009-01-21 09:47:43 +0000 |
commit | 4c9c0f719df00f211790eadf04d21a93a0cdf76c (patch) | |
tree | 90a4d5a29da41787f75ac11191f707e8f2215f5e /EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk | |
parent | 96827f17562a5f055b7e14817f3388e881f33020 (diff) | |
download | edk2-platforms-4c9c0f719df00f211790eadf04d21a93a0cdf76c.tar.xz |
Rename module name from ***To*** to ***On***. AAAOnBBB means this module produce AAA Protocol/PPI based on BBB. This change improves the readability.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7328 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk')
24 files changed, 9646 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.c new file mode 100644 index 0000000000..6be0496c61 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.c @@ -0,0 +1,1078 @@ +/**@file
+ This file implements functions related to Config Access Protocols installed by
+ by HII Thunk Modules. These Config access Protocols are used to thunk UEFI Config
+ Access Callback to Framework HII Callback and EFI Variable Set/Get operations.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HiiDatabase.h"
+#include "UefiIfrParser.h"
+
+BOOLEAN mHiiPackageListUpdated = FALSE;
+
+CONFIG_ACCESS_PRIVATE gConfigAccessPrivateTempate = {
+ CONFIG_ACCESS_PRIVATE_SIGNATURE,
+ {
+ ThunkExtractConfig,
+ ThunkRouteConfig,
+ ThunkCallback
+ }, //ConfigAccessProtocol
+ NULL, //FormCallbackProtocol
+ NULL
+};
+
+/**
+ Get the first EFI_IFR_VARSTORE from the FormSet.
+
+ @param FormSet The Form Set.
+
+ @retval FORMSET_STORAGE * Return the first EFI_IFR_VARSTORE.
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.
+**/
+FORMSET_STORAGE *
+GetFirstStorageOfFormSet (
+ IN CONST FORM_BROWSER_FORMSET * FormSet
+ )
+{
+ LIST_ENTRY *StorageList;
+ FORMSET_STORAGE *Storage;
+
+ StorageList = GetFirstNode (&FormSet->StorageListHead);
+
+ if (!IsNull (&FormSet->StorageListHead, StorageList)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
+ return Storage;
+ }
+
+ return NULL;
+}
+
+/**
+ Get the EFI_IFR_VARSTORE where the Question's value is stored.
+
+ @param FormSet The Form Set.
+
+ @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE where the Question's value is stored.
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.
+**/
+FORMSET_STORAGE *
+GetStorageFromQuestionId (
+ IN CONST FORM_BROWSER_FORMSET * FormSet,
+ IN EFI_QUESTION_ID QuestionId
+ )
+{
+ LIST_ENTRY *FormList;
+ LIST_ENTRY *StatementList;
+ FORM_BROWSER_FORM *Form;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ FormList = GetFirstNode (&FormSet->FormListHead);
+
+ while (!IsNull (&FormSet->FormListHead, FormList)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (FormList);
+
+ StatementList = GetFirstNode (&Form->StatementListHead);
+
+ while (!IsNull (&Form->StatementListHead, StatementList)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);
+ if ((QuestionId == Statement->QuestionId) && (Statement->Storage != NULL)) {
+ //
+ // UEFI Question ID is unique in a FormSet.
+ //
+ ASSERT (Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER);
+ return Statement->Storage;
+ }
+ StatementList = GetNextNode (&Form->StatementListHead, StatementList);
+ }
+
+ FormList = GetNextNode (&FormSet->FormListHead, FormList);
+ }
+
+ return NULL;
+}
+
+/**
+ Get the EFI_IFR_VARSTORE based the ID.
+
+ @param FormSet The Form Set.
+
+ @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE with the ID.
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.
+**/
+FORMSET_STORAGE *
+GetStorageFromVarStoreId (
+ IN CONST FORM_BROWSER_FORMSET * FormSet,
+ IN EFI_VARSTORE_ID VarStoreId
+ )
+{
+ LIST_ENTRY *StorageList;
+ FORMSET_STORAGE *Storage;
+
+ StorageList = GetFirstNode (&FormSet->StorageListHead);
+
+ while (!IsNull (&FormSet->StorageListHead, StorageList)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
+
+ if (VarStoreId == Storage->VarStoreId) {
+ return Storage;
+ }
+
+ StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
+ }
+
+ return NULL;
+}
+
+/**
+ Get the EFI_IFR_VARSTORE based the <ConfigHdr> string in a <ConfigRequest>
+ or a <ConfigResp> string.
+
+ @param FormSet The Form Set.
+ @param ConfigString The Configuration String which is defined by UEFI HII.
+
+ @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE where the Question's value is stored.
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.
+**/
+FORMSET_STORAGE *
+GetStorageFromConfigString (
+ IN CONST FORM_BROWSER_FORMSET *FormSet,
+ IN CONST EFI_STRING ConfigString
+ )
+{
+ LIST_ENTRY *StorageList;
+ FORMSET_STORAGE *Storage;
+ CHAR16 *Name;
+
+ StorageList = GetFirstNode (&FormSet->StorageListHead);
+
+ while (!IsNull (&FormSet->StorageListHead, StorageList)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
+
+ if ((Storage->VarStoreId == FormSet->DefaultVarStoreId) && (FormSet->OriginalDefaultVarStoreName != NULL)) {
+ Name = FormSet->OriginalDefaultVarStoreName;
+ } else {
+ Name = Storage->Name;
+ }
+
+ if (IsConfigHdrMatch (ConfigString, &Storage->Guid, Name)) {
+ return Storage;
+ }
+
+ StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
+ }
+
+ return NULL;
+}
+
+/**
+ This function installs a EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered
+ by a module using Framework HII Protocol Interfaces.
+
+ UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
+ that Setup Utility can load the Buffer Storage using this protocol.
+
+ @param Packages The Package List.
+ @param ThunkContext The Thunk Context.
+
+ @retval EFI_SUCCESS The Config Access Protocol is installed successfully.
+ @retval EFI_OUT_RESOURCE There is not enough memory.
+
+**/
+EFI_STATUS
+InstallDefaultConfigAccessProtocol (
+ IN CONST EFI_HII_PACKAGES *Packages,
+ IN OUT HII_THUNK_CONTEXT *ThunkContext
+ )
+{
+ EFI_STATUS Status;
+ CONFIG_ACCESS_PRIVATE *ConfigAccessInstance;
+
+ ASSERT (ThunkContext->IfrPackageCount != 0);
+
+ Status = HiiLibCreateHiiDriverHandle (&ThunkContext->UefiHiiDriverHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ ConfigAccessInstance = AllocateCopyPool (
+ sizeof (CONFIG_ACCESS_PRIVATE),
+ &gConfigAccessPrivateTempate
+ );
+ ASSERT (ConfigAccessInstance != NULL);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ThunkContext->UefiHiiDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ &ConfigAccessInstance->ConfigAccessProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ConfigAccessInstance->ThunkContext = ThunkContext;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function un-installs the EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered
+ by a module using Framework HII Protocol Interfaces.
+
+ ASSERT if no Config Access is found for such pakcage list or failed to uninstall the protocol.
+
+ @param ThunkContext The Thunk Context.
+
+**/
+VOID
+UninstallDefaultConfigAccessProtocol (
+ IN HII_THUNK_CONTEXT *ThunkContext
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+
+ HiiLibDestroyHiiDriverHandle (ThunkContext->UefiHiiDriverHandle);
+
+ Status = gBS->HandleProtocol (
+ ThunkContext->UefiHiiDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->UninstallProtocolInterface (
+ ThunkContext->UefiHiiDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ ConfigAccess
+ );
+ ASSERT_EFI_ERROR (Status);
+
+}
+
+
+/**
+ Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvRead.
+
+ @param BufferStorage The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.
+ @param FwFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.
+ @param Data The data read.
+ @param DataSize The size of data.
+
+ @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.
+ @retval EFI_INVALID_PARAMETER If the EFI_FORM_CALLBACK_PROTOCOL.NvRead return the size information of the data
+ does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.
+ **/
+EFI_STATUS
+CallFormCallBack (
+ IN FORMSET_STORAGE *BufferStorage,
+ IN EFI_FORM_CALLBACK_PROTOCOL *FwFormCallBack,
+ OUT VOID **Data,
+ OUT UINTN *DataSize
+ )
+{
+ EFI_STATUS Status;
+
+ *DataSize = 0;
+ *Data = NULL;
+
+ Status = FwFormCallBack->NvRead (
+ FwFormCallBack,
+ BufferStorage->Name,
+ &BufferStorage->Guid,
+ NULL,
+ DataSize,
+ *Data
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if (BufferStorage->Size != *DataSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Data = AllocateZeroPool (*DataSize);
+ if (Data == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FwFormCallBack->NvRead (
+ FwFormCallBack,
+ BufferStorage->Name,
+ &BufferStorage->Guid,
+ NULL,
+ DataSize,
+ *Data
+ );
+ }
+
+ return Status;
+}
+
+
+/**
+ Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Get Service.
+
+ @param BufferStorage The key with all attributes needed to call a UEFI Variable Get Service.
+ @param Data The data read.
+ @param DataSize The size of data.
+
+ If the UEFI Variable Get Service return the size information of the data
+ does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.
+ then ASSERT.
+
+ @retval EFI_STATUS The status returned by the UEFI Variable Get Service.
+ @retval EFI_INVALID_PARAMETER If the UEFI Variable Get Service return the size information of the data
+ does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.
+ **/
+
+EFI_STATUS
+GetUefiVariable (
+ IN FORMSET_STORAGE *BufferStorage,
+ OUT VOID **Data,
+ OUT UINTN *DataSize
+ )
+{
+ EFI_STATUS Status;
+
+ *DataSize = 0;
+ *Data = NULL;
+ Status = gRT->GetVariable (
+ BufferStorage->Name,
+ &BufferStorage->Guid,
+ NULL,
+ DataSize,
+ *Data
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+ if (BufferStorage->Size != *DataSize) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Data = AllocateZeroPool (*DataSize);
+ if (Data == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gRT->GetVariable (
+ BufferStorage->Name,
+ &BufferStorage->Guid,
+ NULL,
+ DataSize,
+ *Data
+ );
+ }
+
+ return Status;
+}
+
+/**
+
+ This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig
+ so that data can be read from the data storage such as UEFI Variable or module's
+ customized storage exposed by EFI_FRAMEWORK_CALLBACK.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
+ @param Request A null-terminated Unicode string in <ConfigRequest> format. Note that this
+ includes the routing information as well as the configurable name / value pairs. It is
+ invalid for this string to be in <MultiConfigRequest> format.
+
+ @param Progress On return, points to a character in the Request string. Points to the string's null
+ terminator if request was successful. Points to the most recent '&' before the first
+ failing name / value pair (or the beginning of the string if the failure is in the first
+ name / value pair) if the request was not successful
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which has all
+ values filled in for the names in the Request string. String to be allocated by the called
+ function.
+
+ @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.
+ @retval EFI_SUCCESS The setting is retrived successfully.
+ @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.
+ **/
+EFI_STATUS
+EFIAPI
+ThunkExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ )
+{
+ EFI_STATUS Status;
+ CONFIG_ACCESS_PRIVATE *ConfigAccess;
+ FORMSET_STORAGE *BufferStorage;
+ VOID *Data;
+ UINTN DataSize;
+
+ if (Request == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Data = NULL;
+ ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);
+
+ BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);
+
+ if (BufferStorage == NULL) {
+ *Progress = (EFI_STRING) Request;
+ return EFI_NOT_FOUND;
+ }
+
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {
+ //
+ // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.
+ //
+ if (ConfigAccess->FormCallbackProtocol == NULL ||
+ ConfigAccess->FormCallbackProtocol->NvRead == NULL) {
+ Status = GetUefiVariable (
+ BufferStorage,
+ &Data,
+ &DataSize
+ );
+ } else {
+ Status = CallFormCallBack (
+ BufferStorage,
+ ConfigAccess->FormCallbackProtocol,
+ &Data,
+ &DataSize
+ );
+ }
+ } else {
+ //
+ // Use the NvMapOverride.
+ //
+ DataSize = BufferStorage->Size;
+ Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);
+
+ if (Data != NULL) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = mHiiConfigRoutingProtocol->BlockToConfig (
+ mHiiConfigRoutingProtocol,
+ Request,
+ Data,
+ DataSize,
+ Results,
+ Progress
+ );
+ }
+
+ if (Data != NULL) {
+ FreePool (Data);
+ }
+ return Status;
+}
+
+/**
+ This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig
+ so that data can be written to the data storage such as UEFI Variable or module's
+ customized storage exposed by EFI_FRAMEWORK_CALLBACK.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
+ @param Configuration A null-terminated Unicode string in <ConfigResp> format.
+ @param Progress A pointer to a string filled in with the offset of the most recent '&' before the first
+ failing name / value pair (or the beginning of the string if the failure is in the first
+ name / value pair) or the terminating NULL if all was successful.
+
+ @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.
+ @retval EFI_SUCCESS The setting is saved successfully.
+ @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.
+**/
+EFI_STATUS
+EFIAPI
+ThunkRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STATUS Status;
+ CONFIG_ACCESS_PRIVATE *ConfigAccess;
+ FORMSET_STORAGE *BufferStorage;
+ VOID *Data;
+ UINTN DataSize;
+ UINTN DataSize2;
+ UINTN LastModifiedByteIndex;
+ BOOLEAN ResetRequired;
+ BOOLEAN DataAllocated;
+
+ if (Configuration == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = NULL;
+ ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);
+
+ BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Configuration);
+
+ if (BufferStorage == NULL) {
+ *Progress = Configuration;
+ return EFI_NOT_FOUND;
+ }
+
+ DataSize2 = BufferStorage->Size;
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {
+ DataAllocated = TRUE;
+ if (ConfigAccess->FormCallbackProtocol == NULL ||
+ ConfigAccess->FormCallbackProtocol->NvRead == NULL) {
+ Status = GetUefiVariable (
+ BufferStorage,
+ &Data,
+ &DataSize
+ );
+ } else {
+ Status = CallFormCallBack (
+ BufferStorage,
+ ConfigAccess->FormCallbackProtocol,
+ &Data,
+ &DataSize
+ );
+ }
+ } else {
+ //
+ // ConfigToBlock will convert the Config String and update the NvMapOverride accordingly.
+ //
+ Status = EFI_SUCCESS;
+ Data = ConfigAccess->ThunkContext->NvMapOverride;
+ DataSize = DataSize2;
+ DataAllocated = FALSE;
+ }
+ if (EFI_ERROR (Status) || (DataSize2 != DataSize)) {
+ if (Data == NULL) {
+ Data = AllocateZeroPool (DataSize2);
+ }
+ }
+
+ Status = mHiiConfigRoutingProtocol->ConfigToBlock (
+ mHiiConfigRoutingProtocol,
+ Configuration,
+ Data,
+ &LastModifiedByteIndex,
+ Progress
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {
+ if (ConfigAccess->FormCallbackProtocol == NULL ||
+ ConfigAccess->FormCallbackProtocol->NvWrite == NULL) {
+ Status = gRT->SetVariable (
+ BufferStorage->Name,
+ &BufferStorage->Guid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize2,
+ Data
+ );
+ } else {
+ Status = ConfigAccess->FormCallbackProtocol->NvWrite (
+ ConfigAccess->FormCallbackProtocol,
+ BufferStorage->Name,
+ &BufferStorage->Guid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize2,
+ Data,
+ &ResetRequired
+ );
+
+ }
+ }
+
+Done:
+ if (DataAllocated && (Data != NULL)) {
+ FreePool (Data);
+ }
+
+ return Status;
+}
+
+/**
+ Build the FRAMEWORK_EFI_IFR_DATA_ARRAY which will be used to pass to
+ EFI_FORM_CALLBACK_PROTOCOL.Callback. Check definition of FRAMEWORK_EFI_IFR_DATA_ARRAY
+ for details.
+
+ ASSERT if the Question Type is not EFI_IFR_TYPE_NUM_SIZE_* or EFI_IFR_TYPE_STRING.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
+ @param QuestionId The Question ID.
+ @param Type The Question Type.
+ @param Value The Question Value.
+ @param NvMapAllocated On output indicates if a buffer is allocated for NvMap.
+
+ @return A pointer to FRAMEWORK_EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated.
+**/
+FRAMEWORK_EFI_IFR_DATA_ARRAY *
+CreateIfrDataArray (
+ IN CONFIG_ACCESS_PRIVATE *ConfigAccess,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT BOOLEAN *NvMapAllocated
+ )
+{
+ FRAMEWORK_EFI_IFR_DATA_ARRAY *IfrDataArray;
+ FRAMEWORK_EFI_IFR_DATA_ENTRY *IfrDataEntry;
+ UINTN BrowserDataSize;
+ FORMSET_STORAGE *BufferStorage;
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN StringSize;
+ EFI_STRING String;
+
+ *NvMapAllocated = FALSE;
+
+ String = NULL;
+
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ case EFI_IFR_TYPE_BOOLEAN:
+ Size = sizeof (*Value);
+ break;
+
+ case EFI_IFR_TYPE_STRING:
+ StringSize = 0;
+ Status = HiiLibGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, String, &StringSize);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ String = AllocateZeroPool (StringSize);
+ ASSERT (String != NULL);
+
+ Status = HiiLibGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, String, &StringSize);
+ ASSERT_EFI_ERROR (Status);
+
+ Size = StringSize;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ Size = 0;
+ break;
+ }
+
+ IfrDataArray = AllocateZeroPool (sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY) + sizeof (FRAMEWORK_EFI_IFR_DATA_ENTRY) + Size);
+ ASSERT (IfrDataArray != NULL);
+
+ BufferStorage = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);
+
+ if (BufferStorage == NULL) {
+ //
+ // The QuestionId is not associated with a Buffer Storage.
+ // Try to get the first Buffer Storage then.
+ //
+ BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);
+ }
+
+ if (BufferStorage != NULL) {
+ BrowserDataSize = BufferStorage->Size;
+
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {
+ *NvMapAllocated = TRUE;
+ IfrDataArray->NvRamMap = AllocateZeroPool (BrowserDataSize);
+ } else {
+ *NvMapAllocated = FALSE;
+ IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride;
+ }
+
+ Status = GetBrowserData (&BufferStorage->Guid, BufferStorage->Name, &BrowserDataSize, IfrDataArray->NvRamMap);
+ ASSERT_EFI_ERROR (Status);
+
+ IfrDataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1);
+
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ case EFI_IFR_TYPE_BOOLEAN:
+ CopyMem (&IfrDataEntry->Data, &(Value->u8), sizeof (*Value));
+ break;
+
+ case EFI_IFR_TYPE_STRING:
+ ASSERT (String != NULL);
+ StrCpy ((CHAR16 *) &IfrDataEntry->Data, String);
+ FreePool (String);
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ //
+ // Need to fiil in the information for the rest of field for FRAMEWORK_EFI_IFR_DATA_ENTRY.
+ // It seems that no implementation is found to use other fields. Leave them uninitialized for now.
+ //
+ //UINT8 OpCode; // Likely a string, numeric, or one-of
+ //UINT8 Length; // Length of the FRAMEWORK_EFI_IFR_DATA_ENTRY packet
+ //UINT16 Flags; // Flags settings to determine what behavior is desired from the browser after the callback
+ //VOID *Data; // The data in the form based on the op-code type - this is not a pointer to the data, the data follows immediately
+ // If the OpCode is a OneOf or Numeric type - Data is a UINT16 value
+ // If the OpCode is a String type - Data is a CHAR16[x] type
+ // If the OpCode is a Checkbox type - Data is a UINT8 value
+ // If the OpCode is a NV Access type - Data is a FRAMEWORK_EFI_IFR_NV_DATA structure
+ }
+
+ return IfrDataArray;
+}
+
+/**
+ If a NvMapOverride is passed in to EFI_FORM_BROWSER_PROTOCOL.SendForm, the Form Browser
+ needs to be informed when data changed in NvMapOverride. This function will invoke
+ SetBrowserData () to set internal data of Form Browser.
+
+ @param ConfigAccess The Config Access Private Context.
+ @param QuestionId The Question Id that invokes the callback.
+
+
+**/
+VOID
+SyncBrowserDataForNvMapOverride (
+ IN CONST CONFIG_ACCESS_PRIVATE *ConfigAccess,
+ IN EFI_QUESTION_ID QuestionId
+ )
+{
+ FORMSET_STORAGE *BufferStorage;
+ EFI_STATUS Status;
+ UINTN BrowserDataSize;
+
+ if (ConfigAccess->ThunkContext->NvMapOverride != NULL) {
+
+ BufferStorage = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);
+
+ if (BufferStorage == NULL) {
+ //
+ // QuestionId is a statement without Storage.
+ // 1) It is a Goto.
+ //
+ //
+ BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);
+ }
+
+ //
+ // If NvMapOverride is not NULL, this Form must have at least one Buffer Type Variable Storage.
+ //
+ ASSERT (BufferStorage != NULL);
+
+ BrowserDataSize = BufferStorage->Size;
+
+ Status = SetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, ConfigAccess->ThunkContext->NvMapOverride, NULL);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+}
+
+/**
+ Free up resource allocated for a FRAMEWORK_EFI_IFR_DATA_ARRAY by CreateIfrDataArray ().
+
+ @param Array The FRAMEWORK_EFI_IFR_DATA_ARRAY allocated.
+ @param NvMapAllocated If the NvRamMap is allocated for FRAMEWORK_EFI_IFR_DATA_ARRAY.
+
+**/
+VOID
+DestroyIfrDataArray (
+ IN FRAMEWORK_EFI_IFR_DATA_ARRAY *Array,
+ IN BOOLEAN NvMapAllocated
+ )
+{
+ if (Array != NULL) {
+ if (NvMapAllocated) {
+ FreePool (Array->NvRamMap);
+ }
+
+ FreePool (Array);
+ }
+}
+
+/**
+ Get the ONE_OF_OPTION_MAP_ENTRY for a QuestionId that invokes the
+ EFI_FORM_CALLBACK_PROTOCOL.Callback. The information is needed as
+ the callback mechanism for EFI_IFR_ONE_OF_OPTION is changed from
+ EFI_IFR_ONE_OF_OPTION in Framework IFR. Check EFI_IFR_GUID_OPTIONKEY
+ for detailed information.
+
+ @param ThunkContext The Thunk Context.
+ @param QuestionId The Question Id.
+ @param Type The Question Type.
+ @param Value The One Of Option's value.
+
+ @return The ONE_OF_OPTION_MAP_ENTRY found.
+ @retval NULL If no entry is found.
+**/
+ONE_OF_OPTION_MAP_ENTRY *
+GetOneOfOptionMapEntry (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link2;
+ ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;
+ ONE_OF_OPTION_MAP *OneOfOptionMap;
+ FORM_BROWSER_FORMSET *FormSet;
+
+ FormSet = ThunkContext->FormSet;
+
+ Link = GetFirstNode (&FormSet->OneOfOptionMapListHead);
+
+ while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) {
+ OneOfOptionMap = ONE_OF_OPTION_MAP_FROM_LINK(Link);
+ if (OneOfOptionMap->QuestionId == QuestionId) {
+ ASSERT (OneOfOptionMap->ValueType == Type);
+
+ Link2 = GetFirstNode (&OneOfOptionMap->OneOfOptionMapEntryListHead);
+
+ while (!IsNull (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2)) {
+ OneOfOptionMapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);
+
+ if (CompareMem (Value, &OneOfOptionMapEntry->Value, sizeof (EFI_IFR_TYPE_VALUE)) == 0) {
+ return OneOfOptionMapEntry;
+ }
+
+ Link2 = GetNextNode (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2);
+ }
+ }
+
+ Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link);
+ }
+
+
+ return NULL;
+}
+
+/**
+ Functions which are registered to receive notification of
+ database events have this prototype. The actual event is encoded
+ in NotifyType. The following table describes how PackageType,
+ PackageGuid, Handle, and Package are used for each of the
+ notification types.
+
+ If any Pakcage List in database is updated, mHiiPackageListUpdated
+ will be set. If mHiiPackageListUpdated is set, Framework ThunkCallback()
+ will force the UEFI Setup Browser to save the uncommitted data. This
+ is needed as Framework's Callback function may dynamically update
+ opcode in a Package List. UEFI Setup Browser will quit itself and reparse
+ the Package List's IFR and display it. UEFI Config Access's implementation
+ is required to save the modified (SetBrowserData or directly save the data
+ to NV storage). But Framework HII Modules is not aware of this rule. Therefore,
+ we will enforce the rule in ThunkCallback (). The side effect of force saving
+ of NV data is the NV flag in browser may not flag a update as data has already
+ been saved to NV storage.
+
+ @param PackageType Package type of the notification.
+
+ @param PackageGuid If PackageType is
+ EFI_HII_PACKAGE_TYPE_GUID, then this is
+ the pointer to the GUID from the Guid
+ field of EFI_HII_PACKAGE_GUID_HEADER.
+ Otherwise, it must be NULL.
+
+ @param Package Points to the package referred to by the
+ notification Handle The handle of the package
+ list which contains the specified package.
+
+ @param Handle The HII handle.
+
+ @param NotifyType The type of change concerning the
+ database. See
+ EFI_HII_DATABASE_NOTIFY_TYPE.
+
+**/
+EFI_STATUS
+EFIAPI
+FormUpdateNotify (
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+ )
+{
+ mHiiPackageListUpdated = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.CallBack to EFI_FORM_CALLBACK_PROTOCOL.Callback. Therefor,
+ the framework HII module willl do no porting and work with a UEFI HII SetupBrowser.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.
+ @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the
+ type of data to expect. The format of the data tends to vary based on the opcode that
+ generated the callback.
+ @param Type The type of value for the question. See EFI_IFR_TYPE_x in
+ EFI_IFR_ONE_OF_OPTION.
+ @param Value A pointer to the data being sent to the original exporting driver. The type is specified
+ by Type. Type EFI_IFR_TYPE_VALUE is defined in
+ EFI_IFR_ONE_OF_OPTION.
+ @param ActionRequest On return, points to the action requested by the callback function. Type
+ EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form
+ Browser Protocol.
+
+ @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under
+ focuse to be INTERRACTIVE.
+ @retval EFI_SUCCESS The callback complete successfully.
+ @retval !EFI_SUCCESS The error code returned by EFI_FORM_CALLBACK_PROTOCOL.Callback.
+
+ **/
+EFI_STATUS
+EFIAPI
+ThunkCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ )
+{
+ EFI_STATUS Status;
+ CONFIG_ACCESS_PRIVATE *ConfigAccess;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;
+ EFI_HII_CALLBACK_PACKET *Packet;
+ FRAMEWORK_EFI_IFR_DATA_ARRAY *Data;
+ FRAMEWORK_EFI_IFR_DATA_ENTRY *DataEntry;
+ UINT16 KeyValue;
+ ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;
+ EFI_HANDLE NotifyHandle;
+ EFI_INPUT_KEY Key;
+ BOOLEAN NvMapAllocated;
+
+ ASSERT (This != NULL);
+ ASSERT (Value != NULL);
+ ASSERT (ActionRequest != NULL);
+
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
+
+ ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);
+
+ FormCallbackProtocol = ConfigAccess->FormCallbackProtocol;
+ if (FormCallbackProtocol == NULL) {
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check if the QuestionId match a OneOfOption.
+ //
+ OneOfOptionMapEntry = GetOneOfOptionMapEntry (ConfigAccess->ThunkContext, QuestionId, Type, Value);
+
+ if (OneOfOptionMapEntry == NULL) {
+ //
+ // This is not a One-Of-Option opcode. QuestionId is the KeyValue
+ //
+ KeyValue = QuestionId;
+ } else {
+ //
+ // Otherwise, use the original Key specified in One Of Option in the Framework VFR syntax.
+ //
+ KeyValue = OneOfOptionMapEntry->FwKey;
+ }
+
+ //
+ // Build the FRAMEWORK_EFI_IFR_DATA_ARRAY
+ //
+ Data = CreateIfrDataArray (ConfigAccess, QuestionId, Type, Value, &NvMapAllocated);
+
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_FORMS,
+ NULL,
+ FormUpdateNotify,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ &NotifyHandle
+ );
+ //
+ //Call the Framework Callback function.
+ //
+ Packet = NULL;
+ Status = FormCallbackProtocol->Callback (
+ FormCallbackProtocol,
+ KeyValue,
+ Data,
+ &Packet
+ );
+ SyncBrowserDataForNvMapOverride (ConfigAccess, QuestionId);
+
+ //
+ // Callback require browser to perform action
+ //
+ if (EFI_ERROR (Status)) {
+ if (Packet != NULL) {
+ do {
+ IfrLibCreatePopUp (1, &Key, Packet->String);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ }
+ //
+ // Error Code in Status is discarded.
+ //
+ } else {
+ if (Packet != NULL) {
+ if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {
+ DataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY));
+ if ((DataEntry->Flags & EXIT_REQUIRED) == EXIT_REQUIRED) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ }
+
+ if ((DataEntry->Flags & SAVE_REQUIRED) == SAVE_REQUIRED) {
+ Status = ConfigAccess->ConfigAccessProtocol.RouteConfig (
+ &ConfigAccess->ConfigAccessProtocol,
+ NULL,
+ NULL
+ );
+ }
+ }
+ FreePool (Packet);
+ }
+ }
+
+ //
+ // Unregister notify for Form package update
+ //
+ Status = mHiiDatabase->UnregisterPackageNotify (
+ mHiiDatabase,
+ NotifyHandle
+ );
+ //
+ // UEFI SetupBrowser behaves differently with Framework SetupBrowser when call back function
+ // update any forms in HII database. UEFI SetupBrowser will re-parse the displaying form package and load
+ // the values from variable storages. Framework SetupBrowser will only re-parse the displaying form packages.
+ // To make sure customer's previous changes is saved and the changing question behaves as expected, we
+ // issue a EFI_BROWSER_ACTION_REQUEST_SUBMIT to ask UEFI SetupBrowser to save the changes proceed to re-parse
+ // the form and load all the variable storages.
+ //
+ if (*ActionRequest == EFI_BROWSER_ACTION_REQUEST_NONE && mHiiPackageListUpdated) {
+ mHiiPackageListUpdated= FALSE;
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
+ } else {
+ if (ConfigAccess->ThunkContext->FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS ||
+ ConfigAccess->ThunkContext->FormSet->SubClass == EFI_SINGLE_USE_SUBCLASS) {
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
+ }
+ }
+
+
+ //
+ // Clean up.
+ //
+ DestroyIfrDataArray (Data, NvMapAllocated);
+
+ return Status;
+}
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.h new file mode 100644 index 0000000000..c26f456620 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/ConfigAccess.h @@ -0,0 +1,139 @@ +/**@file
+ This file contains functions related to Config Access Protocols installed by
+ by HII Thunk Modules which is used to thunk UEFI Config Access Callback to
+ Framework HII Callback.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HII_THUNK_CONFIG_ACCESS_H
+#define _HII_THUNK_CONFIG_ACCESS_H
+
+/**
+ This function installs a EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered
+ by a module using Framework HII Protocol Interfaces.
+
+ UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
+ that Setup Utility can load the Buffer Storage using this protocol.
+
+ @param Packages The framework package list.
+ @param ThunkContext The Thunk Layer Handle Mapping Database Entry.
+
+ @retval EFI_SUCCESS The Config Access Protocol is installed successfully.
+ @retval EFI_OUT_RESOURCE There is not enough memory.
+
+**/
+EFI_STATUS
+InstallDefaultConfigAccessProtocol (
+ IN CONST EFI_HII_PACKAGES *Packages,
+ IN OUT HII_THUNK_CONTEXT *ThunkContext
+ );
+
+VOID
+UninstallDefaultConfigAccessProtocol (
+ IN HII_THUNK_CONTEXT *ThunkContext
+ );
+
+/**
+
+ This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig
+ so that data can be read from the data storage such as UEFI Variable or module's
+ customized storage exposed by EFI_FRAMEWORK_CALLBACK.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
+ @param Request A null-terminated Unicode string in <ConfigRequest> format. Note that this
+ includes the routing information as well as the configurable name / value pairs. It is
+ invalid for this string to be in <MultiConfigRequest> format.
+
+ @param Progress On return, points to a character in the Request string. Points to the string's null
+ terminator if request was successful. Points to the most recent '&' before the first
+ failing name / value pair (or the beginning of the string if the failure is in the first
+ name / value pair) if the request was not successful
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which has all
+ values filled in for the names in the Request string. String to be allocated by the called
+ function.
+
+ @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.
+ @retval EFI_SUCCESS The setting is retrived successfully.
+ @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.
+ **/
+EFI_STATUS
+EFIAPI
+ThunkExtractConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Request,
+ OUT EFI_STRING *Progress,
+ OUT EFI_STRING *Results
+ );
+
+
+/**
+
+ This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig
+ so that data can be written to the data storage such as UEFI Variable or module's
+ customized storage exposed by EFI_FRAMEWORK_CALLBACK.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL
+ @param Configuration A null-terminated Unicode string in <ConfigResp> format.
+ @param Progress A pointer to a string filled in with the offset of the most recent '&' before the first
+ failing name / value pair (or the beginning of the string if the failure is in the first
+ name / value pair) or the terminating NULL if all was successful.
+
+ @retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.
+ @retval EFI_SUCCESS The setting is saved successfully.
+ @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.
+**/
+EFI_STATUS
+EFIAPI
+ThunkRouteConfig (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN CONST EFI_STRING Configuration,
+ OUT EFI_STRING *Progress
+ );
+
+/**
+ Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.CallBack to EFI_FORM_CALLBACK_PROTOCOL.Callback. Therefor,
+ the framework HII module willl do no porting (except some porting works needed for callback for EFI_ONE_OF_OPTION opcode)
+ and still work with a UEFI HII SetupBrowser.
+
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+ @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.
+ @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the
+ type of data to expect. The format of the data tends to vary based on the opcode that
+ generated the callback.
+ @param Type The type of value for the question. See EFI_IFR_TYPE_x in
+ EFI_IFR_ONE_OF_OPTION.
+ @param Value A pointer to the data being sent to the original exporting driver. The type is specified
+ by Type. Type EFI_IFR_TYPE_VALUE is defined in
+ EFI_IFR_ONE_OF_OPTION.
+ @param ActionRequest On return, points to the action requested by the callback function. Type
+ EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form
+ Browser Protocol.
+
+ @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under
+ focuse to be INTERRACTIVE.
+ @retval EFI_SUCCESS The callback complete successfully.
+ @retval !EFI_SUCCESS The error code returned by EFI_FORM_CALLBACK_PROTOCOL.Callback.
+
+ **/
+EFI_STATUS
+EFIAPI
+ThunkCallback (
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
+ IN EFI_BROWSER_ACTION Action,
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT8 Type,
+ IN EFI_IFR_TYPE_VALUE *Value,
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
+ );
+
+#endif
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Fonts.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Fonts.c new file mode 100644 index 0000000000..27b5d95fbd --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Fonts.c @@ -0,0 +1,187 @@ +/**@file
+ This file contains the Glyph related function.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiDatabase.h"
+
+EFI_NARROW_GLYPH mNarrowGlyphBuffer = {0, 0, {0}};
+
+BOOLEAN mSysFontColorCached = FALSE;
+EFI_GRAPHICS_OUTPUT_BLT_PIXEL mSysFGColor = {0};
+
+
+/**
+ Translates a Unicode character into the corresponding font glyph.
+
+ Notes:
+ This function is only called by Graphics Console module and GraphicsLib.
+ Wrap the Framework HII GetGlyph function to UEFI Font Protocol.
+
+ EDK II provides a UEFI Graphics Console module. ECP provides a GraphicsLib
+ complying to UEFI HII.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Source A pointer to a Unicode string.
+ @param Index On input, the offset into the string from which to fetch the character. On successful completion, the
+ index is updated to the first character past the character(s) making up the just extracted glyph.
+ @param GlyphBuffer Pointer to an array where the glyphs corresponding to the characters in the source may be stored.
+ GlyphBuffer is assumed to be wide enough to accept a wide glyph character.
+ @param BitWidth If EFI_SUCCESS was returned, the UINT16 pointed to by this value is filled with the length of the glyph in pixels.
+ It is unchanged if the call was unsuccessful.
+ @param InternalStatus To save the time required to read the string from the beginning on each glyph extraction
+ (for example, to ensure that the narrow versus wide glyph mode is correct), this value is
+ updated each time the function is called with the status that is local to the call. The cell pointed
+ to by this parameter must be initialized to zero prior to invoking the call the first time for any string.
+
+ @retval EFI_SUCCESS It worked.
+ @retval EFI_NOT_FOUND A glyph for a character was not found.
+
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Source,
+ IN OUT UINT16 *Index,
+ OUT UINT8 **GlyphBuffer,
+ OUT UINT16 *BitWidth,
+ IN OUT UINT32 *InternalStatus
+ )
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_OUTPUT *Blt;
+ EFI_FONT_DISPLAY_INFO *FontInfo;
+ UINTN Xpos;
+ UINTN Ypos;
+ UINTN BaseLine;
+
+ if (!mSysFontColorCached) {
+ //
+ // Cache the system font's foreground color.
+ //
+ Status = mHiiFontProtocol->GetFontInfo (
+ mHiiFontProtocol,
+ NULL,
+ NULL,
+ &FontInfo,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ASSERT (StrCmp (FontInfo->FontInfo.FontName, L"sysdefault") == 0);
+ mSysFGColor = FontInfo->ForegroundColor;
+ FreePool (FontInfo);
+
+ mSysFontColorCached = TRUE;
+ }
+
+ }
+
+ Blt = NULL;
+ Status = mHiiFontProtocol->GetGlyph (
+ mHiiFontProtocol,
+ Source[*Index],
+ NULL,
+ &Blt,
+ &BaseLine
+ );
+
+ if (!EFI_ERROR (Status) && (Status != EFI_WARN_UNKNOWN_GLYPH)) {
+ //
+ // For simplicity, we only handle Narrow Glyph.
+ //
+ if (Blt->Height == EFI_GLYPH_HEIGHT && Blt->Width == EFI_GLYPH_WIDTH) {
+
+ ZeroMem (&mNarrowGlyphBuffer, sizeof (mNarrowGlyphBuffer));
+ mNarrowGlyphBuffer.UnicodeWeight = *Source;
+ for (Ypos = 0; Ypos < EFI_GLYPH_HEIGHT; Ypos++) {
+ for (Xpos = 0; Xpos < EFI_GLYPH_WIDTH; Xpos++) {
+ if (CompareMem (&Blt->Image.Bitmap[Ypos * EFI_GLYPH_WIDTH + Xpos], &mSysFGColor, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) == 0) {
+ mNarrowGlyphBuffer.GlyphCol1[Ypos] = (UINT8) (mNarrowGlyphBuffer.GlyphCol1[Ypos] | (1 << (EFI_GLYPH_WIDTH - 1 - Xpos)));
+ }
+ }
+ }
+
+ *GlyphBuffer = (UINT8 *) &mNarrowGlyphBuffer;
+ *BitWidth = EFI_GLYPH_WIDTH;
+ *Index += 1;
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+
+ }
+
+ if (EFI_ERROR (Status) || (Status == EFI_WARN_UNKNOWN_GLYPH)) {
+ if (Status == EFI_WARN_UNKNOWN_GLYPH) {
+ Status = EFI_NOT_FOUND;
+ }
+ *GlyphBuffer = NULL;
+ }
+ return Status;
+}
+
+/**
+ Translates a glyph into the format required for input to the Universal Graphics Adapter (UGA) Block Transfer (BLT) routines.
+
+ Notes:
+ This function is only called by Graphics Console module and GraphicsLib.
+ EDK II provides a UEFI Graphics Console module. ECP provides a GraphicsLib
+ complying to UEFI HII.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param GlyphBuffer A pointer to the buffer that contains glyph data.
+ @param Foreground The foreground setting requested to be used for the generated BltBuffer data. Type EFI_UGA_PIXEL is defined in "Related Definitions" below.
+ @param Background The background setting requested to be used for the generated BltBuffer data.
+ @param Count The entry in the BltBuffer upon which to act.
+ @param Width The width in bits of the glyph being converted.
+ @param Height The height in bits of the glyph being converted
+ @param BltBuffer A pointer to the buffer that contains the data that is ready to be used by the UGA BLT routines.
+
+ @retval EFI_SUCCESS It worked.
+ @retval EFI_NOT_FOUND A glyph for a character was not found.
+
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGlyphToBlt (
+ IN EFI_HII_PROTOCOL *This,
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN Count,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ )
+{
+ UINTN X;
+ UINTN Y;
+
+ //
+ // Convert Monochrome bitmap of the Glyph to BltBuffer structure
+ //
+ for (Y = 0; Y < Height; Y++) {
+ for (X = 0; X < Width; X++) {
+ if ((((EFI_NARROW_GLYPH *) GlyphBuffer)->GlyphCol1[Y] & (1 << X)) != 0) {
+ BltBuffer[Y * Width * Count + (Width - X - 1)] = Foreground;
+ } else {
+ BltBuffer[Y * Width * Count + (Width - X - 1)] = Background;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Forms.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Forms.c new file mode 100644 index 0000000000..efc205e919 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Forms.c @@ -0,0 +1,576 @@ +/**@file
+ This file contains the form processing code to the HII database.
+
+Copyright (c) 2006 - 2008 Intel Corporation. <BR>
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiDatabase.h"
+#include "UefiIfrDefault.h"
+
+//
+// This structure is only intended to be used in this file.
+//
+#pragma pack(1)
+typedef struct {
+ EFI_HII_PACK_HEADER PackageHeader;
+ FRAMEWORK_EFI_IFR_FORM_SET FormSet;
+ FRAMEWORK_EFI_IFR_END_FORM_SET EndFormSet;
+} FW_HII_FORMSET_TEMPLATE;
+#pragma pack()
+
+FW_HII_FORMSET_TEMPLATE FormSetTemplate = {
+ {
+ sizeof (FW_HII_FORMSET_TEMPLATE),
+ EFI_HII_IFR
+ },
+ {
+ {
+ FRAMEWORK_EFI_IFR_FORM_SET_OP,
+ sizeof (FRAMEWORK_EFI_IFR_FORM_SET)
+ },
+ {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}, //Guid
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ },
+ {
+ {
+ FRAMEWORK_EFI_IFR_END_FORM_SET_OP,
+ sizeof (FRAMEWORK_EFI_IFR_END_FORM_SET)
+ }
+ }
+};
+
+
+EFI_GUID mTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;
+
+/**
+
+ This thunk module only handles UEFI HII packages. The caller of this function
+ won¡¯t be able to parse the content. Therefore, it is not supported.
+
+ This function will ASSERT and return EFI_UNSUPPORTED.
+
+ @param This N.A.
+ @param Handle N.A.
+ @param BufferSize N.A.
+ @param Buffer N.A.
+
+ @retval EFI_UNSUPPORTED
+
+**/
+EFI_STATUS
+EFIAPI
+HiiExportDatabase (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ This function allows a program to extract a form or form package that has
+ previously been registered with the EFI HII database.
+
+ In this thunk module, this function will create a IFR Package with only
+ one Formset. Effectively, only the GUID of the Formset is updated and return
+ in this IFR package to caller. This is enable the Framework modules which call
+ a API named GetStringFromToken. GetStringFromToken retieves a String based on
+ a String Token from a Package List known only by the Formset GUID.
+
+
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle Handle on which the form resides. Type FRAMEWORK_EFI_HII_HANDLE is defined in
+ EFI_HII_PROTOCOL.NewPack() in the Packages section.
+ @param FormId Ignored by this implementation.
+ @param BufferLengthTemp On input, the size of input buffer. On output, it
+ is the size of FW_HII_FORMSET_TEMPLATE.
+ @param Buffer The buffer designed to receive the form(s).
+
+ @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength
+ was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form on the requested handle cannot be found with the
+ requested FormId.
+ @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to allow the form to be stored.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetForms (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINTN *BufferLengthTemp,
+ OUT UINT8 *Buffer
+ )
+{
+ HII_THUNK_PRIVATE_DATA *Private;
+ HII_THUNK_CONTEXT *ThunkContext;
+ FW_HII_FORMSET_TEMPLATE *OutputFormSet;
+
+ if (*BufferLengthTemp < sizeof(FW_HII_FORMSET_TEMPLATE)) {
+ *BufferLengthTemp = sizeof(FW_HII_FORMSET_TEMPLATE);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
+
+ if (ThunkContext == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ OutputFormSet = (FW_HII_FORMSET_TEMPLATE *) Buffer;
+
+ CopyMem (OutputFormSet, &FormSetTemplate, sizeof (FW_HII_FORMSET_TEMPLATE));
+ CopyMem (&OutputFormSet->FormSet.Guid, &ThunkContext->TagGuid, sizeof (EFI_GUID));
+
+ if (ThunkContext->FormSet != NULL) {
+ OutputFormSet->FormSet.Class = ThunkContext->FormSet->Class;
+ OutputFormSet->FormSet.SubClass = ThunkContext->FormSet->SubClass;
+ OutputFormSet->FormSet.Help = ThunkContext->FormSet->Help;
+ OutputFormSet->FormSet.FormSetTitle = ThunkContext->FormSet->FormSetTitle;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ This function allows a program to extract the NV Image
+ that represents the default storage image
+
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle The HII handle from which will have default data retrieved.
+ UINTN - Mask used to retrieve the default image.
+ @param DefaultMask EDES_TODO: Add parameter description
+ @param VariablePackList Callee allocated, tightly-packed, link list data
+ structure that contain all default varaible packs
+ from the Hii Database.
+
+ @retval EFI_NOT_FOUND If Hii database does not contain any default images.
+ @retval EFI_INVALID_PARAMETER Invalid input parameter.
+ @retval EFI_SUCCESS Operation successful.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetDefaultImage (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ )
+{
+ LIST_ENTRY *UefiDefaults;
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
+ if (ThunkContext == NULL) {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UefiDefaults = NULL;
+ Status = UefiIfrGetBufferTypeDefaults (ThunkContext, &UefiDefaults);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = UefiDefaultsToFwDefaults (UefiDefaults, DefaultMask, ThunkContext->FormSet->DefaultVarStoreId, VariablePackList);
+
+Done:
+ FreeDefaultList (UefiDefaults);
+
+ return Status;
+}
+
+/**
+ This function update the FormCallbackProtocol cached in Config Access
+ private context data.
+
+ @param CallbackHandle The EFI Handle on which the Framework FormCallbackProtocol is
+ installed.
+ @param ThunkContext The Thunk Context.
+
+ @retval EFI_SUCCESS The update is successful.
+ @retval EFI_INVALID_PARAMETER If no Framework FormCallbackProtocol is located on CallbackHandle.
+
+**/
+EFI_STATUS
+UpdateFormCallBack (
+ IN EFI_HANDLE CallbackHandle,
+ IN CONST HII_THUNK_CONTEXT *ThunkContext
+ )
+{
+ EFI_STATUS Status;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccessProtocol;
+ EFI_HANDLE UefiDriverHandle;
+ CONFIG_ACCESS_PRIVATE *ConfigAccessPrivate;
+
+ Status = gBS->HandleProtocol (
+ CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallbackProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = mHiiDatabase->GetPackageListHandle (
+ mHiiDatabase,
+ ThunkContext->UefiHiiHandle,
+ &UefiDriverHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->HandleProtocol (
+ UefiDriverHandle,
+ &gEfiHiiConfigAccessProtocolGuid,
+ (VOID **) &ConfigAccessProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ConfigAccessPrivate = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (ConfigAccessProtocol);
+
+ ConfigAccessPrivate->FormCallbackProtocol = FormCallbackProtocol;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get the package data from the Package List.
+
+ @param HiiPackageList Package List.
+ @param PackageIndex The index of the Package in the Package List.
+ @param BufferLen The Length of the Pacage data.
+ @param Buffer On output, the Package data.
+
+ @return EFI_NOT_FOUND No Package is found for PackageIndex.
+ @return EFI_SUCCESS The package data is returned.
+
+**/
+EFI_STATUS
+GetPackageData (
+ IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
+ IN UINT32 PackageIndex,
+ OUT UINT32 *BufferLen,
+ OUT EFI_HII_PACKAGE_HEADER **Buffer
+ )
+{
+ UINT32 Index;
+ EFI_HII_PACKAGE_HEADER *Package;
+ UINT32 Offset;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0};
+
+ ASSERT(HiiPackageList != NULL);
+
+ if ((BufferLen == NULL) || (Buffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Package = NULL;
+ Index = 0;
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+ while (Offset < PackageListLength) {
+ Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+ if (Index == PackageIndex) {
+ break;
+ }
+ Offset += PackageHeader.Length;
+ Index++;
+ }
+ if (Offset >= PackageListLength) {
+ //
+ // no package found in this Package List
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ *BufferLen = PackageHeader.Length;
+ *Buffer = Package;
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if Label exist in the IFR form package and return the FormSet GUID
+ and Form ID.
+
+ @param Package The Package Header.
+ @param Label The Label ID.
+ @param FormsetGuid Returns the FormSet GUID.
+ @param FormId Returns the Form ID.
+
+ @retval EFI_SUCCESS The FORM ID is found.
+ @retval EFI_NOT_FOUND The FORM ID is not found.
+**/
+EFI_STATUS
+LocateLabel (
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_FORM_LABEL Label,
+ OUT EFI_GUID *FormsetGuid,
+ OUT EFI_FORM_ID *FormId
+ )
+{
+ UINTN Offset;
+ EFI_IFR_OP_HEADER *IfrOpHdr;
+ EFI_GUID InternalFormSetGuid;
+ EFI_FORM_ID InternalFormId;
+ BOOLEAN GetFormSet;
+ BOOLEAN GetForm;
+ EFI_IFR_GUID_LABEL *LabelOpcode;
+
+ IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
+ Offset = sizeof (EFI_HII_PACKAGE_HEADER);
+
+ InternalFormId= 0;
+ ZeroMem (&InternalFormSetGuid, sizeof (EFI_GUID));
+ GetFormSet = FALSE;
+ GetForm = FALSE;
+
+ while (Offset < Package->Length) {
+ switch (IfrOpHdr->OpCode) {
+ case EFI_IFR_FORM_SET_OP :
+ CopyMem (&InternalFormSetGuid, &((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, sizeof (EFI_GUID));
+ GetFormSet = TRUE;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ CopyMem (&InternalFormId, &((EFI_IFR_FORM *) IfrOpHdr)->FormId, sizeof (EFI_FORM_ID));
+ GetForm = TRUE;
+ break;
+
+ case EFI_IFR_GUID_OP :
+ LabelOpcode = (EFI_IFR_GUID_LABEL *) IfrOpHdr;
+ //
+ // If it is an Label opcode.
+ //
+ if ((LabelOpcode->ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) && (CompareMem (&LabelOpcode->Guid, &mTianoHiiIfrGuid, sizeof (EFI_GUID)) == 0)) {
+ if (CompareMem (&Label, &LabelOpcode->Number, sizeof (UINT16)) == 0) {
+ ASSERT (GetForm && GetFormSet);
+ CopyGuid (FormsetGuid, &InternalFormSetGuid);
+ *FormId = InternalFormId;
+ return EFI_SUCCESS;
+ }
+ }
+ break;
+ default :
+ break;
+ }
+
+ //
+ // Go to the next Op-Code
+ //
+ Offset += IfrOpHdr->Length;
+ IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Find the first EFI_FORM_LABEL in FormSets for a given EFI_HII_HANLDE defined.
+
+ EFI_FORM_LABEL is a specific to Tiano implementation. The current implementation
+ does not restrict labels with same label value to be duplicated in either FormSet
+ scope or Form scope. This function will only locate the FIRST EFI_FORM_LABEL
+ with value as the same as the input Label in the Formset registered with UefiHiiHandle. The FormSet GUID
+ and Form ID is returned if such Label is found.
+
+
+ @retval EFI_INVALID_PARAMETER If UefiHiiHandle is not a valid handle.
+ @retval EFI_NOT_FOUND The package list identified by UefiHiiHandle deos not contain FormSet or
+ There is no Form ID with value Label found in all Form Sets in the pacakge
+ list.
+
+ @retval EFI_SUCCESS The first found Form ID is returned in FormId.
+**/
+EFI_STATUS
+LocateFormId (
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ OUT EFI_GUID *FormsetGuid,
+ OUT EFI_FORM_ID *FormId
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINT32 Index;
+ UINTN BufferSize;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ EFI_HII_PACKAGE_HEADER *Package;
+ UINT32 PackageLength;
+
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ for (Index = 0; ; Index++) {
+ Status = GetPackageData (HiiPackageList, Index, &PackageLength, &Package);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
+ Status = LocateLabel (Package, Label, FormsetGuid, FormId);
+ if (!EFI_ERROR(Status)) {
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+
+
+Done:
+ FreePool (HiiPackageList);
+
+ return Status;
+}
+
+/**
+ This function allows the caller to update a form that has
+ previously been registered with the EFI HII database.
+
+
+ @param This EDES_TODO: Add parameter description
+ @param Handle Hii Handle associated with the Formset to modify
+ @param Label Update information starting immediately after this label in the IFR
+ @param AddData If TRUE, add data. If FALSE, remove data
+ @param Data If adding data, this is the pointer to the data to add
+
+ @retval EFI_SUCCESS Update success.
+ @retval Other Update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiUpdateForm (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ IN BOOLEAN AddData,
+ IN FRAMEWORK_EFI_HII_UPDATE_DATA *Data
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ HII_THUNK_CONTEXT *ThunkContext;
+ EFI_HII_UPDATE_DATA *UefiHiiUpdateData;
+ EFI_HII_HANDLE UefiHiiHandle;
+ EFI_GUID FormsetGuid;
+ EFI_FORM_ID FormId;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ mInFrameworkUpdatePakcage = TRUE;
+ Status = EFI_SUCCESS;
+ UefiHiiUpdateData = NULL;
+
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
+
+ if (ThunkContext == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ if (Data->FormSetUpdate) {
+ Status = UpdateFormCallBack ((EFI_HANDLE) (UINTN) Data->FormCallbackHandle, ThunkContext);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ if (ThunkContext->IfrPackageCount == 0) {
+ ASSERT (FALSE);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ } else {
+ UefiHiiHandle = ThunkContext->UefiHiiHandle;
+ }
+
+ Status = LocateFormId (UefiHiiHandle, Label, &FormsetGuid, &FormId);
+ if (EFI_ERROR (Status)) {
+ //
+ // Can't find the label.
+ //
+ goto Done;
+ }
+
+ if (AddData) {
+ if (Data->DataCount != 0) {
+
+ ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
+ Status = FwUpdateDataToUefiUpdateData (ThunkContext, Data, &UefiHiiUpdateData);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, TRUE, UefiHiiUpdateData);
+ ASSERT_EFI_ERROR (Status);
+
+ }
+ } else {
+ //
+ // Delete Opcode starting from Labe in FormId found
+ //
+ UefiHiiUpdateData = AllocateZeroPool (sizeof (*UefiHiiUpdateData));
+
+ Status = IfrLibUpdateForm (UefiHiiHandle, &FormsetGuid, FormId, Label, FALSE, UefiHiiUpdateData);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+Done:
+ if (UefiHiiUpdateData != NULL) {
+ if (UefiHiiUpdateData->Data != NULL) {
+ FreePool (UefiHiiUpdateData->Data);
+ }
+ FreePool (UefiHiiUpdateData);
+ }
+
+ mInFrameworkUpdatePakcage = FALSE;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf new file mode 100644 index 0000000000..d1343adf5b --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/FrameworkHiiToUefiHiiThunk.inf @@ -0,0 +1,108 @@ +#/** @file
+# Component description file for HiiDatabase module which produce a Framework HII Protocol instance
+# based on the avaliable UEFI HII protocol found in the platform. This modules enables modules complying
+# to Framework HII specification to able to run on a UEFI HII platform with only a rebuild. This is
+# to ensure that all HII packages are generated by UEFI HII package generation tools (UEFI VfrCompiler and
+# String Gather Tools). This thunk layer only produces the Frameowork HII protocol interface. The binary package
+# data format complying to UEFI HII specification.
+#
+# This module inits HII database and installs HII protocol based on the avaliable UEFI HII protocol found in the platform..
+# Copyright (c) 2006 - 2008, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FrameworkHiiToUefiHiiThunk
+ FILE_GUID = AC3435BB-B1D3-4EF8-957C-8048606FF671
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeHiiDatabase
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ SetupBrowser.c
+ HiiHandle.c
+ HiiHandle.h
+ ConfigAccess.c
+ ConfigAccess.h
+ OpcodeCreation.c
+ UefiIfrParser.c
+ UefiIfrParser.h
+ UefiIfrParserExpression.c
+ UefiIfrParserExpression.h
+ UefiIfrDefault.c
+ UefiIfrDefault.h
+ Keyboard.c
+ Fonts.c
+ Package.c
+ Strings.c
+ Forms.c
+ HiiDatabase.h
+ HiiDatabase.c
+ Utility.c
+ Utility.h
+ Strings.uni
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[LibraryClasses]
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ DebugLib
+ BaseLib
+ HiiLib
+ ExtendedHiiLib
+ IfrSupportLib
+ ExtendedIfrSupportLib
+ PrintLib
+ UefiLib
+ PcdLib
+
+[Protocols]
+ gEfiHiiImageProtocolGuid
+ gEfiHiiDatabaseProtocolGuid
+ gEfiHiiStringProtocolGuid
+ gEfiHiiFontProtocolGuid
+ gEfiHiiConfigRoutingProtocolGuid
+ gEfiHiiConfigAccessProtocolGuid
+ gEfiFormCallbackProtocolGuid
+ gEfiUnicodeCollation2ProtocolGuid
+ gEfiHiiCompatibilityProtocolGuid
+ gEfiFormBrowserCompatibilityProtocolGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformBootTimeOutDefault
+
+[Depex]
+ gEfiHiiDatabaseProtocolGuid AND
+ gEfiHiiStringProtocolGuid AND
+ gEfiHiiConfigRoutingProtocolGuid AND
+ gEfiHiiFontProtocolGuid AND
+ gEfiFormBrowser2ProtocolGuid
+
+
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c new file mode 100644 index 0000000000..1bf17c174c --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.c @@ -0,0 +1,528 @@ +/**@file
+Framework to UEFI 2.1 HII Thunk. The driver consume UEFI HII protocols
+to produce a Framework HII protocol.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HiiDatabase.h"
+#include "HiiHandle.h"
+
+HII_THUNK_PRIVATE_DATA *mHiiThunkPrivateData;
+
+HII_THUNK_PRIVATE_DATA mHiiThunkPrivateDataTempate = {
+ HII_THUNK_PRIVATE_DATA_SIGNATURE,
+ (EFI_HANDLE) NULL,
+ {
+ HiiNewPack,
+ HiiRemovePack,
+ HiiFindHandles,
+ HiiExportDatabase,
+
+ HiiTestString,
+ HiiGetGlyph,
+ HiiGlyphToBlt,
+
+ HiiNewString,
+ HiiGetPrimaryLanguages,
+ HiiGetSecondaryLanguages,
+ HiiGetString,
+ HiiResetStrings,
+ HiiGetLine,
+ HiiGetForms,
+ HiiGetDefaultImage,
+ HiiUpdateForm,
+
+ HiiGetKeyboardLayout
+ },
+
+ {
+ ///
+ /// HiiHandleLinkList
+ ///
+ NULL, NULL
+ },
+};
+
+EFI_FORMBROWSER_THUNK_PRIVATE_DATA mBrowserThunkPrivateDataTemplate = {
+ EFI_FORMBROWSER_THUNK_PRIVATE_DATA_SIGNATURE,
+ (EFI_HANDLE) NULL,
+ (HII_THUNK_PRIVATE_DATA *) NULL,
+ {
+ ThunkSendForm,
+ ThunkCreatePopUp
+ }
+};
+
+
+CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol;
+CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol;
+CONST EFI_HII_FONT_PROTOCOL *mHiiFontProtocol;
+CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol;
+CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2Protocol;
+
+
+/**
+ This routine initializes the HII Database.
+
+ @param ImageHandle Image handle for PCD DXE driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCCESS The entry point alwasy return successfully.
+**/
+EFI_STATUS
+EFIAPI
+InitializeHiiDatabase (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferLength;
+ EFI_HII_HANDLE *Buffer;
+ UINTN Index;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiHiiCompatibilityProtocolGuid);
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiFormBrowserCompatibilityProtocolGuid);
+
+ Private = AllocateCopyPool (sizeof (HII_THUNK_PRIVATE_DATA), &mHiiThunkPrivateDataTempate);
+ ASSERT (Private != NULL);
+ InitializeListHead (&Private->ThunkContextListHead);
+
+ InitHiiHandleDatabase ();
+
+ mHiiThunkPrivateData = Private;
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **) &mHiiDatabase
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiStringProtocolGuid,
+ NULL,
+ (VOID **) &mHiiStringProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiFontProtocolGuid,
+ NULL,
+ (VOID **) &mHiiFontProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiConfigRoutingProtocolGuid,
+ NULL,
+ (VOID **) &mHiiConfigRoutingProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ Status = gBS->LocateProtocol (
+ &gEfiFormBrowser2ProtocolGuid,
+ NULL,
+ (VOID **) &mFormBrowser2Protocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+
+
+ //
+ // Install protocol interface
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Private->Handle,
+ &gEfiHiiCompatibilityProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *) &Private->Hii
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = HiiLibListPackageLists (EFI_HII_PACKAGE_STRINGS, NULL, &BufferLength, &Buffer);
+ if (Status == EFI_SUCCESS) {
+ for (Index = 0; Index < BufferLength / sizeof (EFI_HII_HANDLE); Index++) {
+ ThunkContext = CreateThunkContextForUefiHiiHandle (Buffer[Index]);
+ ASSERT (ThunkContext!= NULL);
+
+ InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
+ }
+
+ FreePool (Buffer);
+ }
+
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_STRINGS,
+ NULL,
+ NewOrAddPackNotify,
+ EFI_HII_DATABASE_NOTIFY_NEW_PACK,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_STRINGS,
+ NULL,
+ NewOrAddPackNotify,
+ EFI_HII_DATABASE_NOTIFY_ADD_PACK,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_FORMS,
+ NULL,
+ NewOrAddPackNotify,
+ EFI_HII_DATABASE_NOTIFY_NEW_PACK,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_FORMS,
+ NULL,
+ NewOrAddPackNotify,
+ EFI_HII_DATABASE_NOTIFY_ADD_PACK,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mHiiDatabase->RegisterPackageNotify (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_STRINGS,
+ NULL,
+ RemovePackNotify,
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
+ &Handle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ InitSetBrowserStrings ();
+
+ mBrowserThunkPrivateDataTemplate.ThunkPrivate = Private;
+ Status = gBS->InstallProtocolInterface (
+ &mBrowserThunkPrivateDataTemplate.Handle,
+ &gEfiFormBrowserCompatibilityProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *) &mBrowserThunkPrivateDataTemplate.FormBrowser
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Determines the handles that are currently active in the database.
+
+ This function determines the handles that are currently active in the database.
+ For example, a program wishing to create a Setup-like configuration utility would use this call
+ to determine the handles that are available. It would then use calls defined in the forms section
+ below to extract forms and then interpret them.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param HandleBufferLength On input, a pointer to the length of the handle buffer.
+ On output, the length of the handle buffer that is required for the handles found.
+ @param Handle An array of EFI_HII_HANDLE instances returned.
+ Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack() in the Packages section.
+
+ @retval EFI_SUCCESS Handle was updated successfully.
+
+ @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates that Handle is too small
+ to support the number of handles. HandleBufferLength is updated with a value that
+ will enable the data to fit.
+**/
+EFI_STATUS
+EFIAPI
+HiiFindHandles (
+ IN EFI_HII_PROTOCOL *This,
+ IN OUT UINT16 *HandleBufferLength,
+ OUT FRAMEWORK_EFI_HII_HANDLE Handle[1]
+ )
+{
+ UINT16 Count;
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+ HII_THUNK_PRIVATE_DATA *Private;
+
+ if (HandleBufferLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ //
+ // Count the number of handles.
+ //
+ Count = 0;
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+ Count++;
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+ if (Count > *HandleBufferLength) {
+ *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Output the handles.
+ //
+ Count = 0;
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+ Handle[Count] = ThunkContext->FwHiiHandle;
+
+ Count++;
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+
+ }
+
+ *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+LangCodes3066To639 (
+ IN CHAR8 *LangCodes3066,
+ IN CHAR8 **LangCodes639
+ )
+{
+ CHAR8 *AsciiLangCodes;
+ CHAR8 Lang[RFC_3066_ENTRY_SIZE];
+ UINTN Index;
+ UINTN Count;
+ EFI_STATUS Status;
+
+ ASSERT (LangCodes3066 != NULL);
+ ASSERT (LangCodes639 != NULL);
+
+ //
+ // Count the number of RFC 3066 language codes.
+ //
+ Index = 0;
+ AsciiLangCodes = LangCodes3066;
+ while (AsciiStrLen (AsciiLangCodes) != 0) {
+ HiiLibGetNextLanguage (&AsciiLangCodes, Lang);
+ Index++;
+ }
+
+ Count = Index;
+
+ //
+ //
+ //
+ *LangCodes639 = AllocateZeroPool (ISO_639_2_ENTRY_SIZE * Count + 1);
+ if (*LangCodes639 == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AsciiLangCodes = LangCodes3066;
+
+ for (Index = 0; Index < Count; Index++) {
+ HiiLibGetNextLanguage (&AsciiLangCodes, Lang);
+ Status = ConvertRfc3066LanguageToIso639Language (Lang, *LangCodes639 + Index * ISO_639_2_ENTRY_SIZE);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Allows a program to determine the primary languages that are supported on a given handle.
+
+ This routine is intended to be used by drivers to query the interface database for supported languages.
+ This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack()
+ in the Packages section.
+ @param LanguageString A string allocated by GetPrimaryLanguages() that contains a list of all primary languages
+ registered on the handle. The routine will not return the three-spaces language identifier used in
+ other functions to indicate non-language-specific strings.
+
+ @reval EFI_SUCCESS LanguageString was correctly returned.
+
+ @reval EFI_INVALID_PARAMETER The Handle was unknown.
+**/
+EFI_STATUS
+EFIAPI
+HiiGetPrimaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ OUT EFI_STRING *LanguageString
+ )
+{
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_HII_HANDLE UefiHiiHandle;
+ CHAR8 *LangCodes3066;
+ CHAR16 *UnicodeLangCodes639;
+ CHAR8 *LangCodes639;
+ EFI_STATUS Status;
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
+ if (UefiHiiHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LangCodes3066 = HiiLibGetSupportedLanguages (UefiHiiHandle);
+
+ if (LangCodes3066 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+
+ LangCodes639 = NULL;
+ Status = LangCodes3066To639 (LangCodes3066, &LangCodes639);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ UnicodeLangCodes639 = AllocateZeroPool (AsciiStrSize (LangCodes639) * sizeof (CHAR16));
+ if (UnicodeLangCodes639 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // The language returned is in RFC 639-2 format.
+ //
+ AsciiStrToUnicodeStr (LangCodes639, UnicodeLangCodes639);
+ *LanguageString = UnicodeLangCodes639;
+
+Done:
+ FreePool (LangCodes3066);
+ if (LangCodes639 != NULL) {
+ FreePool (LangCodes639);
+ }
+
+ return Status;
+}
+
+
+/**
+ Allows a program to determine which secondary languages are supported on a given handle for a given primary language
+
+ This routine is intended to be used by drivers to query the interface database for supported languages.
+ This routine returns a string of concatenated 3-byte language identifiers, one per string package associated with the handle.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle The handle on which the strings reside. Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack()
+ in the Packages section.
+ @param PrimaryLanguage Pointer to a NULL-terminated string containing a single ISO 639-2 language identifier, indicating
+ the primary language.
+ @param LanguageString A string allocated by GetSecondaryLanguages() containing a list of all secondary languages registered
+ on the handle. The routine will not return the three-spaces language identifier used in other functions
+ to indicate non-language-specific strings, nor will it return the primary language. This function succeeds
+ but returns a NULL LanguageString if there are no secondary languages associated with the input Handle and
+ PrimaryLanguage pair. Type EFI_STRING is defined in String.
+
+ @reval EFI_SUCCESS LanguageString was correctly returned.
+ @reval EFI_INVALID_PARAMETER The Handle was unknown.
+**/
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN CHAR16 *PrimaryLanguage,
+ OUT EFI_STRING *LanguageString
+ )
+{
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_HII_HANDLE UefiHiiHandle;
+ CHAR8 PrimaryLang3066[RFC_3066_ENTRY_SIZE];
+ CHAR8 *PrimaryLang639;
+ CHAR8 *SecLangCodes3066;
+ CHAR8 *SecLangCodes639;
+ CHAR16 *UnicodeSecLangCodes639;
+ EFI_STATUS Status;
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ SecLangCodes639 = NULL;
+ SecLangCodes3066 = NULL;
+ UnicodeSecLangCodes639 = NULL;
+
+ UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
+ if (UefiHiiHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrimaryLang639 = AllocateZeroPool (StrLen (PrimaryLanguage) + 1);
+ if (PrimaryLang639 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ UnicodeStrToAsciiStr (PrimaryLanguage, PrimaryLang639);
+
+ Status = ConvertIso639LanguageToRfc3066Language (PrimaryLang639, PrimaryLang3066);
+ ASSERT_EFI_ERROR (Status);
+
+ SecLangCodes3066 = HiiLibGetSupportedSecondaryLanguages (UefiHiiHandle, PrimaryLang3066);
+
+ if (SecLangCodes3066 == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Status = LangCodes3066To639 (SecLangCodes3066, &SecLangCodes639);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ UnicodeSecLangCodes639 = AllocateZeroPool (AsciiStrSize (SecLangCodes639) * sizeof (CHAR16));
+ if (UnicodeSecLangCodes639 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // The language returned is in RFC 3066 format.
+ //
+ *LanguageString = AsciiStrToUnicodeStr (SecLangCodes639, UnicodeSecLangCodes639);
+
+Done:
+ if (PrimaryLang639 != NULL) {
+ FreePool (PrimaryLang639);
+ }
+ if (SecLangCodes639 != NULL) {
+ FreePool (SecLangCodes639);
+ }
+ if (SecLangCodes3066 != NULL) {
+ FreePool (SecLangCodes3066);
+ }
+ if (UnicodeSecLangCodes639 != NULL) {
+ FreePool (UnicodeSecLangCodes639);
+ }
+
+ return Status;
+}
+
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.h new file mode 100644 index 0000000000..9eff9a264f --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiDatabase.h @@ -0,0 +1,464 @@ +/**@file
+
+ This file contains global defines and prototype definitions
+ for the Framework HII to Uefi HII Thunk Module.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HIIDATABASE_H
+#define _HIIDATABASE_H
+
+
+#include <FrameworkDxe.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Protocol/FrameworkFormCallback.h>
+#include <Protocol/FrameworkHii.h>
+#include <Protocol/FrameworkFormBrowser.h>
+
+//
+// UEFI HII Protocols
+//
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiImage.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/UgaDraw.h>
+
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ExtendedHiiLib.h>
+#include <Library/UefiLib.h>
+
+#include <Library/IfrSupportLib.h>
+#include <Library/ExtendedIfrSupportLib.h>
+#include <Library/PcdLib.h>
+
+#include <MdeModuleHii.h>
+
+#include "UefiIfrParser.h"
+
+
+//
+// VARSTORE ID of 0 for Buffer Storage Type Storage is defined as invalid in UEFI 2.1 HII. VARSTORE ID
+// 0 is the default VarStore ID for storage without explicit declaration in Framework HII 0.92. EDK II UEFI VFR compiler
+// in compatible mode will assign 0x0001 as UEFI VARSTORE ID to this default storage id in Framework VFR without
+// VARSTORE declaration.
+//
+// In addition, the Name of Default VarStore is assumed to be L"Setup" for those storage without explicit VARSTORE declaration in the formset
+// by Framework HII. EDK II UEFI VFR compiler in compatible mode hard-coded L"Setup" as VARSTORE name.
+//
+#define FRAMEWORK_RESERVED_VARSTORE_ID 0x0001
+#define FRAMEWORK_RESERVED_VARSTORE_NAME L"Setup"
+
+
+#pragma pack (1)
+typedef struct {
+ EFI_HII_PACK_HEADER FrameworkPackageHeader;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+} TIANO_AUTOGEN_PACKAGES_HEADER;
+#pragma pack ()
+
+#define HII_THUNK_PRIVATE_DATA_FROM_THIS(Record) CR(Record, HII_THUNK_PRIVATE_DATA, Hii, HII_THUNK_PRIVATE_DATA_SIGNATURE)
+#define HII_THUNK_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'i', 'I', 'T')
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_HII_PROTOCOL Hii;
+
+ //
+ // The head of link list for all HII_THUNK_CONTEXT.
+ //
+ LIST_ENTRY ThunkContextListHead;
+
+ EFI_HANDLE RemovePackNotifyHandle;
+ EFI_HANDLE AddPackNotifyHandle;
+} HII_THUNK_PRIVATE_DATA;
+
+
+
+
+
+#define QUESTION_ID_MAP_ENTRY_FROM_LINK(Record) CR(Record, QUESTION_ID_MAP_ENTRY, Link, QUESTION_ID_MAP_ENTRY_SIGNATURE)
+#define QUESTION_ID_MAP_ENTRY_SIGNATURE SIGNATURE_32 ('Q', 'I', 'M', 'E')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ UINT16 FwQId;
+ EFI_QUESTION_ID UefiQid;
+} QUESTION_ID_MAP_ENTRY;
+
+
+
+#define QUESTION_ID_MAP_FROM_LINK(Record) CR(Record, QUESTION_ID_MAP, Link, QUESTION_ID_MAP_SIGNATURE)
+#define QUESTION_ID_MAP_SIGNATURE SIGNATURE_32 ('Q', 'I', 'M', 'P')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ UINT16 VarStoreId;
+ UINTN VarSize;
+ LIST_ENTRY MapEntryListHead;
+} QUESTION_ID_MAP;
+
+
+
+#define HII_THUNK_CONTEXT_FROM_LINK(Record) CR(Record, HII_THUNK_CONTEXT, Link, HII_THUNK_CONTEXT_SIGNATURE)
+#define HII_THUNK_CONTEXT_SIGNATURE SIGNATURE_32 ('H', 'T', 'H', 'M')
+typedef struct {
+ LIST_ENTRY Link;
+ UINT32 Signature;
+ FRAMEWORK_EFI_HII_HANDLE FwHiiHandle;
+ EFI_HII_HANDLE UefiHiiHandle;
+ EFI_HANDLE UefiHiiDriverHandle;
+
+ UINTN IfrPackageCount;
+ UINTN StringPackageCount;
+
+ BOOLEAN ByFrameworkHiiNewPack;
+
+ //
+ // HII Thunk will use TagGuid to associate the String Package and Form Package togehter.
+ // See description for TagGuid. This field is to record if either one of the following condition
+ // is TRUE:
+ // 1) if ((SharingStringPack == TRUE) && (StringPackageCount != 0 && IfrPackageCount == 0)), then this Package List only
+ /// has String Packages and provides Strings to other IFR package.
+ // 2) if ((SharingStringPack == TRUE) && (StringPackageCount == 0 && IfrPackageCount != 1)), then this Form Package
+ // copied String Packages from other Package List.
+ // 3) if ((SharingStringPack == FALSE)), this Package does not provide String Package or copy String Packages from other
+ // Package List.
+ //
+ //
+ // When a Hii->NewString() is called for this FwHiiHandle and SharingStringPack is TRUE, then all Package List that sharing
+ // the same TagGuid will update or create String in there respective String Packages. If SharingStringPack is FALSE, then
+ // only the String from String Packages in this Package List will be updated or created.
+ //
+ BOOLEAN SharingStringPack;
+
+ //
+ // The HII 0.92 version of HII data implementation in EDK 1.03 and 1.04 make an the following assumption
+ // in both HII Database implementation and all modules that registering packages:
+ // If a Package List has only IFR package and no String Package, the IFR package will reference
+ // String in another Package List registered with the HII database with the same EFI_HII_PACKAGES.GuidId.
+ // TagGuid is the used to record this GuidId.
+ EFI_GUID TagGuid;
+
+ UINT8 *NvMapOverride;
+
+ FORM_BROWSER_FORMSET *FormSet;
+
+} HII_THUNK_CONTEXT;
+
+
+
+#define BUFFER_STORAGE_ENTRY_SIGNATURE SIGNATURE_32 ('H', 'T', 's', 'k')
+#define BUFFER_STORAGE_ENTRY_FROM_LINK(Record) CR(Record, BUFFER_STORAGE_ENTRY, Link, BUFFER_STORAGE_ENTRY_SIGNATURE)
+typedef struct {
+ LIST_ENTRY Link;
+ UINT32 Signature;
+ EFI_GUID Guid;
+ CHAR16 *Name;
+ UINTN Size;
+ UINT16 VarStoreId;
+} BUFFER_STORAGE_ENTRY;
+
+
+
+#define CONFIG_ACCESS_PRIVATE_SIGNATURE SIGNATURE_32 ('H', 'T', 'c', 'a')
+#define CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL(Record) CR(Record, CONFIG_ACCESS_PRIVATE, ConfigAccessProtocol, CONFIG_ACCESS_PRIVATE_SIGNATURE)
+typedef struct {
+ UINT32 Signature;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccessProtocol;
+ //
+ // Framework's callback
+ //
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;
+
+ HII_THUNK_CONTEXT *ThunkContext;
+} CONFIG_ACCESS_PRIVATE;
+
+
+
+#define EFI_FORMBROWSER_THUNK_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('F', 'B', 'T', 'd')
+#define EFI_FORMBROWSER_THUNK_PRIVATE_DATA_FROM_THIS(Record) CR(Record, EFI_FORMBROWSER_THUNK_PRIVATE_DATA, FormBrowser, EFI_FORMBROWSER_THUNK_PRIVATE_DATA_SIGNATURE)
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ HII_THUNK_PRIVATE_DATA *ThunkPrivate;
+ EFI_FORM_BROWSER_PROTOCOL FormBrowser;
+} EFI_FORMBROWSER_THUNK_PRIVATE_DATA;
+
+
+//
+// Extern Variables
+//
+extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+extern CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol;
+extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol;
+extern CONST EFI_HII_FONT_PROTOCOL *mHiiFontProtocol;
+extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol;
+extern CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2Protocol;
+
+extern HII_THUNK_PRIVATE_DATA *mHiiThunkPrivateData;
+
+extern BOOLEAN mInFrameworkUpdatePakcage;
+
+
+EFI_STATUS
+EFIAPI
+HiiNewPack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGES *PackageList,
+ OUT FRAMEWORK_EFI_HII_HANDLE *Handle
+ );
+
+EFI_STATUS
+EFIAPI
+HiiRemovePack (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle
+ );
+
+EFI_STATUS
+EFIAPI
+HiiFindHandles (
+ IN EFI_HII_PROTOCOL *This,
+ IN OUT UINT16 *HandleBufferLength,
+ OUT FRAMEWORK_EFI_HII_HANDLE *Handle
+ );
+
+EFI_STATUS
+EFIAPI
+HiiExportDatabase (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetGlyph (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Source,
+ IN OUT UINT16 *Index,
+ OUT UINT8 **GlyphBuffer,
+ OUT UINT16 *BitWidth,
+ IN OUT UINT32 *InternalStatus
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGlyphToBlt (
+ IN EFI_HII_PROTOCOL *This,
+ IN UINT8 *GlyphBuffer,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background,
+ IN UINTN Count,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+HiiNewString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN OUT STRING_REF *Reference,
+ IN CHAR16 *NewString
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetString (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINTN *BufferLength,
+ OUT EFI_STRING StringBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+HiiResetStrings (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle
+ );
+
+EFI_STATUS
+EFIAPI
+HiiTestString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *StringToTest,
+ IN OUT UINT32 *FirstMissing,
+ OUT UINT32 *GlyphBufferSize
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetPrimaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ OUT EFI_STRING *LanguageString
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetSecondaryLanguages (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN CHAR16 *PrimaryLanguage,
+ OUT EFI_STRING *LanguageString
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetLine (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_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
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetForms (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN EFI_FORM_ID FormId,
+ IN OUT UINTN *BufferLength,
+ OUT UINT8 *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetDefaultImage (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN UINTN DefaultMask,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ );
+
+EFI_STATUS
+EFIAPI
+HiiUpdateForm (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN EFI_FORM_LABEL Label,
+ IN BOOLEAN AddData,
+ IN FRAMEWORK_EFI_HII_UPDATE_DATA *Data
+ );
+
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+ IN EFI_HII_PROTOCOL *This,
+ OUT UINT16 *DescriptorCount,
+ OUT FRAMEWORK_EFI_KEY_DESCRIPTOR *Descriptor
+ );
+
+EFI_STATUS
+EFIAPI
+ThunkSendForm (
+ IN EFI_FORM_BROWSER_PROTOCOL *This,
+ IN BOOLEAN UseDatabase,
+ IN FRAMEWORK_EFI_HII_HANDLE *Handle,
+ IN UINTN HandleCount,
+ IN FRAMEWORK_EFI_IFR_PACKET *Packet, OPTIONAL
+ IN EFI_HANDLE CallbackHandle, OPTIONAL
+ IN UINT8 *NvMapOverride, OPTIONAL
+ IN FRAMEWORK_EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT BOOLEAN *ResetRequired OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ThunkCreatePopUp (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ );
+
+EFI_STATUS
+EFIAPI
+RemovePackNotify (
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+ );
+
+EFI_STATUS
+EFIAPI
+NewOrAddPackNotify (
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+ );
+
+/**
+ Create a EFI_HII_UPDATE_DATA structure used to call IfrLibUpdateForm.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwUpdateData The Framework Update Data.
+ @param UefiUpdateData The UEFI Update Data.
+
+ @retval EFI_SUCCESS The UEFI Update Data is created successfully.
+ @retval EFI_UNSUPPORTED There is unsupported opcode in FwUpdateData.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource.
+**/
+EFI_STATUS
+FwUpdateDataToUefiUpdateData (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_HII_UPDATE_DATA *FwUpdateData,
+ OUT EFI_HII_UPDATE_DATA **UefiUpdateData
+ )
+;
+
+/**
+
+ Initialize string packages in HII database.
+
+**/
+VOID
+InitSetBrowserStrings (
+ VOID
+ )
+;
+
+#include "Utility.h"
+#include "ConfigAccess.h"
+
+#endif
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiHandle.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiHandle.c new file mode 100644 index 0000000000..35db52932a --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiHandle.c @@ -0,0 +1,85 @@ +/**@file
+ This file is for functins related to assign and free Framework HII handle number.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiHandle.h"
+
+//
+// FRAMEWORK_EFI_HII_HANDLE
+//
+UINT8 mHandle[1024 * 8] = {0};
+
+/**
+
+ Initialize the Framework Hii Handle database.
+
+**/
+VOID
+InitHiiHandleDatabase (
+ VOID
+ )
+{
+ //
+ // FRAMEWORK_EFI_HII_HANDLE 0 is reserved.
+ // Set Bit 0 in mHandle[0] to 1.
+ //
+ mHandle[0] |= 1 << 0;
+}
+
+/**
+ Allocate a new Framework HII handle.
+
+ @param Handle Returns the new Framework HII Handle assigned.
+
+ @retval EFI_SUCCESS A new Framework HII Handle is assigned.
+ @retval EFI_OUT_OF_RESOURCE The Framework HII Handle database is depleted.
+
+**/
+EFI_STATUS
+AllocateHiiHandle (
+ OUT FRAMEWORK_EFI_HII_HANDLE *Handle
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof (mHandle) * 8; Index++) {
+ if ((mHandle[Index / 8] & (1 << (Index % 8))) == 0) {
+ mHandle[Index / 8] = (UINT8) (mHandle[Index / 8] | (1 << (Index % 8)));
+ *Handle = (FRAMEWORK_EFI_HII_HANDLE) Index;
+ ASSERT (*Handle != 0);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+}
+
+/**
+ Free Framework HII handle.
+
+ @param Handle The Framework HII Handle to be freed.
+
+**/
+VOID
+FreeHiiHandle (
+ IN FRAMEWORK_EFI_HII_HANDLE Handle
+ )
+{
+ UINT16 Num;
+
+ Num = (UINT16) Handle;
+
+ ASSERT ((mHandle [Num / 8] & (1 << (Num % 8))) != 0);
+ mHandle [Num / 8] = (UINT8) (mHandle [Num / 8] & (~(1 << (Num % 8))));
+}
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiHandle.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiHandle.h new file mode 100644 index 0000000000..ed2b186b7d --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/HiiHandle.h @@ -0,0 +1,40 @@ +/**@file
+ This file is for functins related to assign and free Framework HII handle number.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HII_HANDLE_H
+#define _HII_HANDLE_H
+
+#include <FrameworkDxe.h>
+#include <Protocol/FrameworkHii.h>
+#include <Library/DebugLib.h>
+
+VOID
+InitHiiHandleDatabase (
+ VOID
+ );
+
+EFI_STATUS
+AllocateHiiHandle (
+ FRAMEWORK_EFI_HII_HANDLE *Handle
+);
+
+
+VOID
+FreeHiiHandle (
+ FRAMEWORK_EFI_HII_HANDLE Handle
+);
+
+
+#endif
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Keyboard.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Keyboard.c new file mode 100644 index 0000000000..32e4f93345 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Keyboard.c @@ -0,0 +1,45 @@ +/**@file
+
+ This file contains the keyboard processing code to the HII database.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiDatabase.h"
+
+/**
+ Retrieves the current keyboard layout.
+ This function is not implemented by HII Thunk Module.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param DescriptorCount A pointer to the number of Descriptor entries being described in the keyboard layout being retrieved.
+ @param Descriptor A pointer to a buffer containing an array of EFI_KEY_DESCRIPTOR entries. Each entry will reflect the
+ definition of a specific physical key. Type EFI_KEY_DESCRIPTOR is defined in "Related Definitions" below.
+
+ @retval EFI_SUCCESS The keyboard layout was retrieved successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetKeyboardLayout (
+ IN EFI_HII_PROTOCOL *This,
+ OUT UINT16 *DescriptorCount,
+ OUT FRAMEWORK_EFI_KEY_DESCRIPTOR *Descriptor
+ )
+{
+ ASSERT (FALSE);
+ //
+ // In previous Framewok HII implementation, GetKeyBoardLayout is defined in HII 0.92 specification,
+ // but it is not implemented. We ASSERT and return UNSUPPORTED here.
+ //
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/OpcodeCreation.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/OpcodeCreation.c new file mode 100644 index 0000000000..5b6fb7655a --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/OpcodeCreation.c @@ -0,0 +1,1055 @@ +/** @file
+Implement Functions to convert IFR Opcode in format defined in Framework HII specification to
+format defined in UEFI HII Specification.
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HiiDatabase.h"
+#include "UefiIfrDefault.h"
+
+EFI_GUID mTianoExtendedOpcodeGuid = EFI_IFR_TIANO_GUID;
+
+
+EFI_IFR_GUID_OPTIONKEY mOptionKeyTemplate = {
+ {EFI_IFR_GUID_OP, sizeof (EFI_IFR_GUID_OPTIONKEY), 0},
+ EFI_IFR_FRAMEWORK_GUID,
+ EFI_IFR_EXTEND_OP_OPTIONKEY,
+ 0,
+ {0},
+ 0
+};
+
+/**
+ The dynamic creation of these opcodes is supported in Framework HII modules.
+ Therefore, Framework HII Thunk module only map these opcode between Framework
+ HII's definitions to UEFI HII's.
+**/
+typedef struct {
+ UINT8 FrameworkIfrOp;
+ UINT8 UefiIfrOp;
+} IFR_OPCODE_MAP;
+
+IFR_OPCODE_MAP mQuestionOpcodeMap [] = {
+ { FRAMEWORK_EFI_IFR_ONE_OF_OP, EFI_IFR_ONE_OF_OP},
+ { FRAMEWORK_EFI_IFR_CHECKBOX_OP, EFI_IFR_CHECKBOX_OP},
+ { FRAMEWORK_EFI_IFR_NUMERIC_OP, EFI_IFR_NUMERIC_OP},
+ { FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP, EFI_IFR_ONE_OF_OPTION_OP},
+ { FRAMEWORK_EFI_IFR_ORDERED_LIST_OP, EFI_IFR_ORDERED_LIST_OP}
+};
+
+/**
+ Translate a Framework Question Opcode to UEFI Question Opcode.
+
+ @param FwOp Framework Opcode.
+ @param UefiOp UEFI Opcode.
+
+ @retval EFI_SUCCESS The UEFI opcode is found and returned.
+ @retval EFI_NOT_FOUND The UEFI opcode is not found.
+**/
+EFI_STATUS
+QuestionOpFwToUefi (
+ IN UINT8 FwOp,
+ OUT UINT8 *UefiOp
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < sizeof (mQuestionOpcodeMap) / sizeof (mQuestionOpcodeMap[0]); Index++) {
+ if (FwOp == mQuestionOpcodeMap[Index].FrameworkIfrOp) {
+ *UefiOp = mQuestionOpcodeMap[Index].UefiIfrOp;
+ return EFI_SUCCESS;
+ }
+ }
+
+ *UefiOp = (UINT8) (FRAMEWORK_EFI_IFR_LAST_OPCODE + 1);
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Translate a Framework Question Opcode to UEFI Question Opcode.
+
+ @param FwOp Framework Opcode.
+ @param UefiOp UEFI Opcode.
+
+ @retval EFI_SUCCESS The UEFI opcode is found and returned.
+ @retval EFI_NOT_FOUND The UEFI opcode is not found.
+**/
+EFI_STATUS
+FwQIdToUefiQId (
+ IN CONST FORM_BROWSER_FORMSET *FormSet,
+ IN UINT8 FwOpCode,
+ IN UINT16 FwQId,
+ OUT UINT16 *UefiQId
+ )
+{
+ LIST_ENTRY *FormList;
+ LIST_ENTRY *StatementList;
+ FORM_BROWSER_FORM *Form;
+ FORM_BROWSER_STATEMENT *Statement;
+ FORM_BROWSER_STATEMENT *StatementFound;
+ EFI_STATUS Status;
+ UINT8 UefiOp;
+
+
+ *UefiQId = 0;
+ StatementFound = NULL;
+
+ FormList = GetFirstNode (&FormSet->FormListHead);
+
+ while (!IsNull (&FormSet->FormListHead, FormList)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (FormList);
+
+ StatementList = GetFirstNode (&Form->StatementListHead);
+
+ while (!IsNull (&Form->StatementListHead, StatementList)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);
+ if (Statement->VarStoreId != 0 && Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+ if (FwQId == Statement->VarStoreInfo.VarOffset) {
+ Status = QuestionOpFwToUefi (FwOpCode, &UefiOp);
+ ASSERT_EFI_ERROR (Status);
+
+ if ((UefiOp == Statement->Operand) && (FormSet->DefaultVarStoreId == Statement->VarStoreId)) {
+ //
+ // If ASSERT here, the Framework VFR file has two Questions with all three attibutes the same:
+ // 1) Same Question Type,
+ // 2) Same Variable Storage
+ // 3) Refering to the Same offset in Variable Map (NvMap).
+ // This is ambigurity as FwQIdToUefiQId () can't find which UEFI Question
+ // ID to return.
+ //
+ // One possible solution is to remove the one of the duplicated questions in this Form Set.
+ //
+ ASSERT (StatementFound == NULL);
+ StatementFound= Statement;
+
+ //
+ // Continue the search to check if the Form Set contains more than one questins that has the 3 attributes
+ // with same value.
+ //
+ }
+ }
+ }
+
+ StatementList = GetNextNode (&Form->StatementListHead, StatementList);
+ }
+
+ FormList = GetNextNode (&FormSet->FormListHead, FormList);
+ }
+
+ if (StatementFound != NULL) {
+ *UefiQId = StatementFound->QuestionId;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+
+#define LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL 0x1000
+/**
+ Append the newly created OpCode buffer to EFI_HII_UPDATE_DATA buffer.
+ Increase the Data buffer in EFI_HII_UPDATE_DATA if the EFI_HII_UPDATE_DATA
+ buffer's Data Buffer does not have space left for the newly created
+ OpCode.
+
+ @param OpCodeBuf The newly created OpCode Buffer to be appended to
+ EFI_HII_UPDATE_DATA buffer.
+ @param OpCodeBufSize The size of OpCodeBuf.
+ @param UefiUpdateData The EFI_HII_UPDATE_DATA to be appended.
+
+ @retval EFI_SUCCESS The OpCode buffer is appended to EFI_HII_UPDATE_DATA successfull.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory.
+**/
+EFI_STATUS
+AppendToUpdateBuffer (
+ IN CONST UINT8 *OpCodeBuf,
+ IN UINTN OpCodeBufSize,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ UINT8 * NewBuff;
+
+ if (UefiUpdateData->Offset + OpCodeBufSize > UefiUpdateData->BufferSize) {
+ NewBuff = AllocateCopyPool (UefiUpdateData->BufferSize + LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL, UefiUpdateData->Data);
+ if (NewBuff == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ UefiUpdateData->BufferSize += LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL;
+ FreePool (UefiUpdateData->Data);
+ UefiUpdateData->Data = NewBuff;
+ }
+
+ CopyMem (UefiUpdateData->Data + UefiUpdateData->Offset, OpCodeBuf, OpCodeBufSize);
+ UefiUpdateData->Offset += (UINT32) OpCodeBufSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Assign a Question ID.
+
+ If FwQuestionId is 0, then assign a new question ID. The new question ID
+ is MaxQuestionId incremented by 1. The MaxQuestionId of FormSet is also
+ incremented by 1.
+
+ If FwQuestionId is not 0, then it is used as the Framework Question ID.
+
+ @return The Framework Question ID.
+**/
+EFI_QUESTION_ID
+AssignQuestionId (
+ IN UINT16 FwQuestionId,
+ IN FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ if (FwQuestionId == 0) {
+ FormSet->MaxQuestionId++;
+ return FormSet->MaxQuestionId;
+ } else {
+ return FwQuestionId;
+ }
+}
+
+/**
+ Create UEFI HII "End Of" Opcode and append it to UefiUpdateData buffer.
+
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+UCreateEndOfOpcode (
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_END UOpcode;
+
+ ZeroMem (&UOpcode, sizeof (UOpcode));
+
+ UOpcode.Header.OpCode = EFI_IFR_END_OP;
+ UOpcode.Header.Length = sizeof (UOpcode);
+
+ return AppendToUpdateBuffer ((UINT8 *)&UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+/**
+ Create UEFI HII Subtitle Opcode from a Framework HII Subtitle Opcode.
+
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateSubtitleOpCode (
+ IN CONST FRAMEWORK_EFI_IFR_SUBTITLE *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_SUBTITLE UOpcode;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ UOpcode.Header.OpCode = EFI_IFR_SUBTITLE_OP;
+ UOpcode.Header.Length = sizeof (EFI_IFR_SUBTITLE);
+
+ UOpcode.Statement.Prompt = FwOpcode->SubTitle;
+
+ return AppendToUpdateBuffer ((UINT8 *)&UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+/**
+ Create UEFI HII Text Opcode from a Framework HII Text Opcode.
+
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateTextOpCode (
+ IN CONST FRAMEWORK_EFI_IFR_TEXT *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_TEXT UTextOpCode;
+ EFI_IFR_ACTION UActionOpCode;
+
+ if ((FwOpcode->Flags & FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE) == 0) {
+ ZeroMem (&UTextOpCode, sizeof(UTextOpCode));
+
+ UTextOpCode.Header.OpCode = EFI_IFR_TEXT_OP;
+ UTextOpCode.Header.Length = sizeof (EFI_IFR_TEXT);
+
+ UTextOpCode.Statement.Help = FwOpcode->Help;
+
+ UTextOpCode.Statement.Prompt = FwOpcode->Text;
+ UTextOpCode.TextTwo = FwOpcode->TextTwo;
+
+ return AppendToUpdateBuffer ((UINT8 *) &UTextOpCode, sizeof(UTextOpCode), UefiUpdateData);
+ } else {
+ //
+ // Iteractive Text Opcode is EFI_IFR_ACTION
+ //
+
+ ZeroMem (&UActionOpCode, sizeof (UActionOpCode));
+
+ UActionOpCode.Header.OpCode = EFI_IFR_ACTION_OP;
+ UActionOpCode.Header.Length = sizeof (EFI_IFR_ACTION);
+
+ UActionOpCode.Question.Header.Prompt = FwOpcode->Text;
+ UActionOpCode.Question.Header.Help = FwOpcode->Help;
+ UActionOpCode.Question.Flags = EFI_IFR_FLAG_CALLBACK;
+ UActionOpCode.Question.QuestionId = FwOpcode->Key;
+
+ return AppendToUpdateBuffer ((UINT8 *) &UActionOpCode, sizeof(UActionOpCode), UefiUpdateData);
+
+ }
+}
+
+/**
+ Create UEFI HII Reference Opcode from a Framework HII Reference Opcode.
+
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateReferenceOpCode (
+ IN CONST FRAMEWORK_EFI_IFR_REF *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_REF UOpcode;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_REF_OP;
+
+ UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
+ UOpcode.Question.Header.Help = FwOpcode->Help;
+ UOpcode.Question.QuestionId = FwOpcode->Key;
+
+ UOpcode.FormId = FwOpcode->FormId;
+
+ //
+ // We only map FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE and FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED to
+ // UEFI IFR Opcode flags. The rest flags are obsolete.
+ //
+ UOpcode.Question.Flags = (UINT8) (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
+
+
+ return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+
+/**
+ Create UEFI HII "One Of Option" Opcode from a Framework HII "One Of Option" Opcode.
+
+ @param FwOpcode The input Framework Opcode.
+ @param Width The size of the One Of Option. 1 bytes or 2 bytes.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateOneOfOptionOpCode (
+ IN CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOpcode,
+ IN UINTN Width,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_ONE_OF_OPTION UOpcode;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
+
+ UOpcode.Option = FwOpcode->Option;
+ CopyMem (&UOpcode.Value.u8, &FwOpcode->Value, Width);
+
+ //
+ // #define FRAMEWORK_EFI_IFR_FLAG_DEFAULT 0x01
+ // #define FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING 0x02
+ // #define EFI_IFR_OPTION_DEFAULT 0x10
+ // #define EFI_IFR_OPTION_DEFAULT_MFG 0x20
+ //
+ UOpcode.Flags = (UINT8) (UOpcode.Flags | (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_DEFAULT | FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING)) << 4);
+
+ switch (Width) {
+ case 1:
+ UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ break;
+
+ case 2:
+ UOpcode.Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+/**
+ Create a GUID Opcode EFI_IFR_GUID_OPTIONKEY to map the Framework One Of Option callback key
+ to a UEFI Question ID. This information is used to invoke the Framework HII Browser Callback
+ function. The opcode is appened to UefiUpdateData.
+
+ @param QuestionId The UEFI Question ID.
+ @param OptionValue The value of the "One Of Option".
+ @param KeyValue The Framework "One Of Option" callback key.
+ @param UefiDat The UEFI Update Data buffer.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+**/
+
+EFI_STATUS
+CreateGuidOptionKeyOpCode (
+ IN EFI_QUESTION_ID QuestionId,
+ IN UINT16 OptionValue,
+ IN EFI_QUESTION_ID KeyValue,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_GUID_OPTIONKEY UOpcode;
+
+ CopyMem (&UOpcode, &mOptionKeyTemplate, sizeof (EFI_IFR_GUID_OPTIONKEY));
+
+ UOpcode.QuestionId = QuestionId;
+ CopyMem (&UOpcode.OptionValue, &OptionValue, sizeof (OptionValue));
+ UOpcode.KeyValue = KeyValue;
+
+ return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+/**
+ Create UEFI HII "One Of" Opcode from a Framework HII "One Of" Opcode.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+ @param NextFwOpcode Returns the position of the next Framework Opcode after FRAMEWORK_EFI_IFR_END_ONE_OF_OP of
+ the "One Of Option".
+ @param OpcodeCount The number of Opcode for the complete Framework "One Of" Opcode.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateOneOfOpCode (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_IFR_ONE_OF *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData,
+ OUT FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,
+ OUT UINTN *OpcodeCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_IFR_ONE_OF UOpcode;
+ FRAMEWORK_EFI_IFR_OP_HEADER *FwOpHeader;
+ FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOneOfOp;
+
+ ASSERT (NextFwOpcode != NULL);
+ ASSERT (OpcodeCount != NULL);
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+ *OpcodeCount = 0;
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_ONE_OF_OP;
+ UOpcode.Header.Scope = 1;
+
+ UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
+ UOpcode.Question.Header.Help = FwOpcode->Help;
+ UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId;
+ UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
+
+ //
+ // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
+ //
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
+ while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
+ ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
+
+ FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
+ if ((FwOneOfOp->Flags & FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE) != 0) {
+ UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
+
+ if (UOpcode.Question.QuestionId == 0) {
+ Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ if (EFI_ERROR (Status)) {
+ UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);
+ }
+ }
+
+ }
+
+ if (FwOneOfOp->Flags & FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED) {
+ UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
+ }
+
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
+ }
+
+
+ if (UOpcode.Question.QuestionId == 0) {
+ //
+ // Assign QuestionId if still not assigned.
+ //
+ Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ if (EFI_ERROR (Status)) {
+ UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
+ }
+ }
+
+ Status = AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof (UOpcode), UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *OpcodeCount += 1;
+
+ //
+ // Go over again the Framework IFR binary to build the UEFI One Of Option opcodes.
+ //
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
+ while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
+
+ FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
+
+ Status = F2UCreateOneOfOptionOpCode ((FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, FwOpcode->Width, UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = CreateGuidOptionKeyOpCode (UOpcode.Question.QuestionId, FwOneOfOp->Value, FwOneOfOp->Key, UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
+ *OpcodeCount += 1;
+ }
+
+ Status = UCreateEndOfOpcode (UefiUpdateData);
+ if (!EFI_ERROR (Status)) {
+ *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
+ *OpcodeCount += 1;
+ }
+
+ return Status;
+}
+
+/**
+ Create UEFI HII "Ordered List" Opcode from a Framework HII "Ordered List" Opcode.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+ @param NextFwOpcode Returns the position of the next Framework Opcode after FRAMEWORK_EFI_IFR_END_ONE_OF_OP of
+ the "Ordered List".
+ @param OpcodeCount The number of Opcode for the complete Framework "Ordered List" Opcode.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateOrderedListOpCode (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_IFR_ORDERED_LIST *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData,
+ OUT FRAMEWORK_EFI_IFR_OP_HEADER **NextFwOpcode,
+ OUT UINTN *OpcodeCount
+ )
+{
+ EFI_IFR_ORDERED_LIST UOpcode;
+ EFI_STATUS Status;
+ FRAMEWORK_EFI_IFR_OP_HEADER *FwOpHeader;
+ FRAMEWORK_EFI_IFR_ONE_OF_OPTION *FwOneOfOp;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+ *OpcodeCount = 0;
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
+ UOpcode.Header.Scope = 1;
+
+ UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
+ UOpcode.Question.Header.Help = FwOpcode->Help;
+ UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId;
+ UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
+
+ UOpcode.MaxContainers = FwOpcode->MaxEntries;
+
+ //
+ // Go over the Framework IFR binary to get the QuestionId for generated UEFI One Of Option opcode
+ //
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
+ while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
+ ASSERT (FwOpHeader->OpCode == FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP);
+
+ FwOneOfOp = (FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader;
+ if ((FwOneOfOp->Flags & FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE) != 0) {
+ UOpcode.Question.Flags |= EFI_IFR_FLAG_CALLBACK;
+
+ if (UOpcode.Question.QuestionId == 0) {
+ Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ if (EFI_ERROR (Status)) {
+ UOpcode.Question.QuestionId = AssignQuestionId (FwOneOfOp->Key, ThunkContext->FormSet);
+ }
+
+ }
+ }
+
+ if (FwOneOfOp->Flags & FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED) {
+ UOpcode.Question.Flags |= EFI_IFR_FLAG_RESET_REQUIRED;
+ }
+
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
+ }
+
+ if (UOpcode.Question.QuestionId == 0) {
+ Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ if (EFI_ERROR (Status)) {
+ UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
+ }
+ }
+
+ Status = AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ *OpcodeCount += 1;
+
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpcode + FwOpcode->Header.Length);
+ while (FwOpHeader->OpCode != FRAMEWORK_EFI_IFR_END_ONE_OF_OP) {
+ //
+ // Each entry of Order List in Framework HII is always 1 byte in size
+ //
+ Status = F2UCreateOneOfOptionOpCode ((CONST FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) FwOpHeader, 1, UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FwOpHeader = (FRAMEWORK_EFI_IFR_OP_HEADER *) ((UINT8 *) FwOpHeader + FwOpHeader->Length);
+ *OpcodeCount += 1;
+ }
+
+ Status = UCreateEndOfOpcode (UefiUpdateData);
+ if (!EFI_ERROR (Status)) {
+ *NextFwOpcode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpHeader + FwOpHeader->Length);
+ *OpcodeCount += 1;
+ }
+
+ return Status;
+}
+
+/**
+ Create UEFI HII CheckBox Opcode from a Framework HII Checkbox Opcode.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateCheckBoxOpCode (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_IFR_CHECKBOX *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_STATUS Status;
+ EFI_IFR_CHECKBOX UOpcode;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_CHECKBOX_OP;
+
+ UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
+ UOpcode.Question.Header.Help = FwOpcode->Help;
+
+ if (FwOpcode->Key == 0) {
+ Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ if (EFI_ERROR (Status)) {
+ //
+ // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
+ //
+ UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
+ }
+ } else {
+ UOpcode.Question.QuestionId = FwOpcode->Key;
+ }
+
+ //
+ // We map 2 flags:
+ // FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE,
+ // FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED,
+ // to UEFI IFR Opcode Question flags. The rest flags are obsolete.
+ //
+ UOpcode.Question.Flags = (UINT8) (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
+
+
+ UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId;
+ UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
+
+ //
+ // We also map these 2 flags:
+ // FRAMEWORK_EFI_IFR_FLAG_DEFAULT,
+ // FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING,
+ // to UEFI IFR CheckBox Opcode default flags.
+ //
+ UOpcode.Flags = (UINT8) (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_DEFAULT | FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING));
+
+ return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+
+/**
+ Create UEFI HII Numeric Opcode from a Framework HII Numeric Opcode.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateNumericOpCode (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_IFR_NUMERIC *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_STATUS Status;
+ EFI_IFR_NUMERIC UOpcode;
+ EFI_IFR_DEFAULT UOpcodeDefault;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ if (FwOpcode->Key == 0) {
+ Status = FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ if (EFI_ERROR (Status)) {
+ //
+ // Add a new opcode and it will not trigger call back. So we just reuse the FW QuestionId.
+ //
+ UOpcode.Question.QuestionId = AssignQuestionId (FwOpcode->QuestionId, ThunkContext->FormSet);
+ }
+ } else {
+ UOpcode.Question.QuestionId = FwOpcode->Key;
+ }
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_NUMERIC_OP;
+ //
+ // We need to create a nested default value for the UEFI Numeric Opcode.
+ // So turn on the scope.
+ //
+ UOpcode.Header.Scope = 1;
+
+ UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
+ UOpcode.Question.Header.Help = FwOpcode->Help;
+
+ UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId;
+ UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
+
+ UOpcode.Question.Flags = (UINT8) (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
+
+ //
+ // Framework Numeric values are all in UINT16 and displayed as decimal.
+ //
+ UOpcode.data.u16.MinValue = FwOpcode->Minimum;
+ UOpcode.data.u16.MaxValue = FwOpcode->Maximum;
+ UOpcode.data.u16.Step = FwOpcode->Step;
+
+ switch (FwOpcode->Width) {
+ case 1:
+ {
+ UOpcode.Flags = EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC;
+ break;
+ }
+ case 2:
+ {
+ UOpcode.Flags = EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC;
+ break;
+ }
+ default:
+ {
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Status = AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // We need to create a default value.
+ //
+ ZeroMem (&UOpcodeDefault, sizeof (UOpcodeDefault));
+ UOpcodeDefault.Header.Length = sizeof (UOpcodeDefault);
+ UOpcodeDefault.Header.OpCode = EFI_IFR_DEFAULT_OP;
+
+ UOpcodeDefault.DefaultId = 0;
+
+ switch (FwOpcode->Width) {
+ case 1:
+ {
+ UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ break;
+ }
+ case 2:
+ {
+ UOpcodeDefault.Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ break;
+ }
+ }
+
+ CopyMem (&UOpcodeDefault.Value.u8, &FwOpcode->Default, FwOpcode->Width);
+
+ Status = AppendToUpdateBuffer ((UINT8 *) &UOpcodeDefault, sizeof(UOpcodeDefault), UefiUpdateData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = UCreateEndOfOpcode (UefiUpdateData);
+
+ return Status;
+}
+
+
+/**
+ Create UEFI HII String Opcode from a Framework HII String Opcode.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateStringOpCode (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_IFR_STRING *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_STRING UOpcode;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ if (FwOpcode->Key == 0) {
+ FwQIdToUefiQId (ThunkContext->FormSet, FwOpcode->Header.OpCode, FwOpcode->QuestionId, &UOpcode.Question.QuestionId);
+ } else {
+ UOpcode.Question.QuestionId = FwOpcode->Key;
+ }
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_STRING_OP;
+
+ UOpcode.Question.Header.Prompt = FwOpcode->Prompt;
+ UOpcode.Question.Header.Help = FwOpcode->Help;
+
+ UOpcode.Question.QuestionId = FwOpcode->Key;
+ UOpcode.Question.Flags = (UINT8) (FwOpcode->Flags & (FRAMEWORK_EFI_IFR_FLAG_INTERACTIVE | FRAMEWORK_EFI_IFR_FLAG_RESET_REQUIRED));
+
+ UOpcode.Question.VarStoreId = ThunkContext->FormSet->DefaultVarStoreId;
+ UOpcode.Question.VarStoreInfo.VarOffset = FwOpcode->QuestionId;
+
+ UOpcode.MinSize = FwOpcode->MinSize;
+ UOpcode.MaxSize = FwOpcode->MaxSize;
+ UOpcode.Flags = EFI_IFR_STRING_MULTI_LINE;
+
+ return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+/**
+ Create UEFI HII Banner Opcode from a Framework HII Banner Opcode.
+
+ @param FwOpcode The input Framework Opcode.
+ @param UefiUpdateData The newly created UEFI HII opcode is appended to UefiUpdateData.
+
+ @retval EFI_SUCCESS The UEFI HII opcode is created successfully and appended to UefiUpdateData.
+ @retval EFI_OUT_OF_RESOURCE There is not enough resource.
+
+**/
+EFI_STATUS
+F2UCreateBannerOpCode (
+ IN CONST FRAMEWORK_EFI_IFR_BANNER *FwOpcode,
+ IN OUT EFI_HII_UPDATE_DATA *UefiUpdateData
+ )
+{
+ EFI_IFR_GUID_BANNER UOpcode;
+
+ ZeroMem (&UOpcode, sizeof(UOpcode));
+
+ UOpcode.Header.Length = sizeof(UOpcode);
+ UOpcode.Header.OpCode = EFI_IFR_GUID_OP;
+
+ CopyMem (&UOpcode.Guid, &mTianoExtendedOpcodeGuid, sizeof (EFI_GUID));
+ UOpcode.ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER;
+ UOpcode.Title = FwOpcode->Title;
+ UOpcode.LineNumber = FwOpcode->LineNumber;
+ UOpcode.Alignment = FwOpcode->Alignment;
+
+ return AppendToUpdateBuffer ((UINT8 *) &UOpcode, sizeof(UOpcode), UefiUpdateData);
+}
+
+/**
+ Create a EFI_HII_UPDATE_DATA structure used to call IfrLibUpdateForm.
+
+ @param ThunkContext The HII Thunk Context.
+ @param FwUpdateData The Framework Update Data.
+ @param UefiUpdateData The UEFI Update Data.
+
+ @retval EFI_SUCCESS The UEFI Update Data is created successfully.
+ @retval EFI_UNSUPPORTED There is unsupported opcode in FwUpdateData.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource.
+**/
+EFI_STATUS
+FwUpdateDataToUefiUpdateData (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST FRAMEWORK_EFI_HII_UPDATE_DATA *FwUpdateData,
+ OUT EFI_HII_UPDATE_DATA **UefiUpdateData
+ )
+{
+ FRAMEWORK_EFI_IFR_OP_HEADER *FwOpCode;
+ FRAMEWORK_EFI_IFR_OP_HEADER *NextFwOpCode;
+ EFI_HII_UPDATE_DATA *UefiOpCode;
+ UINTN Index;
+ EFI_STATUS Status;
+ UINTN DataCount;
+
+ UefiOpCode = AllocateZeroPool (sizeof (EFI_HII_UPDATE_DATA));
+ if (UefiOpCode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UefiOpCode->Data = AllocateZeroPool (LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL);
+ if (UefiOpCode->Data == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UefiOpCode->BufferSize = LOCAL_UPDATE_DATA_BUFFER_INCREMENTAL;
+ UefiOpCode->Offset = 0;
+
+ FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *) &FwUpdateData->Data;
+
+ for (Index = 0; Index < FwUpdateData->DataCount; Index += DataCount) {
+ switch (FwOpCode->OpCode) {
+ case FRAMEWORK_EFI_IFR_SUBTITLE_OP:
+ Status = F2UCreateSubtitleOpCode ((FRAMEWORK_EFI_IFR_SUBTITLE *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_TEXT_OP:
+ Status = F2UCreateTextOpCode ((FRAMEWORK_EFI_IFR_TEXT *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_REF_OP:
+ Status = F2UCreateReferenceOpCode ((FRAMEWORK_EFI_IFR_REF *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_ONE_OF_OP:
+ Status = F2UCreateOneOfOpCode (ThunkContext, (FRAMEWORK_EFI_IFR_ONE_OF *) FwOpCode, UefiOpCode, &NextFwOpCode, &DataCount);
+ if (!EFI_ERROR (Status)) {
+ FwOpCode = NextFwOpCode;
+ //
+ // FwOpCode is already updated to point to the next opcode.
+ //
+ continue;
+ }
+ break;
+
+ case FRAMEWORK_EFI_IFR_ORDERED_LIST_OP:
+ Status = F2UCreateOrderedListOpCode (ThunkContext, (FRAMEWORK_EFI_IFR_ORDERED_LIST *) FwOpCode, UefiOpCode, &NextFwOpCode, &DataCount);
+ if (!EFI_ERROR (Status)) {
+ FwOpCode = NextFwOpCode;
+ //
+ // FwOpCode is already updated to point to the next opcode.
+ //
+ continue;
+ }
+ break;
+
+ case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
+ Status = F2UCreateCheckBoxOpCode (ThunkContext, (FRAMEWORK_EFI_IFR_CHECKBOX *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_STRING_OP:
+ Status = F2UCreateStringOpCode (ThunkContext, (FRAMEWORK_EFI_IFR_STRING *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_BANNER_OP:
+ Status = F2UCreateBannerOpCode ((FRAMEWORK_EFI_IFR_BANNER *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_END_ONE_OF_OP:
+ Status = UCreateEndOfOpcode (UefiOpCode);
+ DataCount = 1;
+ break;
+
+ case FRAMEWORK_EFI_IFR_NUMERIC_OP:
+ Status = F2UCreateNumericOpCode (ThunkContext, (FRAMEWORK_EFI_IFR_NUMERIC *) FwOpCode, UefiOpCode);
+ DataCount = 1;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (EFI_ERROR (Status)) {
+ FreePool (UefiOpCode->Data);
+ FreePool (UefiOpCode);
+ return Status;
+ }
+
+ FwOpCode = (FRAMEWORK_EFI_IFR_OP_HEADER *)((UINT8 *) FwOpCode + FwOpCode->Length);
+ }
+
+ *UefiUpdateData = UefiOpCode;
+
+ return EFI_SUCCESS;
+}
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Package.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Package.c new file mode 100644 index 0000000000..3187a94160 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Package.c @@ -0,0 +1,885 @@ +/**@file
+ Implement protocol interface related to package registrations.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiDatabase.h"
+#include "HiiHandle.h"
+
+
+BOOLEAN mInFrameworkHiiNewPack = FALSE;
+BOOLEAN mInFrameworkHiiRemovePack = FALSE;
+BOOLEAN mInFrameworkUpdatePakcage = FALSE;
+UINT64 mGuidCount = 0;
+
+EFI_GUID mGuidBase = { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }};
+
+
+
+/**
+ Get the number of package IFR and STRING packages in the package list passed in.
+
+ @param Packages Package List.
+ @param IfrPackageCount Number of IFR Packages.
+ @param StringPackageCount Number of String Packages.
+
+ @retval EFI_INVALID_PARAMETER If the Package List has package with type of
+ EFI_HII_PACKAGE_KEYBOARD_LAYOUT, EFI_HII_PACKAGE_FONTS, EFI_HII_PACKAGE_IMAGES.
+ @reval EFI_SUCCESS Successfully get the number of IFR and STRING package.
+
+
+**/
+EFI_STATUS
+GetPackageCount (
+ IN CONST EFI_HII_PACKAGES *Packages,
+ OUT UINTN *IfrPackageCount,
+ OUT UINTN *StringPackageCount,
+ OUT UINTN *FontPackageCount
+ )
+{
+ UINTN Index;
+ TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
+
+ ASSERT (Packages != NULL);
+ ASSERT (IfrPackageCount != NULL);
+ ASSERT (StringPackageCount != NULL);
+ ASSERT (FontPackageCount != NULL);
+
+ *IfrPackageCount = 0;
+ *StringPackageCount = 0;
+ *FontPackageCount = 0;
+
+ TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
+
+ for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
+ //
+ // The current UEFI HII build tool generate a binary in the format defined by
+ // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
+ // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
+ // may not be the exact number of valid package number in the binary generated
+ // by HII Build tool.
+ //
+ switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
+ case EFI_HII_IFR:
+ *IfrPackageCount += 1;
+ break;
+ case EFI_HII_STRING:
+ *StringPackageCount += 1;
+ break;
+
+ case EFI_HII_FONT:
+ *FontPackageCount += 1;
+ break;
+
+ //
+ // The following fonts are invalid for a module that using Framework to UEFI thunk layer.
+ //
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert the String Package into the Package Lists which has the TAG GUID matching
+ the PackageListGuid of the String Package.
+
+ The Package List must have only IFR Package and no String Package.
+ Otherwise, ASSERT.
+
+ @param Private The HII THUNK driver context data.
+ @param StringPackageThunkContext The HII THUNK context data.
+ @param StringPackageListHeader The String Package List Header.
+
+**/
+VOID
+UpdatePackListWithOnlyIfrPack (
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN HII_THUNK_CONTEXT *StringPackageThunkContext,
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (StringPackageThunkContext != ThunkContext) {
+ //
+ // Skip the String Package Thunk Entry itself.
+ //
+
+ if (CompareGuid (&StringPackageListHeader->PackageListGuid, &ThunkContext->TagGuid)) {
+
+ ASSERT (ThunkContext->StringPackageCount == 0 && ThunkContext->IfrPackageCount == 1);
+
+ ThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
+
+ Status = mHiiDatabase->UpdatePackageList (
+ mHiiDatabase,
+ ThunkContext->UefiHiiHandle,
+ StringPackageListHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ThunkContext->SharingStringPack = TRUE;
+ StringPackageThunkContext->SharingStringPack = TRUE;
+
+ }
+ }
+
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+}
+
+/**
+ Caculate the size of UEFI Simple Font Package that is needed to
+ convert all the font a Framework Font Paackage.
+
+ ONLY Narrow Font is supported. Wide Font is discarded.
+
+ If the Package Header is not of EFI_HII_FONT type, then ASSERT.
+
+ @param The Package header of the Framework Font Package.
+
+ @return The size of the UEFI Simple Font Package.
+
+**/
+UINTN
+GetUefiSimpleFontPackSize (
+ IN CONST EFI_HII_PACK_HEADER * PackHeader
+ )
+{
+ UINTN Size;
+ EFI_HII_FONT_PACK *FwFontPack;
+
+ FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;
+
+ ASSERT (FwFontPack->Header.Type == EFI_HII_FONT);
+
+ Size = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR)
+ + (FwFontPack->NumberOfNarrowGlyphs * sizeof (EFI_NARROW_GLYPH));
+
+ return Size;
+}
+
+
+/**
+ Convert Font Package in Framework format to a newly allocated UEFI
+ Simple Font Package.
+
+ ONLY Narrow Font is supported. Wide Font is discarded.
+
+ If memory allocation fails, then ASSERT.
+
+ @param FwFontPack Framework Font Package.
+
+ @reture UEFI Simple Font Package.
+**/
+EFI_HII_SIMPLE_FONT_PACKAGE_HDR *
+FrameworkFontPackToUefiSimpliedFont (
+ IN CONST EFI_HII_PACK_HEADER * PackHeader
+ )
+{
+ EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack;
+ UINTN Size;
+ EFI_NARROW_GLYPH *FwNarrowGlyph;
+ EFI_NARROW_GLYPH *NarrowGlyph;
+ UINTN Idx;
+ EFI_HII_FONT_PACK *FwFontPack;
+
+ Size = GetUefiSimpleFontPackSize (PackHeader);
+
+ FwFontPack = (EFI_HII_FONT_PACK *) PackHeader;
+
+ FontPack = AllocateZeroPool (Size);
+ ASSERT (FontPack != NULL);
+
+ //
+ // Prepare the Header information.
+ //
+ FontPack->Header.Length = (UINT32) Size;
+ FontPack->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS;
+
+ FontPack->NumberOfNarrowGlyphs = FwFontPack->NumberOfNarrowGlyphs;
+
+ //
+ // ONLY Narrow Font is supported. Wide Font is discarded.
+ //
+ FontPack->NumberOfWideGlyphs = 0;
+
+ //
+ // Copy Narrow Glyph
+ //
+ NarrowGlyph = (EFI_NARROW_GLYPH *) (FontPack + 1);
+ FwNarrowGlyph = (EFI_NARROW_GLYPH *) (FwFontPack + 1);
+ CopyMem (NarrowGlyph, FwNarrowGlyph, sizeof (EFI_NARROW_GLYPH) * FwFontPack->NumberOfNarrowGlyphs);
+ for (Idx = 0; Idx < FwFontPack->NumberOfNarrowGlyphs; Idx++) {
+ //
+ // Clear the GLYPH_NON_BREAKING (EFI_GLYPH_WIDE is used here as they are all 0x02)
+ // attribute which is not defined in UEFI EFI_NARROW_GLYPH
+ //
+ NarrowGlyph[Idx].Attributes = (UINT8) (NarrowGlyph[Idx].Attributes & ~(EFI_GLYPH_WIDE));
+ }
+
+ return FontPack;
+}
+
+/**
+ Prepare a UEFI Package List from a Framework HII package list registered
+ from a Framework HII NewPack () function.
+
+ If either Packages or PackageListGuid is NULL, then ASSERT.
+
+ @param Packages The Framework HII Package List.
+ @param PackageListGuid The Package List GUID.
+
+
+ @return The UEFI Package List.
+**/
+EFI_HII_PACKAGE_LIST_HEADER *
+PrepareUefiPackageListFromFrameworkHiiPackages (
+ IN CONST EFI_HII_PACKAGES *Packages,
+ IN CONST EFI_GUID *PackageListGuid
+ )
+{
+ UINTN NumberOfPackages;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
+ UINT8 *PackageListData;
+ UINT32 PackageListLength;
+ UINT32 PackageLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ UINTN Index;
+ TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
+ EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack;
+
+
+ ASSERT (Packages != NULL);
+ ASSERT (PackageListGuid != NULL);
+
+ TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId));
+ NumberOfPackages = Packages->NumberOfPackages;
+
+ PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+
+ for (Index = 0; Index < NumberOfPackages; Index++) {
+ if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {
+ //
+ // There is no tool to generate Font package in Framework HII's implementation.
+ // Therefore, Font Package be a C structure defined in Framework HII code.
+ // Therefore, Font Package will be in Framework HII format defined by EFI_HII_FONT_PACK.
+ // We need to create a UEFI Simple Font Package and copy over all data. Hence, EFI_HII_FONT
+ // is handled differently than EFI_HII_IFR and EFI_HII_STRING.
+ //
+ PackageListLength = (UINT32) (PackageListLength + GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader));
+
+ } else {
+ //
+ // For EFI_HII_IFR and EFI_HII_STRING, EDK II's VFR Compiler and Build.exe will generate a binary in a format
+ // defined by TIANO_AUTOGEN_PACKAGES_HEADER. A Framework HII's EFI_HII_PACK_HEADER is inserted before
+ // the UEFI package data.
+ //
+ CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length, sizeof (UINT32));
+ //
+ // EFI_HII_PACK_HEADER.FrameworkPackageHeader.Length include the sizeof FrameworkPackageHeader itself.
+ //
+ PackageListLength += (PackageLength - sizeof(EFI_HII_PACK_HEADER));
+
+ }
+ }
+
+ //
+ // Include the lenght of EFI_HII_PACKAGE_END
+ //
+ PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER);
+ PackageListHeader = AllocateZeroPool (PackageListLength);
+ ASSERT (PackageListHeader != NULL);
+
+ CopyMem (&PackageListHeader->PackageListGuid, PackageListGuid, sizeof (EFI_GUID));
+ PackageListHeader->PackageLength = PackageListLength;
+
+ PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+
+ //
+ // Build the UEFI Package List.
+ //
+ for (Index = 0; Index < NumberOfPackages; Index++) {
+ if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) {
+ PackageLength = (UINT32) GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);
+ FontPack = FrameworkFontPackToUefiSimpliedFont (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader);
+ CopyMem (PackageListData, FontPack, PackageLength);
+ FreePool (FontPack);
+
+ } else {
+ CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length), sizeof (UINT32));
+ PackageLength -= sizeof (EFI_HII_PACK_HEADER);
+ CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), PackageLength);
+
+ }
+ PackageListData += PackageLength;
+ }
+
+ //
+ // Append EFI_HII_PACKAGE_END
+ //
+ PackageHeader.Type = EFI_HII_PACKAGE_END;
+ PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER);
+ CopyMem (PackageListData, &PackageHeader, PackageHeader.Length);
+
+ return PackageListHeader;
+}
+
+
+/**
+ Generate a Random GUID.
+
+ @param Guid On output, a Random GUID will be filled.
+
+**/
+VOID
+GenerateRandomGuid (
+ OUT EFI_GUID * Guid
+ )
+{
+ CopyGuid (Guid, &mGuidBase);
+
+ mGuidCount++;
+ *((UINT64 *) Guid) = *((UINT64 *) Guid) + mGuidCount;
+}
+
+/**
+ Given a Package List with only a IFR package, find the Package List that only has a String Package based on
+ the TAG GUID. Then export the String Package from the Package List and insert it
+ to the given IFR package.
+
+ This is to handle the case of Framework HII interface which allow String Package
+ and IFR package to be registered using two different NewPack () calls.
+
+ @param Private The HII THUNK driver context data.
+ @param IfrThunkContext Package List with only a IFR package.
+
+ @retval EFI_SUCCESS If the String Package is found and inserted to the
+ Package List with only a IFR package.
+ @retval EFI_NOT_FOUND No String Package matching the TAG GUID is found.
+**/
+EFI_STATUS
+FindStringPackAndUpdatePackListWithOnlyIfrPack (
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN HII_THUNK_CONTEXT *IfrThunkContext
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader;
+ UINTN Size;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (ThunkContext != IfrThunkContext) {
+ if (CompareGuid (&IfrThunkContext->TagGuid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount == 0)) {
+ Status = HiiLibExportPackageLists (ThunkContext->UefiHiiHandle, &StringPackageListHeader, &Size);
+ ASSERT_EFI_ERROR (Status);
+
+ IfrThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS);
+ //
+ // Add Function to only get only String Packages from the Package List
+ //
+ Status = mHiiDatabase->UpdatePackageList (
+ mHiiDatabase,
+ IfrThunkContext->UefiHiiHandle,
+ StringPackageListHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (StringPackageListHeader);
+
+ IfrThunkContext->SharingStringPack = TRUE;
+ ThunkContext->SharingStringPack = TRUE;
+
+ return EFI_SUCCESS;
+
+ }
+ }
+
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+ //
+ // A Form Package must have a String Package to function.
+ // If ASSERT here, check the sequence of call to Hii->NewPack.
+ // String Pack must be registered before Ifr Package is registered.
+ //
+ ASSERT (FALSE);
+ return EFI_NOT_FOUND;
+
+}
+
+
+/**
+ Register the Package List passed from the Framework HII NewPack () interface.
+ The FRAMEWORK_EFI_HII_HANDLE will be returned.
+
+ @param This The EFI_HII_PROTOCOL context data. Only used
+ to call HiiRemovePack.
+ @param Private The HII THUNK driver context data.
+ @param Package Package List.
+ @param Handle On output, a FRAMEWORK_EFI_HII_HANDLE number is
+ returned.
+
+ @retval EFI_SUCCESS The Package List is registered successfull in
+ the database.
+ @retval EFI_UNSUPPORTED The number of IFR package in the package list
+ is greater than 1.
+ @retval EFI_OUT_OF_RESOURCE Not enough resouce.
+
+**/
+EFI_STATUS
+UefiRegisterPackageList (
+ IN EFI_HII_PROTOCOL *This,
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN EFI_HII_PACKAGES *Packages,
+ OUT FRAMEWORK_EFI_HII_HANDLE *Handle
+ )
+{
+ EFI_STATUS Status;
+ UINTN StringPackageCount;
+ UINTN IfrPackageCount;
+ UINTN FontPackageCount;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
+ HII_THUNK_CONTEXT *ThunkContext;
+ HII_THUNK_CONTEXT *ThunkContextToRemove;
+ EFI_GUID GuidId;
+ EFI_HII_PACKAGE_HEADER *IfrPackage;
+
+ PackageListHeader = NULL;
+
+ Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount, &FontPackageCount);
+ ASSERT_EFI_ERROR (Status);
+
+ if (IfrPackageCount > 1) {
+ //
+ // HII Thunk only handle package with 0 or 1 IFR package.
+ //
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount);
+ if (ThunkContext == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ThunkContext->ByFrameworkHiiNewPack = TRUE;
+
+ if (Packages->GuidId == NULL) {
+ //
+ // UEFI HII Database require Package List GUID must be unique.
+ //
+ // If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering
+ // packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is
+ // not used as the name of the package list. Formset GUID is used as the Package List
+ // GUID instead.
+ //
+ ASSERT ((StringPackageCount >=1 && IfrPackageCount == 1) || (FontPackageCount > 0));
+ if (IfrPackageCount > 0) {
+ IfrPackage = GetIfrPackage (Packages);
+ GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid);
+ } else {
+ ASSERT (FontPackageCount > 0);
+ GenerateRandomGuid (&ThunkContext->TagGuid);
+ }
+
+ } else {
+ ThunkContextToRemove = TagGuidToIfrPackThunkContext (Private, Packages->GuidId);
+
+ if (IfrPackageCount > 0 &&
+ StringPackageCount > 0 &&
+ (ThunkContextToRemove != NULL)) {
+ DEBUG((EFI_D_WARN, "Framework code registers HII package list with the same GUID more than once.\n"));
+ DEBUG((EFI_D_WARN, "Remove the previously registered package list and register the new one.\n"));
+ HiiRemovePack (This, ThunkContextToRemove->FwHiiHandle);
+ }
+ CopyGuid (&ThunkContext->TagGuid, Packages->GuidId);
+
+ }
+
+ //
+ // UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so
+ // that Setup Utility can load the Buffer Storage using this protocol. An UEFI VFR can only
+ // produce IFR package generated with Buffer Storage type and EFI Variable Storage.
+ // The default EFI_HII_CONFIG_ACCESS_PROTOCOL is used to Get/Set the Buffer Storage.
+ //
+ if (IfrPackageCount != 0) {
+ InstallDefaultConfigAccessProtocol (Packages, ThunkContext);
+ }
+
+ PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &ThunkContext->TagGuid);
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageListHeader,
+ ThunkContext->UefiHiiDriverHandle,
+ &ThunkContext->UefiHiiHandle
+ );
+ if (Status == EFI_INVALID_PARAMETER) {
+ FreePool (PackageListHeader);
+
+ //
+ // UEFI HII database does not allow two package list with the same GUID.
+ // In Framework HII implementation, Packages->GuidId is used as an identifier to associate
+ // a PackageList with only IFR to a Package list the with String package.
+ //
+ GenerateRandomGuid (&GuidId);
+
+ PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId);
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageListHeader,
+ ThunkContext->UefiHiiDriverHandle,
+ &ThunkContext->UefiHiiHandle
+ );
+ }
+
+ //
+ // BUGBUG: Remove when development is done
+ //
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (IfrPackageCount == 0) {
+ if (StringPackageCount != 0) {
+ //
+ // Look for a Package List with only IFR Package with the same TAG GUID name.
+ // If found one, add the String Packages to the found Package List.
+ // This is needed because Framework HII Module may not register the String Package
+ // and IFR Package in one NewPack () call.
+ //
+ UpdatePackListWithOnlyIfrPack (
+ Private,
+ ThunkContext,
+ PackageListHeader
+ );
+ }
+ } else {
+ if (StringPackageCount == 0) {
+ //
+ // Look for the String Package with the same TAG GUID name and add
+ // the found String Package to this Package List.
+ // This is needed because Framework HII Module may not register the String Package
+ // and IFR Package in one NewPack () call.
+ //
+ Status = FindStringPackAndUpdatePackListWithOnlyIfrPack (
+ Private,
+ ThunkContext
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Parse the Formset. Must be called after FindStringPackAndUpdatePackListWithOnlyIfrPack is called so
+ // that String Package is ready.
+ //
+ ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);
+ ASSERT (ThunkContext->FormSet != NULL);
+
+ }
+
+Done:
+ if (EFI_ERROR (Status)) {
+ DestroyThunkContext (ThunkContext);
+ } else {
+ InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
+ *Handle = ThunkContext->FwHiiHandle;
+ }
+
+ if (PackageListHeader != NULL) {
+ FreePool (PackageListHeader);
+ }
+
+ return Status;
+}
+
+
+/**
+
+ Registers the various packages that are passed in a Package List.
+
+ @param This Pointer of Frameowk HII protocol instance.
+ @param Packages Pointer of HII packages.
+ @param Handle Handle value to be returned.
+
+ @retval EFI_SUCCESS Pacakges has added to HII database successfully.
+ @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiNewPack (
+ IN EFI_HII_PROTOCOL *This,
+ IN EFI_HII_PACKAGES *Packages,
+ OUT FRAMEWORK_EFI_HII_HANDLE *Handle
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_TPL OldTpl;
+
+ if (Handle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Packages == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ //
+ // We use a simple Global variable to inform NewOrAddPackNotify()
+ // that the package list registered here is already registered
+ // in the HII Thunk Layer. So NewOrAddPackNotify () does not need to
+ // call registered the Package List again.
+ //
+ mInFrameworkHiiNewPack = TRUE;
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ Status = UefiRegisterPackageList (
+ This,
+ Private,
+ Packages,
+ Handle
+ );
+
+ mInFrameworkHiiNewPack = FALSE;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+
+ Remove a package from the HII database.
+
+ @param This Pointer of Frameowk HII protocol instance.
+ @param Handle Handle value to be removed.
+
+ @retval EFI_SUCCESS Pacakges has added to HII database successfully.
+ @retval EFI_INVALID_PARAMETER If Handle or Packages is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiRemovePack (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ HII_THUNK_CONTEXT *ThunkContext;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ mInFrameworkHiiRemovePack = TRUE;
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, Handle);
+
+ if (ThunkContext != NULL) {
+ Status = mHiiDatabase->RemovePackageList (
+ mHiiDatabase,
+ ThunkContext->UefiHiiHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (ThunkContext->IfrPackageCount != 0) {
+ UninstallDefaultConfigAccessProtocol (ThunkContext);
+ }
+
+ DestroyThunkContext (ThunkContext);
+ }else {
+ Status = EFI_NOT_FOUND;
+ }
+
+ mInFrameworkHiiRemovePack = FALSE;
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ This notification function will be called when a Package List is registered
+ using UEFI HII interface. The Package List registered need to be recorded in
+ Framework Thunk module as Thunk Module may need to look for String Package in
+ the package registered.
+
+ If the Package List registered is not either Sting Package or IFR package,
+ then ASSERT. If the NotifyType is not ADD_PACK or NEW_PACK, then ASSERT.
+ Both cases means UEFI HII Database itself is buggy.
+
+ @param PackageType The Package Type.
+ @param PackageGuid The Package GUID.
+ @param Package The Package Header.
+ @param Handle The HII Handle of this Package List.
+ @param NotifyType The reason of the notification.
+
+ @retval EFI_SUCCESS The notification function is successful.
+
+**/
+EFI_STATUS
+EFIAPI
+NewOrAddPackNotify (
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORMS);
+ ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK);
+
+ Status = EFI_SUCCESS;
+ Private = mHiiThunkPrivateData;
+
+ if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // We will create a ThunkContext to log the package list only if the
+ // package is not registered with by Framework HII Thunk module yet.
+ //
+ ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
+ if (ThunkContext == NULL) {
+ ThunkContext = CreateThunkContextForUefiHiiHandle (Handle);
+ ASSERT (ThunkContext != NULL);
+
+ InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link);
+ }
+
+ if (PackageType == EFI_HII_PACKAGE_FORMS) {
+ if (ThunkContext->FormSet != NULL) {
+ DestroyFormSet (ThunkContext->FormSet);
+ }
+
+ //
+ // Reparse the FormSet.
+ //
+ ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle);
+ ASSERT (ThunkContext->FormSet != NULL);
+ }
+
+ return Status;
+}
+
+/**
+ This notification function will be called when a Package List is removed
+ using UEFI HII interface. The Package List removed need to be removed from
+ Framework Thunk module too.
+
+ If the Package List registered is not Sting Package,
+ then ASSERT. If the NotifyType is not REMOVE_PACK, then ASSERT.
+ Both cases means UEFI HII Database itself is buggy.
+
+ @param PackageType The Package Type.
+ @param PackageGuid The Package GUID.
+ @param Package The Package Header.
+ @param Handle The HII Handle of this Package List.
+ @param NotifyType The reason of the notification.
+
+ @retval EFI_SUCCESS The notification function is successful.
+
+**/
+EFI_STATUS
+EFIAPI
+RemovePackNotify (
+ IN UINT8 PackageType,
+ IN CONST EFI_GUID *PackageGuid,
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ HII_THUNK_CONTEXT *ThunkContext;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+
+ Status = EFI_SUCCESS;
+
+ ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS);
+ ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK);
+
+ if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) {
+ return EFI_SUCCESS;
+ }
+
+ Private = mHiiThunkPrivateData;
+
+ ThunkContext = UefiHiiHandleToThunkContext (Private, Handle);
+
+ //
+ // BugBug: Change to ASSERT if HII Database fix the bug and to also invoke
+ // NEW_PACK_NOTIFY for package (String Package) created internally.
+ //
+ if (ThunkContext != NULL) {
+ if (!ThunkContext->ByFrameworkHiiNewPack) {
+ Status = HiiLibExportPackageLists (Handle, &HiiPackageList, &BufferSize);
+ ASSERT_EFI_ERROR (Status);
+
+ if (GetPackageCountByType (HiiPackageList, EFI_HII_PACKAGE_STRINGS) == 1) {
+ //
+ // If the string package will be removed is the last string package
+ // in the package list, we will remove the HII Thunk entry from the
+ // database.
+ //
+ DestroyThunkContextForUefiHiiHandle (Private, Handle);
+ }
+
+ FreePool (HiiPackageList);
+ }
+ }
+
+
+ return Status;
+}
+
+
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c new file mode 100644 index 0000000000..7f42842755 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.c @@ -0,0 +1,575 @@ +/**@file
+Framework to UEFI 2.1 Setup Browser Thunk. The file consume EFI_FORM_BROWSER2_PROTOCOL
+to produce a EFI_FORM_BROWSER_PROTOCOL.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HiiDatabase.h"
+#include "SetupBrowser.h"
+
+EFI_GUID gFrameworkBdsFrontPageFormsetGuid = FRAMEWORK_BDS_FRONTPAGE_FORMSET_GUID;
+EFI_HII_HANDLE gStringPackHandle = NULL;
+BOOLEAN mFrontPageDisplayed = FALSE;
+//
+// 106F3545-B788-4cb5-9D2A-CE0CDB208DF5
+//
+EFI_GUID gEfiHiiThunkProducerGuid = { 0x106f3545, 0xb788, 0x4cb5, { 0x9d, 0x2a, 0xce, 0xc, 0xdb, 0x20, 0x8d, 0xf5 } };
+
+
+/**
+ Get string by string id from HII Interface
+
+
+ @param Id String ID.
+
+ @retval CHAR16 * String from ID.
+ @retval NULL If error occurs.
+
+**/
+CHAR16 *
+GetStringById (
+ IN EFI_STRING_ID Id
+ )
+{
+ CHAR16 *String;
+
+ String = NULL;
+ HiiLibGetStringFromHandle (gStringPackHandle, Id, &String);
+
+ return String;
+}
+/**
+
+ Show progress bar with title above it. It only works in Graphics mode.
+
+
+ @param TitleForeground Foreground color for Title.
+ @param TitleBackground Background color for Title.
+ @param Title Title above progress bar.
+ @param ProgressColor Progress bar color.
+ @param Progress Progress (0-100)
+ @param PreviousValue The previous value of the progress.
+
+ @retval EFI_STATUS Success update the progress bar
+
+**/
+EFI_STATUS
+PlatformBdsShowProgress (
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ IN CHAR16 *Title,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ IN UINTN Progress,
+ IN UINTN PreviousValue
+ )
+{
+ EFI_STATUS Status;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINT32 SizeOfX;
+ UINT32 SizeOfY;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ UINTN BlockHeight;
+ UINTN BlockWidth;
+ UINTN BlockNum;
+ UINTN PosX;
+ UINTN PosY;
+ UINTN Index;
+
+ if (Progress > 100) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UgaDraw = NULL;
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **) &GraphicsOutput
+ );
+ if (EFI_ERROR (Status)) {
+ GraphicsOutput = NULL;
+
+ Status = gBS->HandleProtocol (
+ gST->ConsoleOutHandle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ SizeOfX = 0;
+ SizeOfY = 0;
+ if (GraphicsOutput != NULL) {
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
+ } else {
+ Status = UgaDraw->GetMode (
+ UgaDraw,
+ &SizeOfX,
+ &SizeOfY,
+ &ColorDepth,
+ &RefreshRate
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ BlockWidth = SizeOfX / 100;
+ BlockHeight = SizeOfY / 50;
+
+ BlockNum = Progress;
+
+ PosX = 0;
+ PosY = SizeOfY * 48 / 50;
+
+ if (BlockNum == 0) {
+ //
+ // Clear progress area
+ //
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &Color,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+ //
+ // Show progress by drawing blocks
+ //
+ for (Index = PreviousValue; Index < BlockNum; Index++) {
+ PosX = Index * BlockWidth;
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ } else {
+ Status = UgaDraw->Blt (
+ UgaDraw,
+ (EFI_UGA_PIXEL *) &ProgressColor,
+ EfiUgaVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)
+ );
+ }
+ }
+
+ PrintXY (
+ (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ &TitleForeground,
+ &TitleBackground,
+ Title
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function waits for a given event to fire, or for an optional timeout to expire.
+
+
+ @param Event The event to wait for
+
+ @param Timeout An optional timeout value in 100 ns units.
+
+ @retval EFI_SUCCESS Event fired before Timeout expired.
+ @retval EFI_TIME_OUT Timout expired before Event fired..
+
+**/
+EFI_STATUS
+WaitForSingleEvent (
+ IN EFI_EVENT Event,
+ IN UINT64 Timeout OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[2];
+
+ if (Timeout != 0) {
+ //
+ // Create a timer event
+ //
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+
+ //
+ // Wait for the original event or the timer
+ //
+ WaitList[0] = Event;
+ WaitList[1] = TimerEvent;
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ gBS->CloseEvent (TimerEvent);
+
+ //
+ // If the timer expired, change the return to timed out
+ //
+ if (!EFI_ERROR (Status) && Index == 1) {
+ Status = EFI_TIMEOUT;
+ }
+ }
+ } else {
+ //
+ // No timeout... just wait on the event
+ //
+ Status = gBS->WaitForEvent (1, &Event, &Index);
+ ASSERT (!EFI_ERROR (Status));
+ ASSERT (Index == 0);
+ }
+
+ return Status;
+}
+
+/**
+ Function show progress bar to wait for user input.
+
+
+ @param TimeoutDefault - The fault time out value before the system
+ continue to boot.
+
+ @retval EFI_SUCCESS User pressed some key except "Enter"
+ @retval EFI_TIME_OUT Timout expired or user press "Enter"
+
+**/
+EFI_STATUS
+ShowProgress (
+ IN UINT16 TimeoutDefault
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TmpStr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
+ EFI_INPUT_KEY Key;
+ UINT16 TimeoutRemain;
+
+ if (TimeoutDefault == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ DEBUG ((EFI_D_INFO, "\n\nStart showing progress bar... Press any key to stop it! ...Zzz....\n"));
+
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
+
+ //
+ // Clear the progress status bar first
+ //
+ TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION));
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (Foreground, Background, TmpStr, Color, 0, 0);
+ }
+
+ TimeoutRemain = TimeoutDefault;
+ while (TimeoutRemain != 0) {
+ DEBUG ((EFI_D_INFO, "Showing progress bar...Remaining %d second!\n", TimeoutRemain));
+
+ Status = WaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND);
+ if (Status != EFI_TIMEOUT) {
+ break;
+ }
+ TimeoutRemain--;
+
+ //
+ // Show progress
+ //
+ if (TmpStr != NULL) {
+ PlatformBdsShowProgress (
+ Foreground,
+ Background,
+ TmpStr,
+ Color,
+ ((TimeoutDefault - TimeoutRemain) * 100 / TimeoutDefault),
+ 0
+ );
+ }
+ }
+ gBS->FreePool (TmpStr);
+
+ //
+ // Timeout expired
+ //
+ if (TimeoutRemain == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ //
+ // User pressed some key
+ //
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ //
+ // User pressed enter, equivalent to select "continue"
+ //
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the default value for system Timeout variable.
+
+ @return Timeout value.
+
+**/
+UINT16
+EFIAPI
+GetTimeout (
+ VOID
+ )
+{
+ UINT16 Timeout;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ //
+ // Return Timeout variable or 0xffff if no valid
+ // Timeout variable exists.
+ //
+ Size = sizeof (UINT16);
+ Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout);
+ if (EFI_ERROR (Status)) {
+ //
+ // According to UEFI 2.0 spec, it should treat the Timeout value as 0xffff
+ // (default value PcdPlatformBootTimeOutDefault) when L"Timeout" variable is not present.
+ // To make the current EFI Automatic-Test activity possible, platform can choose other value
+ // for automatic boot when the variable is not present.
+ //
+ Timeout = PcdGet16 (PcdPlatformBootTimeOutDefault);
+ }
+
+ return Timeout;
+}
+
+
+/**
+ This is the Framework Setup Browser interface which displays a FormSet.
+
+ @param This The EFI_FORM_BROWSER_PROTOCOL context.
+ @param UseDatabase TRUE if the FormSet is from HII database. The Thunk implementation
+ only support UseDatabase is TRUE.
+ @param Handle The Handle buffer.
+ @param HandleCount The number of Handle in the Handle Buffer. It must be 1 for this implementation.
+ @param Packet The pointer to data buffer containing IFR and String package. Not supported.
+ @param CallbackHandle Not supported.
+ @param NvMapOverride The buffer is used only when there is no NV variable to define the
+ current settings and the caller needs to provide to the browser the
+ current settings for the the "fake" NV variable. If used, no saving of
+ an NV variable is possbile. This parameter is also ignored if Handle is NULL.
+
+ @retval EFI_SUCCESS If the Formset is displayed correctly.
+ @retval EFI_UNSUPPORTED If UseDatabase is FALSE or HandleCount is not 1.
+ @retval EFI_INVALID_PARAMETER If the *Handle passed in is not found in the database.
+**/
+
+EFI_STATUS
+EFIAPI
+ThunkSendForm (
+ IN EFI_FORM_BROWSER_PROTOCOL *This,
+ IN BOOLEAN UseDatabase,
+ IN FRAMEWORK_EFI_HII_HANDLE *Handle,
+ IN UINTN HandleCount,
+ IN FRAMEWORK_EFI_IFR_PACKET *Packet, OPTIONAL
+ IN EFI_HANDLE CallbackHandle, OPTIONAL
+ IN UINT8 *NvMapOverride, OPTIONAL
+ IN FRAMEWORK_EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL
+ OUT BOOLEAN *ResetRequired OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ HII_THUNK_CONTEXT *ThunkContext;
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_FORMBROWSER_THUNK_PRIVATE_DATA *BrowserPrivate;
+
+ if (!UseDatabase) {
+ //
+ // ThunkSendForm only support displays forms registered into the HII database.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (HandleCount != 1 ) {
+ return EFI_UNSUPPORTED;
+ }
+
+ BrowserPrivate = EFI_FORMBROWSER_THUNK_PRIVATE_DATA_FROM_THIS (This);
+ Private = BrowserPrivate->ThunkPrivate;
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, *Handle);
+ if (ThunkContext == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Following UEFI spec to do auto booting after a time-out. This feature is implemented
+ // in Framework Setup Browser and moved to MdeModulePkg/Universal/BdsDxe. The auto booting is
+ // moved here in HII Thunk module.
+ //
+ if (CompareGuid (&gFrameworkBdsFrontPageFormsetGuid, &ThunkContext->FormSet->Guid) && !mFrontPageDisplayed) {
+ //
+ // Send form is called before entering the
+ //
+ mFrontPageDisplayed = TRUE;
+ Status = ShowProgress (GetTimeout ());
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (NvMapOverride != NULL) {
+ ThunkContext->NvMapOverride = NvMapOverride;
+ }
+
+ Status = mFormBrowser2Protocol->SendForm (
+ mFormBrowser2Protocol,
+ &ThunkContext->UefiHiiHandle,
+ 1,
+ NULL,
+ 0,
+ (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions,
+ &ActionRequest
+ );
+
+ if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
+ *ResetRequired = TRUE;
+ }
+
+ return Status;
+}
+
+/**
+
+ Rountine used to display a generic dialog interface and return
+ the Key or Input from user input.
+
+ @param NumberOfLines The number of lines for the dialog box.
+ @param HotKey Defines if a single character is parsed (TRUE) and returned in KeyValue
+ or if a string is returned in StringBuffer.
+ @param MaximumStringSize The maximum size in bytes of a typed-in string.
+ @param StringBuffer On return contains the typed-in string if HotKey
+ is FALSE.
+ @param KeyValue The EFI_INPUT_KEY value returned if HotKey is TRUE.
+ @param String The pointer to the first string in the list of strings
+ that comprise the dialog box.
+ @param ... A series of NumberOfLines text strings that will be used
+ to construct the dialog box.
+ @retval EFI_SUCCESS The dialog is created successfully and user interaction was received.
+ @retval EFI_DEVICE_ERROR The user typed in an ESC.
+ @retval EFI_INVALID_PARAMETER One of the parameters was invalid.(StringBuffer == NULL && HotKey == FALSE).
+**/
+EFI_STATUS
+EFIAPI
+ThunkCreatePopUp (
+ IN UINTN NumberOfLines,
+ IN BOOLEAN HotKey,
+ IN UINTN MaximumStringSize,
+ OUT CHAR16 *StringBuffer,
+ OUT EFI_INPUT_KEY *KeyValue,
+ IN CHAR16 *String,
+ ...
+ )
+{
+ EFI_STATUS Status;
+ VA_LIST Marker;
+
+ if (HotKey != TRUE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ VA_START (Marker, String);
+
+ Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, String, Marker);
+
+ VA_END (Marker);
+
+ return Status;
+}
+
+/**
+
+ Initialize string packages in HII database.
+
+**/
+VOID
+InitSetBrowserStrings (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initialize strings to HII database
+ //
+ Status = HiiLibAddPackages (1, &gEfiHiiThunkProducerGuid, NULL, &gStringPackHandle, STRING_ARRAY_NAME);
+ ASSERT_EFI_ERROR (Status);
+
+}
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.h new file mode 100644 index 0000000000..9fd033878e --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/SetupBrowser.h @@ -0,0 +1,25 @@ +/**@file
+ This file contains macros to be included by SetupBrowser.c.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HIITHUNK_SETUPBROWSER_H_
+#define _HIITHUNK_SETUPBROWSER_H_
+
+//
+// In order to follow UEFI spec to do auto booting after a time-out, the GUID of Formset of Frontpage must match this value.
+//
+#define FRAMEWORK_BDS_FRONTPAGE_FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, {0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe }}
+
+#define ONE_SECOND 10000000
+
+#endif
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.c new file mode 100644 index 0000000000..6e966192ac --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.c @@ -0,0 +1,493 @@ +/**@file
+ This file implements the protocol functions related to string package.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiDatabase.h"
+
+typedef struct {
+ CHAR8 *Iso639;
+ CHAR8 *Rfc3066;
+} ISO639TORFC3066MAP;
+
+ISO639TORFC3066MAP Iso639ToRfc3066Map [] = {
+ {"eng", "en-US"},
+ {"fra", "fr-FR"},
+};
+
+CHAR8 *
+ConvertIso639ToRfc3066 (
+ CHAR8 *Iso638Lang
+ )
+{
+ UINTN Index;
+ CHAR8 AsciiLanguage[ISO_639_2_ENTRY_SIZE + 1];
+
+ AsciiStrnCpy (AsciiLanguage, Iso638Lang, sizeof (AsciiLanguage));
+ for (Index = 0; Index < ISO_639_2_ENTRY_SIZE + 1; Index ++) {
+ if (AsciiLanguage [Index] == 0) {
+ break;
+ } else if (AsciiLanguage [Index] >= 'A' && AsciiLanguage [Index] <= 'Z') {
+ AsciiLanguage [Index] = (CHAR8) (AsciiLanguage [Index] - 'A' + 'a');
+ }
+ }
+
+ for (Index = 0; Index < sizeof (Iso639ToRfc3066Map) / sizeof (Iso639ToRfc3066Map[0]); Index++) {
+ if (AsciiStrnCmp (AsciiLanguage, Iso639ToRfc3066Map[Index].Iso639, AsciiStrSize (AsciiLanguage)) == 0) {
+ return Iso639ToRfc3066Map[Index].Rfc3066;
+ }
+ }
+
+ return (CHAR8 *) NULL;
+}
+
+/**
+ Test if all of the characters in a string have corresponding font characters.
+
+ This is a deprecated API. No Framework HII module is calling it. This function will ASSERT and
+ return EFI_UNSUPPORTED.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param StringToTest A pointer to a Unicode string.
+ @param FirstMissing A pointer to an index into the string. On input, the index of
+ the first character in the StringToTest to examine. On exit, the index
+ of the first character encountered for which a glyph is unavailable.
+ If all glyphs in the string are available, the index is the index of the terminator
+ of the string.
+ @param GlyphBufferSize A pointer to a value. On output, if the function returns EFI_SUCCESS,
+ it contains the amount of memory that is required to store the string¡¯s glyph equivalent.
+
+ @retval EFI_UNSUPPORTED The function performs nothing and return EFI_UNSUPPORTED.
+**/
+EFI_STATUS
+EFIAPI
+HiiTestString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *StringToTest,
+ IN OUT UINT32 *FirstMissing,
+ OUT UINT32 *GlyphBufferSize
+ )
+{
+ ASSERT (FALSE);
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Find the corressponding TAG GUID from a Framework HII Handle given.
+
+ @param Private The HII Thunk Module Private context.
+ @param FwHiiHandle The Framemwork HII Handle.
+ @param TagGuid The output of TAG GUID found.
+
+ @return NULL If Framework HII Handle is invalid.
+ @return The corresponding HII Thunk Context.
+**/
+EFI_STATUS
+GetTagGuidByFwHiiHandle (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle,
+ OUT EFI_GUID *TagGuid
+ )
+{
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ ASSERT (TagGuid != NULL);
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (FwHiiHandle == ThunkContext->FwHiiHandle) {
+ CopyGuid (TagGuid, &ThunkContext->TagGuid);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Create or update the String given a new string and String ID.
+
+ @param ThunkContext The Thunk Context.
+ @param Rfc3066AsciiLanguage The RFC 3066 Language code in ASCII string format.
+ @param NewString The new string.
+ @param StringId The String ID. If StringId is 0, a new String Token
+ is created. Otherwise, the String Token StringId is
+ updated.
+
+
+ @retval EFI_SUCCESS The new string is created or updated successfully.
+ The new String Token ID is returned in StringId if
+ *StringId is 0 on input.
+ @return Others The update of string failed.
+
+**/
+EFI_STATUS
+UpdateString (
+ IN CONST HII_THUNK_CONTEXT *ThunkContext,
+ IN CONST CHAR8 *Rfc3066AsciiLanguage,
+ IN CHAR16 *NewString,
+ IN OUT STRING_REF *StringId
+ )
+{
+ EFI_STRING_ID NewStringId;
+ EFI_STATUS Status;
+
+
+ NewStringId = 0;
+
+ if (*StringId == 0) {
+ //
+ // Create a new string token.
+ //
+ if (Rfc3066AsciiLanguage == NULL) {
+ //
+ // For all languages in the package list.
+ //
+ Status = HiiLibNewString (ThunkContext->UefiHiiHandle, &NewStringId, NewString);
+ } else {
+ //
+ // For specified language.
+ //
+ Status = mHiiStringProtocol->NewString (
+ mHiiStringProtocol,
+ ThunkContext->UefiHiiHandle,
+ &NewStringId,
+ Rfc3066AsciiLanguage,
+ NULL,
+ NewString,
+ NULL
+ );
+ }
+ } else {
+ //
+ // Update the existing string token.
+ //
+ if (Rfc3066AsciiLanguage == NULL) {
+ //
+ // For all languages in the package list.
+ //
+ Status = HiiLibSetString (ThunkContext->UefiHiiHandle, *StringId, NewString);
+ } else {
+ //
+ // For specified language.
+ //
+ Status = mHiiStringProtocol->SetString (
+ mHiiStringProtocol,
+ ThunkContext->UefiHiiHandle,
+ *StringId,
+ Rfc3066AsciiLanguage,
+ NewString,
+ NULL
+ );
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ if (*StringId == 0) {
+ //
+ // When creating new string, return the newly created String Token.
+ //
+ *StringId = NewStringId;
+ }
+ } else {
+ //
+ // Only EFI_INVALID_PARAMETER is defined in HII 0.92 specification.
+ //
+ *StringId = 0;
+ }
+
+ return Status;
+}
+
+/**
+ Create or update a String Token in a String Package.
+
+ If *Reference == 0, a new String Token is created.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Language Pointer to a NULL-terminated string containing a single ISO 639-2 language
+ identifier, indicating the language to print. A string consisting of
+ all spaces indicates that the string is applicable to all languages.
+ @param Handle The handle of the language pack to which the string is to be added.
+ @param Token The string token assigned to the string.
+ @param NewString The string to be added.
+
+
+ @retval EFI_SUCCESS The string was effectively registered.
+ @retval EFI_INVALID_PARAMETER The Handle was unknown. The string is not created or updated in the
+ the string package.
+**/
+
+EFI_STATUS
+EFIAPI
+HiiNewString (
+ IN EFI_HII_PROTOCOL *This,
+ IN CHAR16 *Language,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN OUT STRING_REF *Reference,
+ IN CHAR16 *NewString
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_PRIVATE_DATA *Private;
+ EFI_GUID TagGuid;
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+ HII_THUNK_CONTEXT *StringPackThunkContext;
+ EFI_STRING_ID StringId;
+ EFI_STRING_ID LastStringId;
+ CHAR8 AsciiLanguage[ISO_639_2_ENTRY_SIZE + 1];
+ CHAR16 LanguageCopy[ISO_639_2_ENTRY_SIZE + 1];
+ CHAR8 *Rfc3066AsciiLanguage;
+
+ LastStringId = (EFI_STRING_ID) 0;
+ StringId = (EFI_STRING_ID) 0;
+ Rfc3066AsciiLanguage = NULL;
+
+ if (Language != NULL) {
+ ZeroMem (AsciiLanguage, sizeof (AsciiLanguage));;
+ ZeroMem (LanguageCopy, sizeof (LanguageCopy));
+ CopyMem (LanguageCopy, Language, ISO_639_2_ENTRY_SIZE * sizeof (CHAR16));
+ UnicodeStrToAsciiStr (LanguageCopy, AsciiLanguage);
+ Rfc3066AsciiLanguage = ConvertIso639ToRfc3066 (AsciiLanguage);
+ ASSERT (Rfc3066AsciiLanguage != NULL);
+ }
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ StringPackThunkContext = FwHiiHandleToThunkContext (Private, Handle);
+ if (StringPackThunkContext == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (StringPackThunkContext->SharingStringPack) {
+ Status = GetTagGuidByFwHiiHandle (Private, Handle, &TagGuid);
+ ASSERT_EFI_ERROR (Status);
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (CompareGuid (&TagGuid, &ThunkContext->TagGuid)) {
+ if (ThunkContext->SharingStringPack) {
+ StringId = *Reference;
+ Status = UpdateString (ThunkContext, Rfc3066AsciiLanguage, NewString, &StringId);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ DEBUG_CODE_BEGIN ();
+ if (*Reference == 0) {
+ //
+ // When creating new string token, make sure all created token is the same
+ // for all string packages registered using FW HII interface.
+ //
+ if (LastStringId == (EFI_STRING_ID) 0) {
+ LastStringId = StringId;
+ } else {
+ if (LastStringId != StringId) {
+ ASSERT(FALSE);
+ }
+ }
+ }
+ DEBUG_CODE_END ();
+
+ }
+ }
+
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+ } else {
+ StringId = *Reference;
+ Status = UpdateString (StringPackThunkContext, Rfc3066AsciiLanguage, NewString, &StringId);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ if (*Reference == 0) {
+ *Reference = StringId;
+ }
+ } else {
+ //
+ // Only EFI_INVALID_PARAMETER is defined in HII 0.92 specification.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/**
+ This function removes any new strings that were added after the initial string export for this handle.
+ UEFI HII String Protocol does not have Reset String function. This function perform nothing.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle The HII handle on which the string resides.
+
+ @retval EFI_SUCCESS This function is a NOP and always return EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiResetStrings (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ This function extracts a string from a package already registered with the EFI HII database.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle The HII handle on which the string resides.
+ @param Token The string token assigned to the string.
+ @param Raw If 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.
+ @param LanguageString Pointer to a NULL-terminated string containing a single ISO 639-2 language
+ identifier, indicating the language to print. If the LanguageString is empty (starts
+ with a NULL), the default system language will be used to determine the language.
+ @param BufferLength Length of the StringBuffer. If the status reports that the buffer width is too
+ small, this parameter is filled with the length of the buffer needed.
+ @param StringBuffer The buffer designed to receive the characters in the string. Type EFI_STRING is
+ defined in String.
+
+ @retval EFI_INVALID_PARAMETER If input parameter is invalid.
+ @retval EFI_BUFFER_TOO_SMALL If the *BufferLength is too small.
+ @retval EFI_SUCCESS Operation is successful.
+
+**/
+EFI_STATUS
+EFIAPI
+HiiGetString (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_EFI_HII_HANDLE Handle,
+ IN STRING_REF Token,
+ IN BOOLEAN Raw,
+ IN CHAR16 *LanguageString,
+ IN OUT UINTN *BufferLengthTemp,
+ OUT EFI_STRING StringBuffer
+ )
+{
+ CHAR8 *Iso639AsciiLanguage;
+ HII_THUNK_PRIVATE_DATA *Private;
+ CHAR8 *Rfc3066AsciiLanguage;
+ EFI_HII_HANDLE UefiHiiHandle;
+ EFI_STATUS Status;
+
+ Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);
+
+ Iso639AsciiLanguage = NULL;
+ Rfc3066AsciiLanguage = NULL;
+
+ if (LanguageString != NULL) {
+ Iso639AsciiLanguage = AllocateZeroPool (StrLen (LanguageString) + 1);
+ if (Iso639AsciiLanguage == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ UnicodeStrToAsciiStr (LanguageString, Iso639AsciiLanguage);
+
+ //
+ // Caller of Framework HII Interface uses the Language Identification String defined
+ // in Iso639. So map it to the Language Identifier defined in RFC3066.
+ //
+ Rfc3066AsciiLanguage = ConvertIso639ToRfc3066 (Iso639AsciiLanguage);
+
+ //
+ // If Rfc3066AsciiLanguage is NULL, more language mapping must be added to
+ // Iso639ToRfc3066Map.
+ //
+ ASSERT (Rfc3066AsciiLanguage != NULL);
+
+ }
+
+ UefiHiiHandle = FwHiiHandleToUefiHiiHandle (Private, Handle);
+ if (UefiHiiHandle == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+
+ if (Rfc3066AsciiLanguage == NULL) {
+ Status = HiiLibGetString (UefiHiiHandle, Token, StringBuffer, BufferLengthTemp);
+ } else {
+ Status = mHiiStringProtocol->GetString (
+ mHiiStringProtocol,
+ Rfc3066AsciiLanguage,
+ UefiHiiHandle,
+ Token,
+ StringBuffer,
+ BufferLengthTemp,
+ NULL
+ );
+ }
+
+Done:
+ if (Iso639AsciiLanguage != NULL) {
+ FreePool (Iso639AsciiLanguage);
+ }
+
+ return Status;
+}
+
+/**
+
+ This function allows a program to extract a part of a string of not more than a given width.
+ With repeated calls, this allows a calling program to extract "lines" of text that fit inside
+ columns. The effort of measuring the fit of strings inside columns is localized to this call.
+
+ This is a deprecated API. No Framework HII module is calling it. This function will ASSERT and
+ return EFI_UNSUPPORTED.
+
+ @param This A pointer to the EFI_HII_PROTOCOL instance.
+ @param Handle The HII handle on which the string resides.
+ @param Token The string token assigned to the string.
+ @param Raw If 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.
+ @param LanguageString Pointer to a NULL-terminated string containing a single ISO 639-2 language
+ identifier, indicating the language to print. If the LanguageString is empty (starts
+ with a NULL), the default system language will be used to determine the language.
+ @param BufferLength Length of the StringBuffer. If the status reports that the buffer width is too
+ small, this parameter is filled with the length of the buffer needed.
+ @param StringBuffer The buffer designed to receive the characters in the string. Type EFI_STRING is
+ defined in String.
+
+ @retval EFI_UNSUPPORTED.
+**/
+EFI_STATUS
+EFIAPI
+HiiGetLine (
+ IN EFI_HII_PROTOCOL *This,
+ IN FRAMEWORK_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
+ )
+{
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.uni b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.uni Binary files differnew file mode 100644 index 0000000000..9de7663df9 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.uni diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrDefault.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrDefault.c new file mode 100644 index 0000000000..e1924791af --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrDefault.c @@ -0,0 +1,551 @@ +/** @file
+ Function and Macro defintions for to extract default values from UEFI Form package.
+
+ Copyright (c) 2008, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HiiDatabase.h"
+#include "UefiIfrParser.h"
+#include "UefiIfrDefault.h"
+
+//
+// Extern Variables
+//
+extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+extern CONST EFI_HII_IMAGE_PROTOCOL *mHiiImageProtocol;
+extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProtocol;
+extern CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRoutingProtocol;
+
+/**
+ Set the data position at Offset with Width in Node->Buffer based
+ the value passed in.
+
+ @param Node The Buffer Storage Node.
+ @param Value The input value.
+ @param Offset The offset in Node->Buffer for the update.
+ @param Width The length of the Value.
+
+ @retval VOID
+
+**/
+VOID
+SetNodeBuffer (
+ OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node,
+ IN CONST EFI_HII_VALUE *Value,
+ IN UINTN Offset,
+ IN UINTN Width
+ )
+{
+ ASSERT (Node->Signature == UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE);
+ ASSERT (Offset + Width <= Node->Size);
+
+ CopyMem (Node->Buffer + Offset, &Value->Value.u8, Width);
+}
+
+
+/**
+ Reset Question to its default value.
+
+ Note Framework 0.92's HII Implementation does not support for default value for these opcodes:
+ EFI_IFR_ORDERED_LIST_OP:
+ EFI_IFR_PASSWORD_OP:
+ EFI_IFR_STRING_OP:
+
+ @param FormSet FormSet data structure.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS Question is reset to default value.
+
+**/
+EFI_STATUS
+GetQuestionDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINT16 DefaultId,
+ IN UINT16 VarStoreId,
+ OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ QUESTION_DEFAULT *Default;
+ QUESTION_OPTION *Option;
+ EFI_HII_VALUE *HiiValue;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Statement don't have storage, skip them
+ //
+ if (Question->QuestionId == 0) {
+ return Status;
+ }
+
+ if (Question->VarStoreId != VarStoreId) {
+ return Status;
+ }
+
+ ASSERT (Question->Storage->Type == EFI_HII_VARSTORE_BUFFER);
+
+ //
+ // There are three ways to specify default value for a Question:
+ // 1, use nested EFI_IFR_DEFAULT (highest priority)
+ // 2, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
+ // 3, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
+ //
+ HiiValue = &Question->HiiValue;
+
+ //
+ // EFI_IFR_DEFAULT has highest priority
+ //
+ if (!IsListEmpty (&Question->DefaultListHead)) {
+ Link = GetFirstNode (&Question->DefaultListHead);
+ while (!IsNull (&Question->DefaultListHead, Link)) {
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);
+
+ if (Default->DefaultId == DefaultId) {
+ //
+ // Default value is embedded in EFI_IFR_DEFAULT
+ //
+ CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
+
+ SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->DefaultListHead, Link);
+ }
+ }
+
+ //
+ // EFI_ONE_OF_OPTION
+ //
+ if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // OneOfOption could only provide Standard and Manufacturing default
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Option->Flags & EFI_IFR_OPTION_DEFAULT)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG))
+ ) {
+ CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
+
+ SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
+ return EFI_SUCCESS;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ }
+ }
+
+ //
+ // EFI_IFR_CHECKBOX - lowest priority
+ //
+ if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
+ if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
+ //
+ // Checkbox could only provide Standard and Manufacturing default
+ //
+ if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT)) ||
+ ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && (Question->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG))
+ ) {
+ HiiValue->Value.b = TRUE;
+ } else {
+ HiiValue->Value.b = FALSE;
+ }
+
+ SetNodeBuffer (Node, HiiValue, Question->VarStoreInfo.VarOffset, Question->StorageWidth);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Reset Questions in a Form to their default value.
+
+ @param FormSet FormSet data structure.
+ @param Form The Form which to be reset.
+ @param DefaultId The Class of the default.
+
+ @retval EFI_SUCCESS The function completed successfully.
+
+**/
+EFI_STATUS
+ExtractFormDefault (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN UINT16 DefaultId,
+ IN UINT16 VarStoreId,
+ OUT UEFI_IFR_BUFFER_STORAGE_NODE *Node
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ //
+ // Reset Question to its default value
+ //
+ Status = GetQuestionDefault (FormSet, Form, Question, DefaultId, VarStoreId, Node);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Destroy all the buffer allocated for the fileds of
+ UEFI_IFR_BUFFER_STORAGE_NODE. The Node itself
+ will be freed too.
+
+ @param FormSet FormSet data structure.
+ @param DefaultId The Class of the default.
+
+ @retval VOID
+
+**/
+VOID
+DestroyDefaultNode (
+ IN UEFI_IFR_BUFFER_STORAGE_NODE *Node
+ )
+{
+ FreePool (Node->Buffer);
+ FreePool (Node->Name);
+ FreePool (Node);
+}
+
+
+/**
+ Get the default value for Buffer Type storage named by
+ a Default Store and a Storage Store from a FormSet.
+ The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
+ allocated by this function. It is inserted to the link list.
+
+ @param DefaultStore The Default Store.
+ @param Storage The Storage.
+ @param FormSet The Form Set.
+ @param UefiDefaultsListHead The head of link list for the output.
+
+ @retval EFI_SUCCESS Successful.
+
+**/
+EFI_STATUS
+GetBufferTypeDefaultIdAndStorageId (
+ IN FORMSET_DEFAULTSTORE *DefaultStore,
+ IN FORMSET_STORAGE *Storage,
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT LIST_ENTRY *UefiDefaultsListHead
+ )
+{
+ UEFI_IFR_BUFFER_STORAGE_NODE *Node;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_FORM *Form;
+ EFI_STATUS Status;
+
+ Node = AllocateZeroPool (sizeof (UEFI_IFR_BUFFER_STORAGE_NODE));
+ ASSERT (Node != NULL);
+
+ Node->Signature = UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE;
+ Node->Name = AllocateCopyPool (StrSize (Storage->Name), Storage->Name);
+ Node->DefaultId = DefaultStore->DefaultId;
+ Node->StoreId = Storage->VarStoreId;
+ CopyGuid (&Node->Guid, &Storage->Guid);
+ Node->Size = Storage->Size;
+ Node->Buffer = AllocateZeroPool (Node->Size);
+ //
+ // Extract default from IFR binary
+ //
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+ Status = ExtractFormDefault (FormSet, Form, DefaultStore->DefaultId, Storage->VarStoreId, Node);
+ ASSERT_EFI_ERROR (Status);
+
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+ }
+
+ InsertTailList (UefiDefaultsListHead, &Node->List);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get the default value for Buffer Type storage named by
+ a Default Store from a FormSet.
+ The result is in the a instance of UEFI_IFR_BUFFER_STORAGE_NODE
+ allocated by this function. The output can be multiple instances
+ of UEFI_IFR_BUFFER_STORAGE_NODE. It is inserted to the link list.
+
+ @param DefaultStore The Default Store.
+ @param FormSet The Form Set.
+ @param UefiDefaultsListHead The head of link list for the output.
+
+ @retval EFI_SUCCESS Successful.
+
+**/
+EFI_STATUS
+GetBufferTypeDefaultId (
+ IN FORMSET_DEFAULTSTORE *DefaultStore,
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT LIST_ENTRY *UefiDefaultsListHead
+ )
+{
+ LIST_ENTRY *StorageLink;
+ FORMSET_STORAGE *Storage;
+ EFI_STATUS Status;
+
+ StorageLink = GetFirstNode (&FormSet->StorageListHead);
+
+ while (!IsNull (&FormSet->StorageListHead, StorageLink)) {
+ Storage = FORMSET_STORAGE_FROM_LINK(StorageLink);
+
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
+ Status = GetBufferTypeDefaultIdAndStorageId (DefaultStore, Storage, FormSet, UefiDefaultsListHead);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ StorageLink = GetNextNode (&FormSet->StorageListHead, StorageLink);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Get the default value for Buffer Type storage from the first FormSet
+ in the Package List specified by a EFI_HII_HANDLE.
+
+ The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE.
+ They are inserted to the link list.
+
+ @param UefiHiiHandle The handle for the package list.
+ @param UefiDefaultsListHead The head of link list for the output.
+
+ @retval EFI_SUCCESS Successful.
+
+**/
+EFI_STATUS
+UefiIfrGetBufferTypeDefaults (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ OUT LIST_ENTRY **UefiDefaults
+ )
+{
+ LIST_ENTRY *DefaultLink;
+ FORMSET_DEFAULTSTORE *DefaultStore;
+ EFI_STATUS Status;
+
+ ASSERT (UefiDefaults != NULL);
+
+ *UefiDefaults = AllocateZeroPool (sizeof (LIST_ENTRY));
+ ASSERT (UefiDefaults != NULL);
+ InitializeListHead (*UefiDefaults);
+
+ DefaultLink = GetFirstNode (&ThunkContext->FormSet->DefaultStoreListHead);
+ while (!IsNull (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink)) {
+ DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);
+
+ Status = GetBufferTypeDefaultId (DefaultStore, ThunkContext->FormSet, *UefiDefaults);
+ ASSERT_EFI_ERROR (Status);
+
+ DefaultLink = GetNextNode (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Convert the UEFI Buffer Type default values to a Framework HII default
+ values specified by a EFI_HII_VARIABLE_PACK_LIST structure.
+
+ @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
+ which contains the default values retrived from
+ a UEFI form set.
+ @param DefaultMask The default mask.
+ The valid values are FRAMEWORK_EFI_IFR_FLAG_DEFAULT
+ and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
+ UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
+ from specification to valid default class.
+ @param VariablePackList The output default value in a format defined in Framework.
+
+
+ @retval EFI_SUCCESS Successful.
+ @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or
+ FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
+**/
+EFI_STATUS
+UefiDefaultsToFwDefaults (
+ IN LIST_ENTRY *ListHead,
+ IN UINTN DefaultMask,
+ IN EFI_VARSTORE_ID UefiFormSetDefaultVarStoreId,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ )
+{
+ LIST_ENTRY *List;
+ UEFI_IFR_BUFFER_STORAGE_NODE *Node;
+ UINTN Size;
+ UINTN Count;
+ UINT16 DefaultId;
+ EFI_HII_VARIABLE_PACK *Pack;
+ EFI_HII_VARIABLE_PACK_LIST *PackList;
+ UINTN Index;
+
+ if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_DEFAULT) {
+ DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
+ } else if (DefaultMask == FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING) {
+ DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
+ } else {
+ //
+ // UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
+ // from specification to valid default class.
+ //
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Calculate the size of the output EFI_HII_VARIABLE_PACK_LIST structure
+ //
+ Size = 0;
+ Count = 0;
+ List = GetFirstNode (ListHead);
+ while (!IsNull (ListHead, List)) {
+ Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
+
+ if (Node->DefaultId == DefaultId) {
+ Size += Node->Size;
+ Size += StrSize (Node->Name);
+
+ Count++;
+ }
+
+ List = GetNextNode (ListHead, List);
+ }
+
+ if (Count == 0) {
+ *VariablePackList = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ Size = Size + Count * (sizeof (EFI_HII_VARIABLE_PACK_LIST) + sizeof (EFI_HII_VARIABLE_PACK));
+
+ *VariablePackList = AllocateZeroPool (Size);
+ ASSERT (*VariablePackList != NULL);
+
+ List = GetFirstNode (ListHead);
+
+ PackList = (EFI_HII_VARIABLE_PACK_LIST *) *VariablePackList;
+ Pack = (EFI_HII_VARIABLE_PACK *) (PackList + 1);
+ Index = 0;
+ while (!IsNull (ListHead, List)) {
+ Node = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(List);
+
+ Size = 0;
+ if (Node->DefaultId == DefaultId) {
+ Size += Node->Size;
+ Size += sizeof (EFI_HII_VARIABLE_PACK);
+
+ Pack->VariableNameLength = (UINT32) StrSize (Node->Name);
+
+ if (Node->StoreId == UefiFormSetDefaultVarStoreId) {
+ //
+ // The default VARSTORE in VFR from a Framework module has Varstore ID of 0.
+ //
+ Pack->VariableId = 0;
+ } else {
+ Pack->VariableId = Node->StoreId;
+ }
+
+ CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK), Node->Name, StrSize (Node->Name));
+ Size += Pack->VariableNameLength;
+
+ //
+ // Initialize EFI_HII_VARIABLE_PACK
+ //
+ Pack->Header.Type = 0;
+ Pack->Header.Length = (UINT32) Size;
+ CopyMem (&Pack->VariableGuid, &Node->Guid, sizeof (EFI_GUID));
+
+ CopyMem ((UINT8 *) Pack + sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength, Node->Buffer, Node->Size);
+
+ Size += sizeof (EFI_HII_VARIABLE_PACK_LIST);
+
+ //
+ // Initialize EFI_HII_VARIABLE_PACK_LIST
+ //
+ PackList->VariablePack = Pack;
+ Index++;
+ if (Index < Count) {
+ PackList->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *)((UINT8 *) PackList + Size);
+
+ PackList = PackList->NextVariablePack;
+ Pack = (EFI_HII_VARIABLE_PACK *) (PackList + 1);
+ }
+
+ }
+
+ List = GetNextNode (ListHead, List);
+ }
+
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE.
+
+ @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
+ which contains the default values retrived from
+ a UEFI form set.
+
+
+ @retval VOID
+**/
+VOID
+FreeDefaultList (
+ IN LIST_ENTRY *ListHead
+ )
+{
+ LIST_ENTRY *Link;
+ UEFI_IFR_BUFFER_STORAGE_NODE *Default;
+
+ while (!IsListEmpty (ListHead)) {
+ Link = GetFirstNode (ListHead);
+
+ Default = UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(Link);
+
+ RemoveEntryList (Link);
+
+ DestroyDefaultNode (Default);
+ }
+
+ FreePool (ListHead);
+}
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrDefault.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrDefault.h new file mode 100644 index 0000000000..e06b2829c3 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrDefault.h @@ -0,0 +1,99 @@ +/** @file
+ Header file for Function and Macro defintions for to extract default values from UEFI Form package.
+
+ Copyright (c) 2008, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HII_THUNK_UEFI_IFR_DEFAULT_
+#define _HII_THUNK_UEFI_IFR_DEFAULT_
+
+#define UEFI_IFR_BUFFER_STORAGE_NODE_FROM_LIST(a) CR(a, UEFI_IFR_BUFFER_STORAGE_NODE, List, UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE)
+#define UEFI_IFR_BUFFER_STORAGE_NODE_SIGNATURE SIGNATURE_32 ('I', 'b', 'S', 'n')
+typedef struct {
+ LIST_ENTRY List;
+ UINT32 Signature;
+
+ EFI_GUID Guid;
+ CHAR16 *Name;
+ UINT16 DefaultId;
+ UINT16 StoreId;
+ UINTN Size;
+ UINT8 *Buffer;
+
+} UEFI_IFR_BUFFER_STORAGE_NODE;
+
+/**
+ Get the default value for Buffer Type storage from the first FormSet
+ in the Package List specified by a EFI_HII_HANDLE.
+
+ The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE.
+ They are inserted to the link list.
+
+ @param UefiHiiHandle The handle for the package list.
+ @param UefiDefaultsListHead The head of link list for the output.
+
+ @retval EFI_SUCCESS Successful.
+
+**/
+EFI_STATUS
+UefiIfrGetBufferTypeDefaults (
+ IN HII_THUNK_CONTEXT *ThunkContext,
+ OUT LIST_ENTRY **UefiDefaults
+);
+
+/**
+ Convert the UEFI Buffer Type default values to a Framework HII default
+ values specified by a EFI_HII_VARIABLE_PACK_LIST structure.
+
+ @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
+ which contains the default values retrived from
+ a UEFI form set.
+ @param DefaultMask The default mask.
+ The valid values are FRAMEWORK_EFI_IFR_FLAG_DEFAULT
+ and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
+ UEFI spec only map FRAMEWORK_EFI_IFR_FLAG_DEFAULT and FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING
+ from specification to valid default class.
+ @param VariablePackList The output default value in a format defined in Framework.
+
+
+ @retval EFI_SUCCESS Successful.
+ @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or
+ FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
+**/
+
+EFI_STATUS
+UefiDefaultsToFwDefaults (
+ IN LIST_ENTRY *UefiIfrDefaults,
+ IN UINTN DefaultMask,
+ IN EFI_VARSTORE_ID UefiFormSetDefaultVarStoreId,
+ OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList
+ );
+
+/**
+ Free up all buffer allocated for the link list of UEFI_IFR_BUFFER_STORAGE_NODE.
+
+ @param ListHead The link list of UEFI_IFR_BUFFER_STORAGE_NODE
+ which contains the default values retrived from
+ a UEFI form set.
+
+
+ @retval EFI_SUCCESS Successful.
+ @retval EFI_INVALID_PARAMETER The default mask is not FRAMEWORK_EFI_IFR_FLAG_DEFAULT or
+ FRAMEWORK_EFI_IFR_FLAG_MANUFACTURING.
+**/
+VOID
+FreeDefaultList (
+ IN LIST_ENTRY *UefiIfrDefaults
+ );
+
+#endif
+
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.c new file mode 100644 index 0000000000..050c3c29b8 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.c @@ -0,0 +1,1089 @@ +/** @file
+Parser for IFR binary encoding.
+
+Copyright (c) 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <Protocol/Print.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/IfrSupportLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <MdeModuleHii.h>
+
+#include "UefiIfrParser.h"
+
+#include "UefiIfrParserExpression.h"
+
+UINT16 mStatementIndex;
+
+BOOLEAN mInScopeSubtitle;
+BOOLEAN mInScopeSuppress;
+BOOLEAN mInScopeGrayOut;
+
+EFI_GUID mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID;
+extern EFI_GUID mTianoHiiIfrGuid;
+
+LIST_ENTRY *
+GetOneOfOptionMapEntryListHead (
+ IN CONST FORM_BROWSER_FORMSET *FormSet,
+ IN UINT16 QuestionId
+ )
+{
+ LIST_ENTRY *Link;
+ ONE_OF_OPTION_MAP *Map;
+
+ Link = GetFirstNode (&FormSet->OneOfOptionMapListHead);
+
+ while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) {
+ Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);
+ if (QuestionId == Map->QuestionId) {
+ return &Map->OneOfOptionMapEntryListHead;
+ }
+ Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link);
+ }
+
+ return NULL;
+}
+
+VOID
+DestoryOneOfOptionMap (
+ IN LIST_ENTRY *OneOfOptionMapListHead
+ )
+{
+ ONE_OF_OPTION_MAP *Map;
+ ONE_OF_OPTION_MAP_ENTRY *MapEntry;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *Link2;
+
+ while (!IsListEmpty (OneOfOptionMapListHead)) {
+ Link = GetFirstNode (OneOfOptionMapListHead);
+
+ Map = ONE_OF_OPTION_MAP_FROM_LINK (Link);
+
+ while (!IsListEmpty (&Map->OneOfOptionMapEntryListHead)) {
+ Link2 = GetFirstNode (&Map->OneOfOptionMapEntryListHead);
+
+ MapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);
+
+ RemoveEntryList (Link2);
+
+ FreePool (MapEntry);
+ }
+
+ RemoveEntryList (Link);
+ FreePool (Map);
+ }
+}
+
+
+/**
+ Initialize Statement header members.
+
+ @param OpCodeData Pointer of the raw OpCode data.
+ @param FormSet Pointer of the current FormSe.
+ @param Form Pointer of the current Form.
+
+ @return The Statement.
+
+**/
+FORM_BROWSER_STATEMENT *
+CreateStatement (
+ IN UINT8 *OpCodeData,
+ IN OUT FORM_BROWSER_FORMSET *FormSet,
+ IN OUT FORM_BROWSER_FORM *Form
+ )
+{
+ FORM_BROWSER_STATEMENT *Statement;
+ EFI_IFR_STATEMENT_HEADER *StatementHdr;
+
+ if (Form == NULL) {
+ //
+ // We are currently not in a Form Scope, so just skip this Statement
+ //
+ return NULL;
+ }
+
+ Statement = &FormSet->StatementBuffer[mStatementIndex];
+ mStatementIndex++;
+
+ InitializeListHead (&Statement->DefaultListHead);
+ InitializeListHead (&Statement->OptionListHead);
+
+ Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
+
+ Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+
+ StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+ CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
+ CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
+
+ Statement->InSubtitle = mInScopeSubtitle;
+
+ //
+ // Insert this Statement into current Form
+ //
+ InsertTailList (&Form->StatementListHead, &Statement->Link);
+
+ return Statement;
+}
+
+/**
+ Initialize Question's members.
+
+ @param OpCodeData Pointer of the raw OpCode data.
+ @param FormSet Pointer of the current FormSet.
+ @param Form Pointer of the current Form.
+
+ @return The Question.
+
+**/
+FORM_BROWSER_STATEMENT *
+CreateQuestion (
+ IN UINT8 *OpCodeData,
+ IN OUT FORM_BROWSER_FORMSET *FormSet,
+ IN OUT FORM_BROWSER_FORM *Form
+ )
+{
+ FORM_BROWSER_STATEMENT *Statement;
+ EFI_IFR_QUESTION_HEADER *QuestionHdr;
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+
+ Statement = CreateStatement (OpCodeData, FormSet, Form);
+ if (Statement == NULL) {
+ return NULL;
+ }
+
+ QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
+ CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
+ CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
+
+ if (FormSet->MaxQuestionId < QuestionHdr->QuestionId) {
+ FormSet->MaxQuestionId = QuestionHdr->QuestionId;
+ }
+
+ Statement->QuestionFlags = QuestionHdr->Flags;
+
+ if (Statement->VarStoreId == 0) {
+ //
+ // VarStoreId of zero indicates no variable storage
+ //
+ return Statement;
+ }
+
+ //
+ // Find Storage for this Question
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+
+ if (Storage->VarStoreId == Statement->VarStoreId) {
+ Statement->Storage = Storage;
+ break;
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+ ASSERT (Statement->Storage != NULL);
+
+ return Statement;
+}
+
+/**
+ Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
+
+ @param FormSet Pointer of the current FormSet
+
+ @return Pointer to a FORMSET_STORAGE data structure.
+
+**/
+FORMSET_STORAGE *
+CreateStorage (
+ IN FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ FORMSET_STORAGE *Storage;
+
+ Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
+ Storage->Signature = FORMSET_STORAGE_SIGNATURE;
+ InsertTailList (&FormSet->StorageListHead, &Storage->Link);
+
+ return Storage;
+}
+
+/**
+ Free resources of a storage
+
+ @param Storage Pointer of the storage
+
+ @return None.
+
+**/
+VOID
+DestroyStorage (
+ IN FORMSET_STORAGE *Storage
+ )
+{
+ if (Storage == NULL) {
+ return;
+ }
+
+ if (Storage->Name!= NULL) {
+ FreePool (Storage->Name);
+ }
+
+ FreePool (Storage);
+}
+
+
+/**
+ Free resources of a Statement
+
+ @param Statement Pointer of the Statement
+
+ @return None.
+
+**/
+VOID
+DestroyStatement (
+ IN OUT FORM_BROWSER_STATEMENT *Statement
+ )
+{
+ LIST_ENTRY *Link;
+ QUESTION_DEFAULT *Default;
+ QUESTION_OPTION *Option;
+
+ //
+ // Free Default value List
+ //
+ while (!IsListEmpty (&Statement->DefaultListHead)) {
+ Link = GetFirstNode (&Statement->DefaultListHead);
+ Default = QUESTION_DEFAULT_FROM_LINK (Link);
+ RemoveEntryList (&Default->Link);
+
+ gBS->FreePool (Default);
+ }
+
+ //
+ // Free Options List
+ //
+ while (!IsListEmpty (&Statement->OptionListHead)) {
+ Link = GetFirstNode (&Statement->OptionListHead);
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+ RemoveEntryList (&Option->Link);
+
+ gBS->FreePool (Option);
+ }
+
+}
+
+
+
+/**
+ Free resources of a Form
+
+ @param Form Pointer of the Form
+
+ @return None.
+
+**/
+VOID
+DestroyForm (
+ IN OUT FORM_BROWSER_FORM *Form
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ //
+ // Free Statements/Questions
+ //
+ while (!IsListEmpty (&Form->StatementListHead)) {
+ Link = GetFirstNode (&Form->StatementListHead);
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ RemoveEntryList (&Statement->Link);
+
+ DestroyStatement (Statement);
+ }
+
+ //
+ // Free this Form
+ //
+ gBS->FreePool (Form);
+}
+
+
+/**
+ Free resources allocated for a FormSet
+
+ @param FormSet Pointer of the FormSet
+
+ @return None.
+
+**/
+VOID
+DestroyFormSet (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+ FORMSET_DEFAULTSTORE *DefaultStore;
+ FORM_BROWSER_FORM *Form;
+
+ //
+ // Free IFR binary buffer
+ //
+ FreePool (FormSet->IfrBinaryData);
+
+ //
+ // Free FormSet Storage
+ //
+ if (FormSet->StorageListHead.ForwardLink != NULL) {
+ while (!IsListEmpty (&FormSet->StorageListHead)) {
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ RemoveEntryList (&Storage->Link);
+
+ DestroyStorage (Storage);
+ }
+ }
+
+ //
+ // Free FormSet Default Store
+ //
+ if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
+ while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
+ Link = GetFirstNode (&FormSet->DefaultStoreListHead);
+ DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
+ RemoveEntryList (&DefaultStore->Link);
+
+ gBS->FreePool (DefaultStore);
+ }
+ }
+
+ //
+ // Free Forms
+ //
+ if (FormSet->FormListHead.ForwardLink != NULL) {
+ while (!IsListEmpty (&FormSet->FormListHead)) {
+ Link = GetFirstNode (&FormSet->FormListHead);
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+ RemoveEntryList (&Form->Link);
+
+ DestroyForm (Form);
+ }
+ }
+
+ if (FormSet->StatementBuffer != NULL) {
+ FreePool (FormSet->StatementBuffer);
+ }
+
+ DestoryOneOfOptionMap (&FormSet->OneOfOptionMapListHead);
+
+ if (FormSet->OriginalDefaultVarStoreName != NULL) {
+ FreePool (FormSet->OriginalDefaultVarStoreName);
+ }
+
+ FreePool (FormSet);
+}
+
+
+/**
+ Tell whether this Operand is an Expression OpCode or not
+
+ @param Operand Operand of an IFR OpCode.
+
+ @retval TRUE This is an Expression OpCode.
+ @retval FALSE Not an Expression OpCode.
+
+**/
+BOOLEAN
+IsExpressionOpCode (
+ IN UINT8 Operand
+ )
+{
+ if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
+ ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
+ (Operand == EFI_IFR_CATENATE_OP)
+ ) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/**
+ Calculate number of Statemens(Questions) and Expression OpCodes.
+
+ @param FormSet The FormSet to be counted.
+ @param NumberOfStatement Number of Statemens(Questions)
+ @param NumberOfExpression Number of Expression OpCodes
+
+ @return None.
+
+**/
+VOID
+CountOpCodes (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN OUT UINT16 *NumberOfStatement,
+ IN OUT UINT16 *NumberOfExpression
+ )
+{
+ UINT16 StatementCount;
+ UINT16 ExpressionCount;
+ UINT8 *OpCodeData;
+ UINTN Offset;
+ UINTN OpCodeLen;
+
+ Offset = 0;
+ StatementCount = 0;
+ ExpressionCount = 0;
+
+ while (Offset < FormSet->IfrBinaryLength) {
+ OpCodeData = FormSet->IfrBinaryData + Offset;
+ OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ Offset += OpCodeLen;
+
+ if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
+ ExpressionCount++;
+ } else {
+ StatementCount++;
+ }
+ }
+
+ *NumberOfStatement = StatementCount;
+ *NumberOfExpression = ExpressionCount;
+}
+
+
+/**
+ Parse opcodes in the formset IFR binary.
+
+ @param FormSet Pointer of the FormSet data structure.
+
+ @retval EFI_SUCCESS Opcode parse success.
+ @retval Other Opcode parse fail.
+
+**/
+EFI_STATUS
+ParseOpCodes (
+ IN FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ FORM_BROWSER_FORM *CurrentForm;
+ FORM_BROWSER_STATEMENT *CurrentStatement;
+ UINT8 Operand;
+ UINT8 Scope;
+ UINTN OpCodeOffset;
+ UINTN OpCodeLength;
+ UINT8 *OpCodeData;
+ UINT8 ScopeOpCode;
+ FORMSET_STORAGE *Storage;
+ FORMSET_DEFAULTSTORE *DefaultStore;
+ QUESTION_DEFAULT *CurrentDefault;
+ QUESTION_OPTION *CurrentOption;
+ CHAR8 *AsciiString;
+ UINT16 NumberOfStatement;
+ UINT16 NumberOfExpression;
+ EFI_IMAGE_ID *ImageId;
+ EFI_HII_VALUE *Value;
+ LIST_ENTRY *OneOfOptinMapEntryListHead;
+ EFI_IFR_GUID_OPTIONKEY *OptionMap;
+ ONE_OF_OPTION_MAP *OneOfOptionMap;
+ ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;
+ UINT8 OneOfType;
+ EFI_IFR_ONE_OF *OneOfOpcode;
+
+ mInScopeSubtitle = FALSE;
+ mInScopeSuppress = FALSE;
+ mInScopeGrayOut = FALSE;
+ CurrentDefault = NULL;
+ CurrentOption = NULL;
+
+ //
+ // Set to a invalid value.
+ //
+ OneOfType = (UINT8) -1;
+
+ //
+ // Get the number of Statements and Expressions
+ //
+ CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
+ FormSet->NumberOfStatement = NumberOfStatement;
+
+ mStatementIndex = 0;
+ FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
+ if (FormSet->StatementBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeListHead (&FormSet->StorageListHead);
+ InitializeListHead (&FormSet->DefaultStoreListHead);
+ InitializeListHead (&FormSet->FormListHead);
+ InitializeListHead (&FormSet->OneOfOptionMapListHead);
+
+ CurrentForm = NULL;
+ CurrentStatement = NULL;
+
+ ResetScopeStack ();
+
+ OpCodeOffset = 0;
+ while (OpCodeOffset < FormSet->IfrBinaryLength) {
+ OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
+
+ OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ OpCodeOffset += OpCodeLength;
+ Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+ Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
+
+ //
+ // If scope bit set, push onto scope stack
+ //
+ if (Scope) {
+ PushScope (Operand);
+ }
+
+ if (IsExpressionOpCode (Operand)) {
+ continue;
+ }
+
+ //
+ // Parse the Opcode
+ //
+ switch (Operand) {
+
+ case EFI_IFR_FORM_SET_OP:
+ //
+ // check the formset GUID
+ //
+ if (!CompareGuid ((EFI_GUID *)(VOID *)&FormSet->Guid, (EFI_GUID *)(VOID *)&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
+ CopyMem (&FormSet->Help, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID));
+ break;
+
+ case EFI_IFR_FORM_OP:
+ //
+ // Create a new Form for this FormSet
+ //
+ CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
+ CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
+
+ InitializeListHead (&CurrentForm->StatementListHead);
+
+ CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
+ CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
+
+ //
+ // Insert into Form list of this FormSet
+ //
+ InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
+ break;
+
+ //
+ // Storage
+ //
+ case EFI_IFR_VARSTORE_OP:
+ //
+ // Create a buffer Storage for this FormSet
+ //
+ Storage = CreateStorage (FormSet);
+ Storage->Type = EFI_HII_VARSTORE_BUFFER;
+
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
+
+ AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
+ Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
+ ASSERT (Storage->Name != NULL);
+ for (Index = 0; AsciiString[Index] != 0; Index++) {
+ Storage->Name[Index] = (CHAR16) AsciiString[Index];
+ }
+
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ ASSERT (FALSE);
+
+ break;
+
+ case EFI_IFR_VARSTORE_EFI_OP:
+ //
+ // Create a EFI variable Storage for this FormSet
+ //
+ Storage = CreateStorage (FormSet);
+ Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
+
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
+ CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
+ break;
+
+ //
+ // DefaultStore
+ //
+ case EFI_IFR_DEFAULTSTORE_OP:
+ DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
+ DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
+
+ CopyMem (&DefaultStore->DefaultId, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId, sizeof (UINT16));
+ CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
+
+ //
+ // Insert to DefaultStore list of this Formset
+ //
+ InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
+ break;
+
+ //
+ // Statements
+ //
+ case EFI_IFR_SUBTITLE_OP:
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+ CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
+
+ if (Scope) {
+ mInScopeSubtitle = TRUE;
+ }
+ break;
+
+ case EFI_IFR_TEXT_OP:
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
+
+ CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
+ break;
+
+ //
+ // Questions
+ //
+ case EFI_IFR_ACTION_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
+ //
+ // No QuestionConfig present, so no configuration string will be processed
+ //
+ CurrentStatement->QuestionConfig = 0;
+ } else {
+ CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
+ }
+ break;
+
+ case EFI_IFR_RESET_BUTTON_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
+ break;
+
+ case EFI_IFR_REF_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
+ if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
+ CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
+
+ if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
+ CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
+
+ if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
+ CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
+ }
+ }
+ }
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_NUMERIC_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
+ Value = &CurrentStatement->HiiValue;
+
+ switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
+ CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
+ CurrentStatement->Step = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
+ CurrentStatement->StorageWidth = sizeof (UINT8);
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
+ CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
+ CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step, sizeof (UINT16));
+ CurrentStatement->StorageWidth = sizeof (UINT16);
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
+ CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
+ CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step, sizeof (UINT32));
+ CurrentStatement->StorageWidth = sizeof (UINT32);
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
+ CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
+ CopyMem (&CurrentStatement->Step, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step, sizeof (UINT64));
+ CurrentStatement->StorageWidth = sizeof (UINT64);
+ Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
+ break;
+
+ default:
+ break;
+ }
+
+ if (Operand == EFI_IFR_ONE_OF_OP) {
+ OneOfOpcode = (EFI_IFR_ONE_OF *) OpCodeData;
+ OneOfType = (UINT8) (OneOfOpcode->Flags & EFI_IFR_NUMERIC_SIZE);
+ }
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
+ CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
+ CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8));
+
+ //
+ // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
+ // has to use FormBrowser2.Callback() to retrieve the uncommited data for
+ // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
+ //
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
+ CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
+
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
+ CurrentStatement->StorageWidth = sizeof (BOOLEAN);
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
+
+ break;
+
+ case EFI_IFR_STRING_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ //
+ // MinSize is the minimum number of characters that can be accepted for this opcode,
+ // MaxSize is the maximum number of characters that can be accepted for this opcode.
+ // The characters are stored as Unicode, so the storage width should multiply 2.
+ //
+ CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
+ CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
+ CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (UINT16));
+ CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
+
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
+ CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
+
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ //
+ // MinSize is the minimum number of characters that can be accepted for this opcode,
+ // MaxSize is the maximum number of characters that can be accepted for this opcode.
+ // The characters are stored as Unicode, so the storage width should multiply 2.
+ //
+ CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
+ CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
+ CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (UINT16));
+
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
+ CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
+
+ break;
+
+ case EFI_IFR_DATE_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
+
+ break;
+
+ case EFI_IFR_TIME_OP:
+ CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
+
+ CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
+ CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
+
+ break;
+
+ //
+ // Default
+ //
+ case EFI_IFR_DEFAULT_OP:
+ //
+ // EFI_IFR_DEFAULT appear in scope of a Question,
+ // It creates a default value for the current question.
+ // A Question may have more than one Default value which have different default types.
+ //
+ CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
+ CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
+
+ CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
+ CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
+ CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ ExtendValueToU64 (&CurrentDefault->Value);
+
+ //
+ // Insert to Default Value list of current Question
+ //
+ InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
+
+ break;
+
+ //
+ // Option
+ //
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ //
+ // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
+ // It create a selection for use in current Question.
+ //
+ CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
+ CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
+
+ CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
+ CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
+ CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
+ CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ ExtendValueToU64 (&CurrentOption->Value);
+
+ //
+ // Insert to Option list of current Question
+ //
+ InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
+ break;
+
+ //
+ // Conditional
+ //
+ case EFI_IFR_NO_SUBMIT_IF_OP:
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ break;
+
+ case EFI_IFR_SUPPRESS_IF_OP:
+ break;
+
+ case EFI_IFR_GRAY_OUT_IF_OP:
+ break;
+
+ case EFI_IFR_DISABLE_IF_OP:
+ ASSERT (FALSE);
+
+
+ //
+ // Expression
+ //
+ case EFI_IFR_VALUE_OP:
+ break;
+
+ case EFI_IFR_RULE_OP:
+ break;
+
+ //
+ // Image
+ //
+ case EFI_IFR_IMAGE_OP:
+ //
+ // Get ScopeOpcode from top of stack
+ //
+ PopScope (&ScopeOpCode);
+ PushScope (ScopeOpCode);
+
+ switch (ScopeOpCode) {
+ case EFI_IFR_FORM_SET_OP:
+ ImageId = &FormSet->ImageId;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ ImageId = &CurrentForm->ImageId;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ ImageId = &CurrentOption->ImageId;
+ break;
+
+ default:
+ ImageId = &CurrentStatement->ImageId;
+ break;
+ }
+
+ CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
+ break;
+
+ //
+ // Refresh
+ //
+ case EFI_IFR_REFRESH_OP:
+ CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
+ break;
+
+ //
+ // Vendor specific
+ //
+ case EFI_IFR_GUID_OP:
+ OptionMap = (EFI_IFR_GUID_OPTIONKEY *) OpCodeData;
+
+ if (CompareGuid (&mTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ //
+ // Tiano specific GUIDed opcodes
+ //
+ switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
+ case EFI_IFR_EXTEND_OP_LABEL:
+ //
+ // just ignore label
+ //
+ break;
+
+
+ case EFI_IFR_EXTEND_OP_CLASS:
+ CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_EXTEND_OP_SUBCLASS:
+ CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
+ break;
+
+ default:
+ break;
+ }
+ }
+ else if (CompareGuid ((EFI_GUID *)(VOID *)&OptionMap->Guid, &mFrameworkHiiCompatibilityGuid)) {
+ if (OptionMap->ExtendOpCode == EFI_IFR_EXTEND_OP_OPTIONKEY) {
+ OneOfOptinMapEntryListHead = GetOneOfOptionMapEntryListHead (FormSet, OptionMap->QuestionId);
+ if (OneOfOptinMapEntryListHead == NULL) {
+ OneOfOptionMap = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP));
+ ASSERT (OneOfOptionMap != NULL);
+
+ OneOfOptionMap->Signature = ONE_OF_OPTION_MAP_SIGNATURE;
+ OneOfOptionMap->QuestionId = OptionMap->QuestionId;
+
+ //
+ // Make sure OneOfType is initialized.
+ //
+ ASSERT (OneOfType != (UINT8) -1);
+ OneOfOptionMap->ValueType = OneOfType;
+ InitializeListHead (&OneOfOptionMap->OneOfOptionMapEntryListHead);
+ OneOfOptinMapEntryListHead = &OneOfOptionMap->OneOfOptionMapEntryListHead;
+ InsertTailList (&FormSet->OneOfOptionMapListHead, &OneOfOptionMap->Link);
+ }
+ OneOfOptionMapEntry = AllocateZeroPool (sizeof (ONE_OF_OPTION_MAP_ENTRY));
+ ASSERT (OneOfOptionMapEntry != NULL);
+
+ OneOfOptionMapEntry->Signature = ONE_OF_OPTION_MAP_ENTRY_SIGNATURE;
+ OneOfOptionMapEntry->FwKey = OptionMap->KeyValue;
+ CopyMem (&OneOfOptionMapEntry->Value, &OptionMap->OptionValue, sizeof (EFI_IFR_TYPE_VALUE));
+
+ InsertTailList (OneOfOptinMapEntryListHead, &OneOfOptionMapEntry->Link);
+ }
+ }
+ break;
+
+ //
+ // Scope End
+ //
+ case EFI_IFR_END_OP:
+ Status = PopScope (&ScopeOpCode);
+ if (EFI_ERROR (Status)) {
+ ResetScopeStack ();
+ return Status;
+ }
+
+ switch (ScopeOpCode) {
+ case EFI_IFR_FORM_SET_OP:
+ //
+ // End of FormSet, update FormSet IFR binary length
+ // to stop parsing substantial OpCodes
+ //
+ FormSet->IfrBinaryLength = OpCodeOffset;
+ break;
+
+ case EFI_IFR_FORM_OP:
+ //
+ // End of Form
+ //
+ CurrentForm = NULL;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ //
+ // End of Option
+ //
+ CurrentOption = NULL;
+ break;
+
+ case EFI_IFR_SUBTITLE_OP:
+ mInScopeSubtitle = FALSE;
+ break;
+
+ case EFI_IFR_NO_SUBMIT_IF_OP:
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ //
+ // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
+ //
+ break;
+
+ case EFI_IFR_GRAY_OUT_IF_OP:
+ mInScopeGrayOut = FALSE;
+ break;
+
+ default:
+ if (IsExpressionOpCode (ScopeOpCode)) {
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.h new file mode 100644 index 0000000000..d5777225ea --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParser.h @@ -0,0 +1,344 @@ +/** @file
+ Function and Macro defintions for IFR parsing. To get the default value from IFR package, the IFR
+ opcode needs to be parsed. Most of code is taken from MdeModulePkg\Universal\SetupBrowserDxe\IfrParse.c.
+ This parser is simplified from the origianl IfrParser.c in the following way:
+
+ 1) All data structure definition that have nothing to do with IFR Default value scanning (
+ required to implement Framework HII's GetDefaultImage ()) is removed.
+ 2) Ignore the IFR opcode which is invalid for Form Package
+ generated using Framework VFR file.
+
+ Copyright (c) 2008, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HII_THUNK_UEFI_IFR_PARSER_
+#define _HII_THUNK_UEFI_IFR_PARSER_
+
+
+//
+// IFR relative definition
+//
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
+#define EFI_HII_EXPRESSION_DISABLE_IF 4
+#define EFI_HII_EXPRESSION_VALUE 5
+#define EFI_HII_EXPRESSION_RULE 6
+
+#define EFI_HII_VARSTORE_BUFFER 0
+#define EFI_HII_VARSTORE_NAME_VALUE 1
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2
+
+#define FORM_INCONSISTENT_VALIDATION 0
+#define FORM_NO_SUBMIT_VALIDATION 1
+
+extern EFI_GUID gTianoHiiIfrGuid;
+
+#define ONE_OF_OPTION_MAP_ENTRY_FROM_LINK(Record) CR(Record, ONE_OF_OPTION_MAP_ENTRY, Link, ONE_OF_OPTION_MAP_ENTRY_SIGNATURE)
+#define ONE_OF_OPTION_MAP_ENTRY_SIGNATURE SIGNATURE_32 ('O', 'O', 'M', 'E')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ UINT16 FwKey;
+ EFI_IFR_TYPE_VALUE Value;
+
+} ONE_OF_OPTION_MAP_ENTRY;
+
+
+
+#define ONE_OF_OPTION_MAP_FROM_LINK(Record) CR(Record, ONE_OF_OPTION_MAP, Link, ONE_OF_OPTION_MAP_SIGNATURE)
+#define ONE_OF_OPTION_MAP_SIGNATURE SIGNATURE_32 ('O', 'O', 'O', 'M')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ UINT16 VarStoreId;
+
+ UINT8 ValueType; //EFI_IFR_TYPE_NUM_*
+
+ EFI_QUESTION_ID QuestionId;
+
+ LIST_ENTRY OneOfOptionMapEntryListHead; //ONE_OF_OPTION_MAP_ENTRY
+} ONE_OF_OPTION_MAP;
+
+
+typedef struct {
+ UINT8 Type;
+ EFI_IFR_TYPE_VALUE Value;
+} EFI_HII_VALUE;
+
+#define NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T')
+
+#define FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'G')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Type; // Storage type
+
+ UINT16 VarStoreId;
+ EFI_GUID Guid;
+
+ CHAR16 *Name; // For EFI_IFR_VARSTORE
+ UINT16 Size;
+
+ UINT32 Attributes; // For EFI_IFR_VARSTORE_EFI: EFI Variable attribute
+
+} FORMSET_STORAGE;
+
+#define FORMSET_STORAGE_FROM_LINK(a) CR (a, FORMSET_STORAGE, Link, FORMSET_STORAGE_SIGNATURE)
+
+#if 0
+
+#define EXPRESSION_OPCODE_SIGNATURE SIGNATURE_32 ('E', 'X', 'O', 'P')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Operand;
+
+ UINT8 Format; // For EFI_IFR_TO_STRING, EFI_IFR_FIND
+ UINT8 Flags; // For EFI_IFR_SPAN
+ UINT8 RuleId; // For EFI_IFR_RULE_REF
+
+ EFI_HII_VALUE Value; // For EFI_IFR_EQ_ID_VAL, EFI_IFR_UINT64, EFI_IFR_UINT32, EFI_IFR_UINT16, EFI_IFR_UINT8, EFI_IFR_STRING_REF1
+
+ EFI_QUESTION_ID QuestionId; // For EFI_IFR_EQ_ID_ID, EFI_IFR_EQ_ID_LIST, EFI_IFR_QUESTION_REF1
+ EFI_QUESTION_ID QuestionId2;
+
+ UINT16 ListLength; // For EFI_IFR_EQ_ID_LIST
+ UINT16 *ValueList;
+
+ EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
+ EFI_GUID Guid;
+} EXPRESSION_OPCODE;
+
+#define EXPRESSION_OPCODE_FROM_LINK(a) CR (a, EXPRESSION_OPCODE, Link, EXPRESSION_OPCODE_SIGNATURE)
+
+#define FORM_EXPRESSION_SIGNATURE SIGNATURE_32 ('F', 'E', 'X', 'P')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Type; // Type for this expression
+
+ UINT8 RuleId; // For EFI_IFR_RULE only
+ EFI_STRING_ID Error; // For EFI_IFR_NO_SUBMIT_IF, EFI_IFR_INCONSISTENT_IF only
+
+ EFI_HII_VALUE Result; // Expression evaluation result
+
+ LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)
+} FORM_EXPRESSION;
+
+#define FORM_EXPRESSION_FROM_LINK(a) CR (a, FORM_EXPRESSION, Link, FORM_EXPRESSION_SIGNATURE)
+#endif
+
+#define QUESTION_DEFAULT_SIGNATURE SIGNATURE_32 ('Q', 'D', 'F', 'T')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 DefaultId;
+ EFI_HII_VALUE Value; // Default value
+
+} QUESTION_DEFAULT;
+
+#define QUESTION_DEFAULT_FROM_LINK(a) CR (a, QUESTION_DEFAULT, Link, QUESTION_DEFAULT_SIGNATURE)
+
+#define QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_STRING_ID Text;
+ UINT8 Flags;
+ EFI_HII_VALUE Value;
+ EFI_IMAGE_ID ImageId;
+
+#if 0
+ FORM_EXPRESSION *SuppressExpression; // Non-NULL indicates nested inside of SuppressIf
+#endif
+} QUESTION_OPTION;
+
+#define QUESTION_OPTION_FROM_LINK(a) CR (a, QUESTION_OPTION, Link, QUESTION_OPTION_SIGNATURE)
+
+#define FORM_BROWSER_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A')
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT8 Operand; // The operand (first byte) of this Statement or Question
+
+ //
+ // Statement Header
+ //
+ EFI_STRING_ID Prompt;
+ EFI_STRING_ID Help;
+ EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT
+
+ //
+ // Question Header
+ //
+ EFI_QUESTION_ID QuestionId; // The value of zero is reserved
+ EFI_VARSTORE_ID VarStoreId; // A value of zero indicates no variable storage
+ FORMSET_STORAGE *Storage;
+ union {
+ EFI_STRING_ID VarName;
+ UINT16 VarOffset;
+ } VarStoreInfo;
+#if 0
+ CHAR16 *UnicodeVarName;
+#endif
+
+ UINT16 StorageWidth;
+ UINT8 QuestionFlags;
+
+#if 0
+ CHAR16 *VariableName; // Name/Value or EFI Variable name
+ CHAR16 *BlockName; // Buffer storage block name: "OFFSET=...WIDTH=..."
+#endif
+
+ EFI_HII_VALUE HiiValue; // Edit copy for checkbox, numberic, oneof
+ UINT8 *BufferValue; // Edit copy for string, password, orderedlist
+
+ //
+ // OpCode specific members
+ //
+ UINT8 Flags; // for EFI_IFR_CHECKBOX, EFI_IFR_DATE, EFI_IFR_NUMERIC, EFI_IFR_ONE_OF,
+ // EFI_IFR_ORDERED_LIST, EFI_IFR_STRING,EFI_IFR_SUBTITLE,EFI_IFR_TIME, EFI_IFR_BANNER
+ UINT8 MaxContainers; // for EFI_IFR_ORDERED_LIST
+
+ UINT16 BannerLineNumber; // for EFI_IFR_BANNER, 1-based line number
+ EFI_STRING_ID QuestionConfig; // for EFI_IFR_ACTION, if 0 then no configuration string will be processed
+
+ UINT64 Minimum; // for EFI_IFR_ONE_OF/EFI_IFR_NUMERIC, it's Min/Max value
+ UINT64 Maximum; // for EFI_IFR_STRING/EFI_IFR_PASSWORD, it's Min/Max length
+ UINT64 Step;
+
+ EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON
+ EFI_FORM_ID RefFormId; // for EFI_IFR_REF
+ EFI_QUESTION_ID RefQuestionId; // for EFI_IFR_REF2
+ EFI_GUID RefFormSetId; // for EFI_IFR_REF3
+ EFI_STRING_ID RefDevicePath; // for EFI_IFR_REF4
+
+ //
+ // Get from IFR parsing
+ //
+#if 0
+ FORM_EXPRESSION *ValueExpression; // nested EFI_IFR_VALUE, provide Question value and indicate Question is ReadOnly
+#endif
+ LIST_ENTRY DefaultListHead; // nested EFI_IFR_DEFAULT list (QUESTION_DEFAULT), provide default values
+ LIST_ENTRY OptionListHead; // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
+
+ EFI_IMAGE_ID ImageId; // nested EFI_IFR_IMAGE
+ UINT8 RefreshInterval; // nested EFI_IFR_REFRESH, refresh interval(in seconds) for Question value, 0 means no refresh
+ BOOLEAN InSubtitle; // nesting inside of EFI_IFR_SUBTITLE
+
+#if 0
+ LIST_ENTRY InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
+ LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (FORM_EXPRESSION)
+ FORM_EXPRESSION *GrayOutExpression; // nesting inside of GrayOutIf
+ FORM_EXPRESSION *SuppressExpression; // nesting inside of SuppressIf
+#endif
+
+} FORM_BROWSER_STATEMENT;
+
+#define FORM_BROWSER_STATEMENT_FROM_LINK(a) CR (a, FORM_BROWSER_STATEMENT, Link, FORM_BROWSER_STATEMENT_SIGNATURE)
+
+#define FORM_BROWSER_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 FormId;
+ EFI_STRING_ID FormTitle;
+
+ EFI_IMAGE_ID ImageId;
+
+#if 0
+ LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
+#endif
+ LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)
+} FORM_BROWSER_FORM;
+
+#define FORM_BROWSER_FORM_FROM_LINK(a) CR (a, FORM_BROWSER_FORM, Link, FORM_BROWSER_FORM_SIGNATURE)
+
+#define FORMSET_DEFAULTSTORE_SIGNATURE SIGNATURE_32 ('F', 'D', 'F', 'S')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 DefaultId;
+ EFI_STRING_ID DefaultName;
+} FORMSET_DEFAULTSTORE;
+
+#define FORMSET_DEFAULTSTORE_FROM_LINK(a) CR (a, FORMSET_DEFAULTSTORE, Link, FORMSET_DEFAULTSTORE_SIGNATURE)
+
+typedef struct {
+ EFI_HII_HANDLE HiiHandle;
+
+ UINTN IfrBinaryLength;
+ UINT8 *IfrBinaryData;
+
+ EFI_GUID Guid;
+ EFI_STRING_ID FormSetTitle;
+ EFI_STRING_ID Help;
+ UINT16 Class;
+ UINT16 SubClass;
+ EFI_IMAGE_ID ImageId;
+
+ FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions
+#if 0
+ EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode
+#endif
+
+ LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE)
+ LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
+ LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)
+
+ LIST_ENTRY OneOfOptionMapListHead; //ONE_OF_OPTION_MAP
+
+ UINT16 MaxQuestionId;
+
+ //
+ // Added for Framework HII Thunk.
+ // Default Variable Storage built from a Framework VFR file using UEFI VFR Compiler in Compatibility mode is determined
+ // by priority rules defined in GetFormsetDefaultVarstoreId (). See the function description for details.
+ //
+ EFI_VARSTORE_ID DefaultVarStoreId;
+ CHAR16 *OriginalDefaultVarStoreName;
+
+ UINTN NumberOfStatement;
+
+} FORM_BROWSER_FORMSET;
+
+
+EFI_STATUS
+ParseOpCodes (
+ IN FORM_BROWSER_FORMSET *FormSet
+ );
+
+VOID
+DestroyFormSet (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ );
+
+#endif
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParserExpression.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParserExpression.c new file mode 100644 index 0000000000..9d2cab5595 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParserExpression.c @@ -0,0 +1,374 @@ +/** @file
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Expression.c
+
+Abstract:
+
+ Expression evaluation.
+
+
+**/
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include "UefiIfrParser.h"
+
+//
+// Global stack used to evaluate boolean expresions
+//
+EFI_HII_VALUE *mOpCodeScopeStack = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
+EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
+
+EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
+EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
+
+#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
+
+
+/**
+ Grow size of the stack
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackPtr On input: old stack end; On output: new stack end
+
+ @retval EFI_SUCCESS Grow stack success.
+ @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.
+
+**/
+STATIC
+EFI_STATUS
+GrowStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd
+ )
+{
+ UINTN Size;
+ EFI_HII_VALUE *NewStack;
+
+ Size = EXPRESSION_STACK_SIZE_INCREMENT;
+ if (*StackPtr != NULL) {
+ Size = Size + (*StackEnd - *Stack);
+ }
+
+ NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
+ if (NewStack == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (*StackPtr != NULL) {
+ //
+ // Copy from Old Stack to the New Stack
+ //
+ CopyMem (
+ NewStack,
+ *Stack,
+ (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
+ );
+
+ //
+ // Free The Old Stack
+ //
+ gBS->FreePool (*Stack);
+ }
+
+ //
+ // Make the Stack pointer point to the old data in the new stack
+ //
+ *StackPtr = NewStack + (*StackPtr - *Stack);
+ *Stack = NewStack;
+ *StackEnd = NewStack + Size;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Push an element onto the Boolean Stack
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackPtr On input: old stack end; On output: new stack end
+ @param Data Data to push.
+
+ @retval EFI_SUCCESS Push stack success.
+
+**/
+EFI_STATUS
+PushStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd,
+ IN EFI_HII_VALUE *Data
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Check for a stack overflow condition
+ //
+ if (*StackPtr >= *StackEnd) {
+ //
+ // Grow the stack
+ //
+ Status = GrowStack (Stack, StackPtr, StackEnd);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Push the item onto the stack
+ //
+ CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
+ *StackPtr = *StackPtr + 1;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Pop an element from the stack.
+
+ @param Stack On input: old stack; On output: new stack
+ @param StackPtr On input: old stack pointer; On output: new stack
+ pointer
+ @param StackPtr On input: old stack end; On output: new stack end
+ @param Data Data to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopStack (
+ IN OUT EFI_HII_VALUE **Stack,
+ IN OUT EFI_HII_VALUE **StackPtr,
+ IN OUT EFI_HII_VALUE **StackEnd,
+ OUT EFI_HII_VALUE *Data
+ )
+{
+ //
+ // Check for a stack underflow condition
+ //
+ if (*StackPtr == *Stack) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Pop the item off the stack
+ //
+ *StackPtr = *StackPtr - 1;
+ CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset stack pointer to begin of the stack.
+
+ None.
+
+ @return None.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ )
+{
+ mOpCodeScopeStackPointer = mOpCodeScopeStack;
+}
+
+
+/**
+ Push an Operand onto the Stack
+
+ @param Operand Operand to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PushScope (
+ IN UINT8 Operand
+ )
+{
+ EFI_HII_VALUE Data;
+
+ Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
+ Data.Value.u8 = Operand;
+
+ return PushStack (
+ &mOpCodeScopeStack,
+ &mOpCodeScopeStackPointer,
+ &mOpCodeScopeStackEnd,
+ &Data
+ );
+}
+
+
+/**
+ Pop an Operand from the Stack
+
+ @param Operand Operand to pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PopScope (
+ OUT UINT8 *Operand
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_VALUE Data;
+
+ Status = PopStack (
+ &mOpCodeScopeStack,
+ &mOpCodeScopeStackPointer,
+ &mOpCodeScopeStackEnd,
+ &Data
+ );
+
+ *Operand = Data.Value.u8;
+
+ return Status;
+}
+
+
+/**
+ Reset stack pointer to begin of the stack.
+
+ None.
+
+ @return None.
+
+**/
+VOID
+ResetExpressionStack (
+ VOID
+ )
+{
+ mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
+}
+
+
+/**
+ Push an Expression value onto the Stack
+
+ @param Value Expression value to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PushExpression (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ return PushStack (
+ &mExpressionEvaluationStack,
+ &mExpressionEvaluationStackPointer,
+ &mExpressionEvaluationStackEnd,
+ Value
+ );
+}
+
+
+/**
+ Pop an Expression value from the stack.
+
+ @param Value Expression value to pop.
+
+ @retval EFI_SUCCESS The value was popped onto the stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+
+**/
+EFI_STATUS
+PopExpression (
+ OUT EFI_HII_VALUE *Value
+ )
+{
+ return PopStack (
+ &mExpressionEvaluationStack,
+ &mExpressionEvaluationStackPointer,
+ &mExpressionEvaluationStackEnd,
+ Value
+ );
+}
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param Value HII Value to be converted.
+
+ @return None.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN EFI_HII_VALUE *Value
+ )
+{
+ UINT64 Temp;
+
+ Temp = 0;
+ switch (Value->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Temp = Value->Value.u8;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Temp = Value->Value.u16;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Temp = Value->Value.u32;
+ break;
+
+ case EFI_IFR_TYPE_BOOLEAN:
+ Temp = Value->Value.b;
+ break;
+
+ case EFI_IFR_TYPE_TIME:
+ Temp = Value->Value.u32 & 0xffffff;
+ break;
+
+ case EFI_IFR_TYPE_DATE:
+ Temp = Value->Value.u32;
+ break;
+
+ default:
+ return;
+ }
+
+ Value->Value.u64 = Temp;
+}
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParserExpression.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParserExpression.h new file mode 100644 index 0000000000..c55277ff13 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/UefiIfrParserExpression.h @@ -0,0 +1,96 @@ +/** @file
+ Internal Function and Macro defintions for IFR Expression evaluation used in Ifr Parsing. This header file should only
+ be included by UefiIfrParserExpression.c and UefiIfrParser.c
+
+ Copyright (c) 2008, Intel Corporation
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HII_THUNK_UEFI_IFR_PARSER_EXPRESSION_
+#define _HII_THUNK_UEFI_IFR_PARSER_EXPRESSION_
+
+/**
+ Reset stack pointer to begin of the stack.
+
+ None.
+
+ @return None.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ );
+
+/**
+ Push an Operand onto the Stack
+
+ @param Operand Operand to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PushScope (
+ IN UINT8 Operand
+ );
+
+
+/**
+ Pop an Operand from the Stack
+
+ @param Operand Operand to pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PopScope (
+ OUT UINT8 *Operand
+ );
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param Value HII Value to be converted.
+
+ @return None.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN EFI_HII_VALUE *Value
+ );
+
+/**
+ Compare two Hii value.
+
+ @param Value1 Expression value to compare on left-hand
+ @param Value2 Expression value to compare on right-hand
+ @param HiiHandle Only required for string compare
+
+ @retval EFI_INVALID_PARAMETER Could not perform comparation on two values
+ @retval 0 Two operators equeal
+ @retval 0 Value1 is greater than Value2
+ @retval 0 Value1 is less than Value2
+
+**/
+INTN
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ );
+
+#endif
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c new file mode 100644 index 0000000000..0ad0668f72 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.c @@ -0,0 +1,687 @@ +/**@file
+
+ This file contains the keyboard processing code to the HII database.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "HiiDatabase.h"
+#include "HiiHandle.h"
+#include <Library/DebugLib.h>
+
+CONST EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
+CONST CHAR16 FrameworkReservedVarstoreName[] = FRAMEWORK_RESERVED_VARSTORE_NAME;
+
+
+/**
+ Find the corressponding UEFI HII Handle from a Framework HII Handle given.
+
+ @param Private The HII Thunk Module Private context.
+ @param FwHiiHandle The Framemwork HII Handle.
+
+ @return NULL If Framework HII Handle is invalid.
+ @return The corresponding UEFI HII Handle.
+**/
+EFI_HII_HANDLE
+FwHiiHandleToUefiHiiHandle (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
+ )
+{
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ ASSERT (FwHiiHandle != (FRAMEWORK_EFI_HII_HANDLE) 0);
+ ASSERT (Private != NULL);
+
+ ThunkContext = FwHiiHandleToThunkContext (Private, FwHiiHandle);
+
+ if (ThunkContext != NULL) {
+ return ThunkContext->UefiHiiHandle;
+ }
+
+ return (EFI_HII_HANDLE) NULL;
+}
+
+
+/**
+ Find the corressponding HII Thunk Context from a Framework HII Handle given.
+
+ @param Private The HII Thunk Module Private context.
+ @param FwHiiHandle The Framemwork HII Handle.
+
+ @return NULL If Framework HII Handle is invalid.
+ @return The corresponding HII Thunk Context.
+**/
+HII_THUNK_CONTEXT *
+FwHiiHandleToThunkContext (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
+ )
+{
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (FwHiiHandle == ThunkContext->FwHiiHandle) {
+ return ThunkContext;
+ }
+
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Find the corressponding HII Thunk Context from a UEFI HII Handle given.
+
+ @param Private The HII Thunk Module Private context.
+ @param UEFIHiiHandle The UEFI HII Handle.
+
+ @return NULL If UEFI HII Handle is invalid.
+ @return The corresponding HII Thunk Context.
+**/
+HII_THUNK_CONTEXT *
+UefiHiiHandleToThunkContext (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE UefiHiiHandle
+ )
+{
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (UefiHiiHandle == ThunkContext->UefiHiiHandle) {
+ return ThunkContext;
+ }
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Find the corressponding HII Thunk Context from a Tag GUID.
+
+ @param Private The HII Thunk Module Private context.
+ @param Guid The Tag GUID.
+
+ @return NULL No HII Thunk Context matched the Tag GUID.
+ @return The corresponding HII Thunk Context.
+**/
+HII_THUNK_CONTEXT *
+TagGuidToIfrPackThunkContext (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN CONST EFI_GUID *Guid
+ )
+{
+ LIST_ENTRY *Link;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ Link = GetFirstNode (&Private->ThunkContextListHead);
+
+ while (!IsNull (&Private->ThunkContextListHead, Link)) {
+ ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
+
+ if (CompareGuid (Guid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount != 0)) {
+ return ThunkContext;
+ }
+
+ Link = GetNextNode (&Private->ThunkContextListHead, Link);
+ }
+
+ return NULL;
+
+}
+
+/**
+ Clean up the HII Thunk Context for a UEFI HII Handle.
+
+ @param Private The HII Thunk Module Private context.
+ @param UEFIHiiHandle The UEFI HII Handle.
+
+**/
+VOID
+DestroyThunkContextForUefiHiiHandle (
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE UefiHiiHandle
+ )
+{
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ ThunkContext = UefiHiiHandleToThunkContext (Private, UefiHiiHandle);
+ ASSERT (ThunkContext != NULL);
+
+ DestroyThunkContext (ThunkContext);
+}
+
+
+/**
+ This function create a HII_THUNK_CONTEXT for a package list registered
+ by a module calling EFI_HII_DATABASE_PROTOCOL.NewPackageList. It records
+ the PackageListGuid in EFI_HII_PACKAGE_LIST_HEADER in the TagGuid in
+ HII_THUNK_CONTEXT created. This TagGuid will be used as a key to s
+
+**/
+HII_THUNK_CONTEXT *
+CreateThunkContextForUefiHiiHandle (
+ IN EFI_HII_HANDLE UefiHiiHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID PackageGuid;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ ThunkContext = AllocateZeroPool (sizeof (*ThunkContext));
+ ASSERT (ThunkContext != NULL);
+
+ ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
+
+ Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ThunkContext->UefiHiiHandle = UefiHiiHandle;
+
+ Status = HiiLibExtractGuidFromHiiHandle (UefiHiiHandle, &PackageGuid);
+ ASSERT_EFI_ERROR (Status);
+
+ CopyGuid(&ThunkContext->TagGuid, &PackageGuid);
+
+ return ThunkContext;
+}
+
+
+/**
+ Get the number of HII Package for a Package type.
+
+ @param PackageListHeader The Package List.
+ @param PackageType The Package Type.
+
+ @return The number of Package for given type.
+**/
+UINTN
+GetPackageCountByType (
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,
+ IN UINT8 PackageType
+ )
+{
+ UINTN Count;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageListHeader + sizeof (EFI_HII_PACKAGE_LIST_HEADER));
+ Count = 0;
+
+ while (PackageHeader->Type != EFI_HII_PACKAGE_END) {
+ if (PackageHeader->Type == PackageType ) {
+ Count++;
+ }
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *) ((UINT8 *) PackageHeader + PackageHeader->Length);
+ }
+
+
+ return Count;
+}
+
+/**
+ Get the Form Package from a Framework Package List.
+
+ @param Packages Framework Package List.
+
+ @return The Form Package Header found.
+**/
+EFI_HII_PACKAGE_HEADER *
+GetIfrPackage (
+ IN CONST EFI_HII_PACKAGES *Packages
+ )
+{
+ UINTN Index;
+ TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;
+
+ ASSERT (Packages != NULL);
+
+ TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));
+
+ for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
+ //
+ // The current UEFI HII build tool generate a binary in the format defined by
+ // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in
+ // this binary is with same package type. So the returned IfrPackageCount and StringPackageCount
+ // may not be the exact number of valid package number in the binary generated
+ // by HII Build tool.
+ //
+ switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) {
+ case EFI_HII_IFR:
+ return &TianoAutogenPackageHdrArray[Index]->PackageHeader;
+ break;
+ case EFI_HII_STRING:
+ case EFI_HII_FONT:
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return NULL;
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Get FormSet GUID.
+
+ ASSERT if no FormSet Opcode is found.
+
+ @param Packages Form Framework Package.
+ @param FormSetGuid Return the FormSet Guid.
+
+**/
+VOID
+GetFormSetGuid (
+ IN EFI_HII_PACKAGE_HEADER *Package,
+ OUT EFI_GUID *FormSetGuid
+ )
+{
+ UINTN Offset;
+ EFI_IFR_OP_HEADER *OpCode;
+ EFI_IFR_FORM_SET *FormSet;
+
+ Offset = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset < Package->Length) {
+ OpCode = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + Offset);
+
+ switch (OpCode->OpCode) {
+ case EFI_IFR_FORM_SET_OP:
+ FormSet = (EFI_IFR_FORM_SET *) OpCode;
+ CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
+ return;
+
+ default:
+ break;
+
+ }
+ Offset += OpCode->Length;
+ }
+
+ //
+ // A proper IFR must have a formset opcode.
+ //
+ ASSERT (FALSE);
+
+}
+
+/**
+ Creat a Thunk Context.
+
+ ASSERT if no FormSet Opcode is found.
+
+ @param Private The HII Thunk Private Context.
+ @param StringPackageCount The String package count.
+ @param FormSetGuid The IFR Package count.
+
+ @return A newly created Thunk Context.
+ @retval NULL No resource to create a new Thunk Context.
+**/
+HII_THUNK_CONTEXT *
+CreateThunkContext (
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN UINTN StringPackageCount,
+ IN UINTN IfrPackageCount
+ )
+{
+ EFI_STATUS Status;
+ HII_THUNK_CONTEXT *ThunkContext;
+
+ ThunkContext = AllocateZeroPool (sizeof (HII_THUNK_CONTEXT));
+ ASSERT (ThunkContext != NULL);
+
+ ThunkContext->Signature = HII_THUNK_CONTEXT_SIGNATURE;
+ ThunkContext->IfrPackageCount = IfrPackageCount;
+ ThunkContext->StringPackageCount = StringPackageCount;
+ Status = AllocateHiiHandle (&ThunkContext->FwHiiHandle);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return ThunkContext;
+
+}
+
+/**
+ Destroy the Thunk Context and free up all resource.
+
+ @param ThunkContext The HII Thunk Private Context to be freed.
+
+**/
+VOID
+DestroyThunkContext (
+ IN HII_THUNK_CONTEXT *ThunkContext
+ )
+{
+ ASSERT (ThunkContext != NULL);
+
+ FreeHiiHandle (ThunkContext->FwHiiHandle);
+
+ RemoveEntryList (&ThunkContext->Link);
+
+ if (ThunkContext->FormSet != NULL) {
+ DestroyFormSet (ThunkContext->FormSet);
+ }
+
+ FreePool (ThunkContext);
+}
+
+/**
+ Get the FormSet's Default Varstore ID based on the rule (Descending Priority):
+
+ 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
+ 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
+ as the default Var Store ID.
+
+ @param FormSet The Form Set. The Default Varstore ID is updated if found.
+
+**/
+VOID
+GetFormsetDefaultVarstoreId (
+ IN OUT FORM_BROWSER_FORMSET * FormSet
+ )
+{
+ LIST_ENTRY *StorageList;
+ FORMSET_STORAGE *Storage;
+ FORMSET_STORAGE *DefaultStorage;
+
+ //
+ // VarStoreId 0 is invalid in UEFI IFR.
+ //
+ DefaultStorage= NULL;
+ FormSet->DefaultVarStoreId = 0;
+ StorageList = GetFirstNode (&FormSet->StorageListHead);
+
+ while (!IsNull (&FormSet->StorageListHead, StorageList)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
+
+ DEBUG ((EFI_D_INFO, "FormSet %g: Found Varstore ID %x Name %s Size 0x%x\n", &FormSet->Guid, Storage->VarStoreId, Storage->Name, Storage->Size));
+
+ if (Storage->VarStoreId == FRAMEWORK_RESERVED_VARSTORE_ID) {
+ //
+ // 1) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID (0x01) is found, Var Store ID is used.
+ //
+ FormSet->DefaultVarStoreId = FRAMEWORK_RESERVED_VARSTORE_ID;
+ DefaultStorage = Storage;
+ break;
+ }
+
+ StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
+ }
+
+ if (FormSet->DefaultVarStoreId != FRAMEWORK_RESERVED_VARSTORE_ID) {
+ //
+ //
+ // 2) If VarStore ID of FRAMEWORK_RESERVED_VARSTORE_ID is not found, First Var Store ID is used
+ // as the default Var Store ID.
+ //
+ StorageList = GetFirstNode (&FormSet->StorageListHead);
+ if (!IsNull (&FormSet->StorageListHead, StorageList)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);
+ FormSet->DefaultVarStoreId = Storage->VarStoreId;
+ DefaultStorage = Storage;
+ }
+
+ }
+
+ DEBUG_CODE_BEGIN ();
+ if (FormSet->DefaultVarStoreId == 0) {
+ DEBUG ((EFI_D_INFO, "FormSet %g: No Varstore Found\n", &FormSet->Guid));
+ } else {
+ // The name of default VARSTORE with a Explicit declaration statement will be updated to L"Setup" to make sure
+ // the Framework HII Setup module will run correctly. Framework HII Setup module always assumed that default
+ // VARSTORE to have L"Setup" as name, Formset GUID as GUID.
+
+ DEBUG ((EFI_D_INFO, "FormSet %g: Default Varstore ID (0x%x) N(%s) G(%g)\n", &FormSet->Guid, FormSet->DefaultVarStoreId, DefaultStorage->Name, &DefaultStorage->Guid));
+
+ if (StrCmp (DefaultStorage->Name, FrameworkReservedVarstoreName) != 0) {
+ DEBUG ((EFI_D_INFO, " : Name is updated from %s to %s.\n", DefaultStorage->Name, FrameworkReservedVarstoreName));
+ FormSet->OriginalDefaultVarStoreName = DefaultStorage->Name;
+ DefaultStorage->Name = AllocateCopyPool (StrSize (FrameworkReservedVarstoreName), FrameworkReservedVarstoreName);
+ }
+ }
+ DEBUG_CODE_END ();
+
+ return;
+}
+
+/**
+ Fetch the Ifr binary data of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @param BinaryLength The length of the FormSet IFR binary.
+ @param BinaryData The buffer designed to receive the FormSet.
+
+ @retval EFI_SUCCESS Buffer filled with the requested FormSet.
+ BufferLength was updated.
+ @retval EFI_INVALID_PARAMETER The handle is unknown.
+ @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
+ be found with the requested FormId.
+
+**/
+EFI_STATUS
+GetIfrBinaryData (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT UINTN *BinaryLength,
+ OUT UINT8 **BinaryData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+ UINT8 *Package;
+ UINT8 *OpCodeData;
+ UINT32 Offset;
+ UINT32 Offset2;
+ BOOLEAN ReturnDefault;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+
+ OpCodeData = NULL;
+ Package = NULL;
+ ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;
+
+ //
+ // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
+ //
+ if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
+ ReturnDefault = TRUE;
+ } else {
+ ReturnDefault = FALSE;
+ }
+
+ //
+ // Get HII PackageList
+ //
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ Offset2 = 0;
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *) HiiPackageList) + Offset;
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
+ //
+ // Search FormSet in this Form Package
+ //
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset2 < PackageHeader.Length) {
+ OpCodeData = Package + Offset2;
+
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+ //
+ // Check whether return default FormSet
+ //
+ if (ReturnDefault) {
+ break;
+ }
+
+ //
+ // FormSet GUID is specified, check it
+ //
+ if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ break;
+ }
+ }
+
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ }
+
+ if (Offset2 < PackageHeader.Length) {
+ //
+ // Target formset found
+ //
+ break;
+ }
+ }
+
+ Offset += PackageHeader.Length;
+ }
+
+ if (Offset >= PackageListLength) {
+ //
+ // Form package not found in this Package List
+ //
+ gBS->FreePool (HiiPackageList);
+ return EFI_NOT_FOUND;
+ }
+
+ if (ReturnDefault && FormSetGuid != NULL) {
+ //
+ // Return the default FormSet GUID
+ //
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ }
+
+ //
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
+ // of the Form Package.
+ //
+ *BinaryLength = PackageHeader.Length - Offset2;
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
+
+ gBS->FreePool (HiiPackageList);
+
+ if (*BinaryData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the internal data structure of a FormSet.
+
+ @param Handle PackageList Handle
+ @param FormSetGuid GUID of a formset. If not specified (NULL or zero
+ GUID), take the first FormSet found in package
+ list.
+ @param FormSet FormSet data structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.
+
+**/
+EFI_STATUS
+InitializeFormSet (
+ IN EFI_HII_HANDLE Handle,
+ IN OUT EFI_GUID *FormSetGuid,
+ OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FormSet->HiiHandle = Handle;
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
+
+ //
+ // Parse the IFR binary OpCodes
+ //
+ Status = ParseOpCodes (FormSet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GetFormsetDefaultVarstoreId (FormSet);
+ return Status;
+}
+
+/**
+ Parse the Form Package and build a FORM_BROWSER_FORMSET structure.
+
+ @param UefiHiiHandle PackageList Handle
+
+ @return A pointer to FORM_BROWSER_FORMSET.
+
+**/
+FORM_BROWSER_FORMSET *
+ParseFormSet (
+ IN EFI_HII_HANDLE UefiHiiHandle
+ )
+{
+ FORM_BROWSER_FORMSET *FormSet;
+ EFI_GUID FormSetGuid;
+ EFI_STATUS Status;
+
+ FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
+ ASSERT (FormSet != NULL);
+
+ CopyGuid (&FormSetGuid, &gZeroGuid);
+ Status = InitializeFormSet (UefiHiiHandle, &FormSetGuid, FormSet);
+ ASSERT_EFI_ERROR (Status);
+
+ return FormSet;
+}
+
diff --git a/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.h b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.h new file mode 100644 index 0000000000..99642fd5b9 --- /dev/null +++ b/EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Utility.h @@ -0,0 +1,123 @@ +/**@file
+
+ This file contains utility functions by HII Thunk Modules.
+
+Copyright (c) 2006 - 2008, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HII_THUNK_UTILITY_H
+#define _HII_THUNK_UTILITY_H
+
+/**
+ Find the UefiHiiHandle based on a Framework HII Handle returned by
+ the HII Thunk to Framework HII code.
+
+ @param Private The pointer to the private data of Hii Thunk.
+ @param FwHiiHandle Framework HII Handle returned by the HII Thunk to Framework HII code.
+
+ @retval NULL If Framework HII Handle passed in does not have matching UEFI HII handle.
+ @retval !NULL If the match is found.
+
+**/
+EFI_HII_HANDLE
+FwHiiHandleToUefiHiiHandle (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
+ );
+
+HII_THUNK_CONTEXT *
+FwHiiHandleToThunkContext (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN FRAMEWORK_EFI_HII_HANDLE FwHiiHandle
+ );
+
+HII_THUNK_CONTEXT *
+UefiHiiHandleToThunkContext (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE UefiHiiHandle
+ );
+
+HII_THUNK_CONTEXT *
+TagGuidToIfrPackThunkContext (
+ IN CONST HII_THUNK_PRIVATE_DATA *Private,
+ IN CONST EFI_GUID *Guid
+ );
+
+HII_THUNK_CONTEXT *
+CreateThunkContextForUefiHiiHandle (
+ IN EFI_HII_HANDLE UefiHiiHandle
+ );
+
+VOID
+DestroyThunkContextForUefiHiiHandle (
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN EFI_HII_HANDLE UefiHiiHandle
+ );
+
+UINTN
+GetPackageCountByType (
+ IN CONST EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader,
+ IN UINT8 PackageType
+ );
+
+EFI_STATUS
+CreateQuestionIdMap (
+ IN OUT HII_THUNK_CONTEXT *ThunkContext
+ );
+
+VOID
+GetAttributesOfFirstFormSet (
+ IN OUT HII_THUNK_CONTEXT *ThunkContext
+ );
+
+LIST_ENTRY *
+GetMapEntryListHead (
+ IN CONST HII_THUNK_CONTEXT *ThunkContext,
+ IN UINT16 VarStoreId
+ );
+
+HII_THUNK_CONTEXT *
+CreateThunkContext (
+ IN HII_THUNK_PRIVATE_DATA *Private,
+ IN UINTN StringPackageCount,
+ IN UINTN IfrPackageCount
+ );
+
+VOID
+DestroyThunkContext (
+ IN HII_THUNK_CONTEXT *ThunkContext
+ );
+
+VOID
+DestoryOneOfOptionMap (
+ IN LIST_ENTRY *OneOfOptionMapListHead
+ );
+
+VOID
+GetFormSetGuid (
+ IN EFI_HII_PACKAGE_HEADER *Package,
+ OUT EFI_GUID *FormSetGuid
+ )
+;
+
+EFI_HII_PACKAGE_HEADER *
+GetIfrPackage (
+ IN CONST EFI_HII_PACKAGES *Packages
+ )
+;
+
+FORM_BROWSER_FORMSET *
+ParseFormSet (
+ IN EFI_HII_HANDLE UefiHiiHandle
+ )
+;
+
+#endif
|