/**@file\r
- This file contains functions related to Config Access Protocols installed by\r
- by HII Thunk Modules which is used to thunk UEFI Config Access Callback to \r
- Framework HII Callback.\r
+ This file implements functions related to Config Access Protocols installed by\r
+ by HII Thunk Modules. These Config access Protocols are used to thunk UEFI Config \r
+ Access Callback to Framework HII Callback and EFI Variable Set/Get operations.\r
\r
Copyright (c) 2008, Intel Corporation\r
All rights reserved. This program and the accompanying materials\r
**/\r
\r
#include "HiiDatabase.h"\r
+#include "UefiIfrParser.h"\r
\r
-HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE ConfigAccessProtocolInstanceTempate = {\r
- HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_SIGNATURE,\r
+BOOLEAN mHiiPackageListUpdated = FALSE;\r
+\r
+CONFIG_ACCESS_PRIVATE gConfigAccessPrivateTempate = {\r
+ CONFIG_ACCESS_PRIVATE_SIGNATURE,\r
{\r
ThunkExtractConfig,\r
ThunkRouteConfig,\r
ThunkCallback\r
}, //ConfigAccessProtocol\r
- NULL, //FrameworkFormCallbackProtocol\r
- {NULL, NULL} //ConfigAccessStorageListHead\r
+ NULL, //FormCallbackProtocol\r
+ NULL \r
};\r
\r
/**\r
- Find and return the pointer to Package Header of the Form package\r
- in the Framework Package List. The Framework Package List is created\r
- by a module calling the Framework HII interface.\r
- The Framwork Package List contains package data \r
- generated by Intel's UEFI VFR Compiler and String gather tool. The data format\r
- of the package data is defined by TIANO_AUTOGEN_PACKAGES_HEADER.\r
-\r
- If the package list contains other type of packages such as KEYBOARD_LAYOUT,\r
- FONTS and IMAGES, the ASSERT. This is to make sure the caller is a \r
- Framework Module which does not include packages introduced by UEFI Specification\r
- or packages that is not supported by Thunk layer.\r
+ Get the first EFI_IFR_VARSTORE from the FormSet. \r
+ \r
+ @param FormSet The Form Set.\r
+ \r
+ @retval FORMSET_STORAGE * Return the first EFI_IFR_VARSTORE.\r
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.\r
+**/\r
+FORMSET_STORAGE *\r
+GetFirstStorageOfFormSet (\r
+ IN CONST FORM_BROWSER_FORMSET * FormSet\r
+ ) \r
+{\r
+ LIST_ENTRY *StorageList;\r
+ FORMSET_STORAGE *Storage;\r
+\r
+ StorageList = GetFirstNode (&FormSet->StorageListHead);\r
+\r
+ if (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
+ return Storage;\r
+ }\r
+ \r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Get the EFI_IFR_VARSTORE where the Question's value is stored.\r
\r
- @param Packages The Framework Package List\r
+ @param FormSet The Form Set.\r
\r
- @retval EFI_HII_PACKAGE_HEADER* Return the Package Header of\r
- Form Package.\r
- @retval NULL If no Form Package is found.\r
+ @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE where the Question's value is stored.\r
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE.\r
**/\r
-EFI_HII_PACKAGE_HEADER *\r
-GetIfrFormSet (\r
- IN CONST EFI_HII_PACKAGES *Packages\r
+FORMSET_STORAGE *\r
+GetStorageFromQuestionId (\r
+ IN CONST FORM_BROWSER_FORMSET * FormSet,\r
+ IN EFI_QUESTION_ID QuestionId\r
)\r
{\r
- TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray;\r
- EFI_HII_PACKAGE_HEADER *IfrPackage;\r
- UINTN Index;\r
+ LIST_ENTRY *FormList;\r
+ LIST_ENTRY *StatementList;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ FormList = GetFirstNode (&FormSet->FormListHead);\r
+\r
+ while (!IsNull (&FormSet->FormListHead, FormList)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (FormList);\r
+\r
+ StatementList = GetFirstNode (&Form->StatementListHead);\r
+\r
+ while (!IsNull (&Form->StatementListHead, StatementList)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);\r
+ if ((QuestionId == Statement->QuestionId) && (Statement->Storage != NULL)) {\r
+ //\r
+ // UEFI Question ID is unique in a FormSet.\r
+ //\r
+ ASSERT (Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER);\r
+ return Statement->Storage;\r
+ }\r
+ StatementList = GetNextNode (&Form->StatementListHead, StatementList);\r
+ }\r
\r
- ASSERT (Packages != NULL);\r
+ FormList = GetNextNode (&FormSet->FormListHead, FormList);\r
+ }\r
+ \r
+ return NULL;\r
+}\r
\r
- IfrPackage = NULL;\r
+/**\r
+ Get the EFI_IFR_VARSTORE based the ID.\r
+ \r
+ @param FormSet The Form Set.\r
+ \r
+ @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE with the ID.\r
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.\r
+**/\r
+FORMSET_STORAGE *\r
+GetStorageFromVarStoreId (\r
+ IN CONST FORM_BROWSER_FORMSET * FormSet,\r
+ IN EFI_VARSTORE_ID VarStoreId\r
+ )\r
+{\r
+ LIST_ENTRY *StorageList;\r
+ FORMSET_STORAGE *Storage;\r
\r
- TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId));\r
- for (Index = 0; Index < Packages->NumberOfPackages; Index++) {\r
- //\r
- // BugBug: The current UEFI HII build tool generate a binary in the format defined in: \r
- // TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in\r
- // this binary is with same package type. So the returned IfrPackNum and StringPackNum\r
- // may not be the exact number of valid package number in the binary generated \r
- // by HII Build tool.\r
- //\r
- switch (TianoAutogenPackageHdrArray[Index]->PackageHeader.Type) {\r
- case EFI_HII_PACKAGE_FORM:\r
- return &TianoAutogenPackageHdrArray[Index]->PackageHeader;\r
- break;\r
+ StorageList = GetFirstNode (&FormSet->StorageListHead);\r
\r
- case EFI_HII_PACKAGE_STRINGS:\r
- case EFI_HII_PACKAGE_SIMPLE_FONTS:\r
- break;\r
+ while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
\r
- //\r
- // The following fonts are invalid for a module that using Framework to UEFI thunk layer.\r
- //\r
- case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:\r
- case EFI_HII_PACKAGE_FONTS:\r
- case EFI_HII_PACKAGE_IMAGES:\r
- default:\r
- ASSERT (FALSE);\r
- break;\r
+ if (VarStoreId == Storage->VarStoreId) {\r
+ return Storage;\r
}\r
- }\r
\r
- return (EFI_HII_PACKAGE_HEADER *) NULL;\r
+ StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
+ }\r
+ \r
+ return NULL;\r
}\r
\r
/**\r
- This function scan EFI_IFR_VARSTORE_OP in the Form Package.\r
- It create entries for these VARSTORE found and append the entry\r
- to a Link List.\r
-\r
- If FormSetPackage is not EFI_HII_PACKAGE_FORM, then ASSERT.\r
- If there is no linear buffer storage in this formset, then ASSERT.\r
-\r
- @param FormSetPackage The Form Package header.\r
- @param BufferStorageListHead The link list for the VARSTORE found in the form package.\r
+ Get the EFI_IFR_VARSTORE based the <ConfigHdr> string in a <ConfigRequest>\r
+ or a <ConfigResp> string.\r
+ \r
+ @param FormSet The Form Set.\r
+ @param ConfigString The Configuration String which is defined by UEFI HII.\r
\r
- @retval EFI_SUCCESS The function scan the form set and find one or more \r
- VARSTOREs.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough memory to complete the function.\r
+ @retval FORMSET_STORAGE * The EFI_IFR_VARSTORE where the Question's value is stored.\r
+ @retval NULL If the Form Set does not have EFI_IFR_VARSTORE with such ID.\r
**/\r
-EFI_STATUS\r
-GetBufferStorage (\r
- IN CONST EFI_HII_PACKAGE_HEADER *FormSetPackage,\r
- OUT LIST_ENTRY *BufferStorageListHead\r
+FORMSET_STORAGE *\r
+GetStorageFromConfigString (\r
+ IN CONST FORM_BROWSER_FORMSET *FormSet,\r
+ IN CONST EFI_STRING ConfigString\r
)\r
{\r
- UINTN OpCodeOffset;\r
- UINTN OpCodeLength;\r
- UINT8 *OpCodeData;\r
- UINT8 Operand;\r
- EFI_IFR_VARSTORE *VarStoreOpCode;\r
- HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
-\r
- ASSERT (FormSetPackage->Type == EFI_HII_PACKAGE_FORM);\r
-\r
- OpCodeOffset = sizeof (EFI_HII_PACKAGE_HEADER);\r
- while (OpCodeOffset < FormSetPackage->Length) {\r
- OpCodeData = (UINT8 *) FormSetPackage + OpCodeOffset;\r
-\r
- OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
- OpCodeOffset += OpCodeLength;\r
- Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
-\r
- if (Operand == EFI_IFR_VARSTORE_OP) {\r
- VarStoreOpCode = (EFI_IFR_VARSTORE *)OpCodeData;\r
- BufferStorageKey = AllocateZeroPool (sizeof (*BufferStorageKey));\r
- if (BufferStorageKey == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- CopyMem (&BufferStorageKey->Guid, &VarStoreOpCode->Guid, sizeof (EFI_GUID));\r
- \r
- BufferStorageKey->Name = AllocateZeroPool (AsciiStrSize (VarStoreOpCode->Name) * 2);\r
- AsciiStrToUnicodeStr (VarStoreOpCode->Name, BufferStorageKey->Name);\r
+ LIST_ENTRY *StorageList;\r
+ FORMSET_STORAGE *Storage;\r
\r
- BufferStorageKey->VarStoreId = VarStoreOpCode->VarStoreId;\r
+ StorageList = GetFirstNode (&FormSet->StorageListHead);\r
\r
- BufferStorageKey->Size = VarStoreOpCode->Size;\r
- BufferStorageKey->Signature = HII_TRHUNK_BUFFER_STORAGE_KEY_SIGNATURE;\r
+ while (!IsNull (&FormSet->StorageListHead, StorageList)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (StorageList);\r
\r
- InsertTailList (BufferStorageListHead, &BufferStorageKey->List);\r
+ if (IsConfigHdrMatch (ConfigString, &Storage->Guid, Storage->Name)) {\r
+ return Storage;\r
}\r
+\r
+ StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);\r
}\r
\r
- return EFI_SUCCESS;\r
+ return NULL;\r
}\r
- \r
+\r
/**\r
This function installs a EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered\r
by a module using Framework HII Protocol Interfaces.\r
\r
- UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
- that Setup Utility can load the Buffer Storage using this protocol.\r
+ UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so\r
+ that Setup Utility can load the Buffer Storage using this protocol.\r
\r
- @param Packages The framework package list.\r
- @param MapEntry The Thunk Layer Handle Mapping Database Entry.\r
+ @param Packages The Package List.\r
+ @param ThunkContext The Thunk Context.\r
\r
- @retval EFI_SUCCESS The Config Access Protocol is installed successfully.\r
- @retval EFI_OUT_RESOURCE There is not enough memory.\r
+ @retval EFI_SUCCESS The Config Access Protocol is installed successfully.\r
+ @retval EFI_OUT_RESOURCE There is not enough memory.\r
\r
**/\r
EFI_STATUS\r
-InstallDefaultUefiConfigAccessProtocol (\r
- IN CONST EFI_HII_PACKAGES *Packages,\r
- IN OUT HII_TRHUNK_HANDLE_MAPPING_DATABASE_ENTRY *MapEntry\r
+InstallDefaultConfigAccessProtocol (\r
+ IN CONST EFI_HII_PACKAGES *Packages,\r
+ IN OUT HII_THUNK_CONTEXT *ThunkContext\r
)\r
{\r
- EFI_HII_PACKAGE_HEADER *FormSetPackage;\r
EFI_STATUS Status;\r
- HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigAccessInstance;\r
+ CONFIG_ACCESS_PRIVATE *ConfigAccessInstance;\r
+\r
+ ASSERT (ThunkContext->IfrPackageCount != 0);\r
\r
- Status = HiiLibCreateHiiDriverHandle (&MapEntry->UefiHiiDriverHandle);\r
+ Status = HiiLibCreateHiiDriverHandle (&ThunkContext->UefiHiiDriverHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
ConfigAccessInstance = AllocateCopyPool (\r
- sizeof (HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE), \r
- &ConfigAccessProtocolInstanceTempate\r
+ sizeof (CONFIG_ACCESS_PRIVATE), \r
+ &gConfigAccessPrivateTempate\r
);\r
ASSERT (ConfigAccessInstance != NULL);\r
- InitializeListHead (&ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
-\r
- //\r
- // We assume there is only one formset package in each Forms Package\r
- //\r
- FormSetPackage = GetIfrFormSet (Packages);\r
- ASSERT (FormSetPackage != NULL);\r
\r
- Status = GetBufferStorage (FormSetPackage, &ConfigAccessInstance->ConfigAccessBufferStorageListHead);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ConfigAccessInstance);\r
- ASSERT (FALSE);\r
- return Status;\r
- }\r
-\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &MapEntry->UefiHiiDriverHandle,\r
+ &ThunkContext->UefiHiiDriverHandle,\r
&gEfiHiiConfigAccessProtocolGuid,\r
&ConfigAccessInstance->ConfigAccessProtocol,\r
NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (ConfigAccessInstance);\r
- return Status;\r
- }\r
+ \r
+ ConfigAccessInstance->ThunkContext = ThunkContext;\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
+ This function un-installs the EFI_CONFIG_ACCESS_PROTOCOL instance for a form package registered\r
+ by a module using Framework HII Protocol Interfaces.\r
\r
- Wrap EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
- \r
- @param BufferStorageKey The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
- @param FrameworkFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
- @param Data The data to be saved.\r
- @param DataSize The size of data.\r
+ ASSERT if no Config Access is found for such pakcage list or failed to uninstall the protocol.\r
+\r
+ @param ThunkContext The Thunk Context.\r
\r
- @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
- **/\r
-EFI_STATUS\r
-RouteConfigToFrameworkFormCallBack (\r
- IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
- IN EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallBack,\r
- IN VOID *Data,\r
- IN UINTN DataSize\r
+**/\r
+VOID\r
+UninstallDefaultConfigAccessProtocol (\r
+ IN HII_THUNK_CONTEXT *ThunkContext\r
)\r
{\r
- EFI_STATUS Status;\r
- BOOLEAN ResetRequired;\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ \r
+ HiiLibDestroyHiiDriverHandle (ThunkContext->UefiHiiDriverHandle);\r
+\r
+ Status = gBS->HandleProtocol (\r
+ ThunkContext->UefiHiiDriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **) &ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->UninstallProtocolInterface (\r
+ ThunkContext->UefiHiiDriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ ConfigAccess\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
\r
- Status = FrameworkFormCallBack->NvWrite (\r
- FrameworkFormCallBack, \r
- BufferStorageKey->Name,\r
- &BufferStorageKey->Guid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- DataSize,\r
- Data,\r
- &ResetRequired\r
- );\r
- return Status;\r
}\r
+ \r
\r
/**\r
Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
\r
- @param BufferStorageKey The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
- @param FrameworkFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
- @param Data The data read.\r
- @param DataSize The size of data.\r
+ @param BufferStorage The key with all attributes needed to call EFI_FORM_CALLBACK_PROTOCOL.NvRead.\r
+ @param FwFormCallBack The EFI_FORM_CALLBACK_PROTOCOL registered by Framework HII module.\r
+ @param Data The data read.\r
+ @param DataSize The size of data.\r
\r
- @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
+ @retval EFI_STATUS The status returned by the EFI_FORM_CALLBACK_PROTOCOL.NvWrite.\r
@retval EFI_INVALID_PARAMETER If the EFI_FORM_CALLBACK_PROTOCOL.NvRead return the size information of the data\r
- does not match what has been recorded early in he HII_TRHUNK_BUFFER_STORAGE_KEY.\r
+ does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
**/\r
EFI_STATUS\r
-ExtractConfigFromFrameworkFormCallBack (\r
- IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
- IN EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallBack,\r
+CallFormCallBack (\r
+ IN FORMSET_STORAGE *BufferStorage,\r
+ IN EFI_FORM_CALLBACK_PROTOCOL *FwFormCallBack,\r
OUT VOID **Data,\r
OUT UINTN *DataSize\r
)\r
*DataSize = 0;\r
*Data = NULL;\r
\r
- Status = FrameworkFormCallBack->NvRead (\r
- FrameworkFormCallBack, \r
- BufferStorageKey->Name,\r
- &BufferStorageKey->Guid,\r
+ Status = FwFormCallBack->NvRead (\r
+ FwFormCallBack, \r
+ BufferStorage->Name,\r
+ &BufferStorage->Guid,\r
NULL,\r
DataSize,\r
*Data\r
);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
- if (BufferStorageKey->Size != *DataSize) {\r
+ if (BufferStorage->Size != *DataSize) {\r
ASSERT (FALSE);\r
return EFI_INVALID_PARAMETER;\r
}\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- FrameworkFormCallBack->NvRead (\r
- FrameworkFormCallBack, \r
- BufferStorageKey->Name,\r
- &BufferStorageKey->Guid,\r
+ FwFormCallBack->NvRead (\r
+ FwFormCallBack, \r
+ BufferStorage->Name,\r
+ &BufferStorage->Guid,\r
NULL,\r
DataSize,\r
*Data\r
return Status;\r
}\r
\r
-/**\r
- Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Set Service.\r
- \r
- @param BufferStorageKey The key with all attributes needed to call a UEFI Variable Get Service.\r
- @param Data The data read.\r
- @param DataSize The size of data.\r
-\r
- @retval EFI_STATUS The status returned by the UEFI Variable Set Service.\r
- \r
- **/\r
-EFI_STATUS\r
-RouteConfigToUefiVariable (\r
- IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
- IN VOID *Data,\r
- IN UINTN DataSize\r
- )\r
-{\r
- return gRT->SetVariable (\r
- BufferStorageKey->Name,\r
- &BufferStorageKey->Guid,\r
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
- DataSize,\r
- Data\r
- );\r
- \r
-}\r
\r
/**\r
Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.ExtractConfig to a call to UEFI Variable Get Service.\r
\r
- @param BufferStorageKey The key with all attributes needed to call a UEFI Variable Get Service.\r
- @param Data The data read.\r
- @param DataSize The size of data.\r
+ @param BufferStorage The key with all attributes needed to call a UEFI Variable Get Service.\r
+ @param Data The data read.\r
+ @param DataSize The size of data.\r
\r
If the UEFI Variable Get Service return the size information of the data\r
- does not match what has been recorded early in he HII_TRHUNK_BUFFER_STORAGE_KEY.\r
+ does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
then ASSERT.\r
\r
- @retval EFI_STATUS The status returned by the UEFI Variable Get Service.\r
+ @retval EFI_STATUS The status returned by the UEFI Variable Get Service.\r
@retval EFI_INVALID_PARAMETER If the UEFI Variable Get Service return the size information of the data\r
- does not match what has been recorded early in he HII_TRHUNK_BUFFER_STORAGE_KEY.\r
+ does not match what has been recorded early in he BUFFER_STORAGE_ENTRY.\r
**/\r
\r
EFI_STATUS\r
-ExtractConfigFromUefiVariable (\r
- IN HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey,\r
+GetUefiVariable (\r
+ IN FORMSET_STORAGE *BufferStorage,\r
OUT VOID **Data,\r
OUT UINTN *DataSize\r
)\r
*DataSize = 0;\r
*Data = NULL;\r
Status = gRT->GetVariable (\r
- BufferStorageKey->Name,\r
- &BufferStorageKey->Guid,\r
+ BufferStorage->Name,\r
+ &BufferStorage->Guid,\r
NULL,\r
DataSize,\r
*Data\r
);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
\r
- if (BufferStorageKey->Size != *DataSize) {\r
+ if (BufferStorage->Size != *DataSize) {\r
ASSERT (FALSE);\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
\r
Status = gRT->GetVariable (\r
- BufferStorageKey->Name,\r
- &BufferStorageKey->Guid,\r
+ BufferStorage->Name,\r
+ &BufferStorage->Guid,\r
NULL,\r
DataSize,\r
*Data\r
so that data can be read from the data storage such as UEFI Variable or module's\r
customized storage exposed by EFI_FRAMEWORK_CALLBACK.\r
\r
- @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
@param Request A null-terminated Unicode string in <ConfigRequest> format. Note that this\r
- includes the routing information as well as the configurable name / value pairs. It is\r
- invalid for this string to be in <MultiConfigRequest> format.\r
+ includes the routing information as well as the configurable name / value pairs. It is\r
+ invalid for this string to be in <MultiConfigRequest> format.\r
\r
- @param Progress On return, points to a character in the Request string. Points to the string's null\r
- terminator if request was successful. Points to the most recent '&' before the first\r
- failing name / value pair (or the beginning of the string if the failure is in the first\r
- name / value pair) if the request was not successful\r
+ @param Progress On return, points to a character in the Request string. Points to the string's null\r
+ terminator if request was successful. Points to the most recent '&' before the first\r
+ failing name / value pair (or the beginning of the string if the failure is in the first\r
+ name / value pair) if the request was not successful\r
@param Results A null-terminated Unicode string in <ConfigAltResp> format which has all\r
- values filled in for the names in the Request string. String to be allocated by the called\r
- function.\r
+ values filled in for the names in the Request string. String to be allocated by the called\r
+ function.\r
\r
@retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.\r
- @retval EFI_SUCCESS The setting is retrived successfully.\r
- @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.\r
+ @retval EFI_SUCCESS The setting is retrived successfully.\r
+ @retval !EFI_SUCCESS The error returned by UEFI Get Variable or Framework Form Callback Nvread.\r
**/\r
EFI_STATUS\r
EFIAPI\r
)\r
{\r
EFI_STATUS Status;\r
- HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
- LIST_ENTRY *ListEntry;\r
- HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
+ CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
+ FORMSET_STORAGE *BufferStorage;\r
VOID *Data;\r
UINTN DataSize;\r
\r
Data = NULL;\r
- ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+ ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
\r
- //\r
- // For now, only one var varstore is supported so that we don't need to parse the Configuration string.\r
- //\r
- ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
- if (ListEntry == NULL) {\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
-\r
- if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
- ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
- Status = ExtractConfigFromUefiVariable (\r
- BufferStorageKey,\r
- &Data,\r
- &DataSize\r
- );\r
+ BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Request);\r
+\r
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+ //\r
+ // NvMapOverride is not used. Get the Storage data from EFI Variable or Framework Form Callback.\r
+ //\r
+ if (ConfigAccess->FormCallbackProtocol == NULL ||\r
+ ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
+ Status = GetUefiVariable (\r
+ BufferStorage,\r
+ &Data,\r
+ &DataSize\r
+ );\r
+ } else {\r
+ Status = CallFormCallBack (\r
+ BufferStorage,\r
+ ConfigAccess->FormCallbackProtocol,\r
+ &Data,\r
+ &DataSize\r
+ );\r
+ }\r
} else {\r
- Status = ExtractConfigFromFrameworkFormCallBack (\r
- BufferStorageKey,\r
- ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
- &Data,\r
- &DataSize\r
- );\r
+ //\r
+ // Use the NvMapOverride.\r
+ //\r
+ DataSize = BufferStorage->Size;\r
+ Data = AllocateCopyPool (DataSize, ConfigAccess->ThunkContext->NvMapOverride);\r
+ \r
+ if (Data != NULL) {\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ }\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
);\r
}\r
\r
- SafeFreePool (Data);\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
return Status;\r
}\r
\r
/**\r
-\r
This function implement the EFI_HII_CONFIG_ACCESS_PROTOCOL.RouteConfig\r
so that data can be written to the data storage such as UEFI Variable or module's\r
customized storage exposed by EFI_FRAMEWORK_CALLBACK.\r
\r
- @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
- @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
+ @param Configuration A null-terminated Unicode string in <ConfigResp> format.\r
@param Progress A pointer to a string filled in with the offset of the most recent '&' before the first\r
- failing name / value pair (or the beginning of the string if the failure is in the first\r
- name / value pair) or the terminating NULL if all was successful.\r
+ failing name / value pair (or the beginning of the string if the failure is in the first\r
+ name / value pair) or the terminating NULL if all was successful.\r
\r
@retval EFI_INVALID_PARAMETER If there is no Buffer Storage for this Config Access instance.\r
- @retval EFI_SUCCESS The setting is saved successfully.\r
- @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.\r
+ @retval EFI_SUCCESS The setting is saved successfully.\r
+ @retval !EFI_SUCCESS The error returned by UEFI Set Variable or Framework Form Callback Nvwrite.\r
**/ \r
EFI_STATUS\r
EFIAPI\r
)\r
{\r
EFI_STATUS Status;\r
- HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
- LIST_ENTRY *ListEntry;\r
- HII_TRHUNK_BUFFER_STORAGE_KEY *BufferStorageKey;\r
+ CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
+ FORMSET_STORAGE *BufferStorage;\r
VOID *Data;\r
UINTN DataSize;\r
+ UINTN DataSize2;\r
UINTN LastModifiedByteIndex;\r
+ BOOLEAN ResetRequired;\r
+ BOOLEAN DataAllocated;\r
\r
Data = NULL;\r
- ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
-\r
- //\r
- // For now, only one var varstore is supported so that we don't need to parse the Configuration string.\r
- //\r
- ListEntry = GetFirstNode (&ConfigaAccessInstance->ConfigAccessBufferStorageListHead);\r
- if (ListEntry == NULL) {\r
- ASSERT (FALSE);\r
- return EFI_INVALID_PARAMETER;\r
+ ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
+\r
+ BufferStorage = GetStorageFromConfigString (ConfigAccess->ThunkContext->FormSet, Configuration);\r
+\r
+ DataSize2 = BufferStorage->Size;\r
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+ DataAllocated = TRUE;\r
+ if (ConfigAccess->FormCallbackProtocol == NULL ||\r
+ ConfigAccess->FormCallbackProtocol->NvRead == NULL) {\r
+ Status = GetUefiVariable (\r
+ BufferStorage,\r
+ &Data,\r
+ &DataSize\r
+ );\r
+ } else {\r
+ Status = CallFormCallBack (\r
+ BufferStorage,\r
+ ConfigAccess->FormCallbackProtocol,\r
+ &Data,\r
+ &DataSize\r
+ );\r
+ }\r
+ } else {\r
+ //\r
+ // ConfigToBlock will convert the Config String and update the NvMapOverride accordingly.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ Data = ConfigAccess->ThunkContext->NvMapOverride;\r
+ DataSize = DataSize2;\r
+ DataAllocated = FALSE;\r
+ } \r
+ if (EFI_ERROR (Status) || (DataSize2 != DataSize)) {\r
+ if (Data == NULL) {\r
+ Data = AllocateZeroPool (DataSize2);\r
+ }\r
}\r
\r
- BufferStorageKey = HII_TRHUNK_BUFFER_STORAGE_KEY_FROM_LIST_ENTRY (ListEntry);\r
-\r
- Data = AllocateZeroPool (BufferStorageKey->Size);\r
- if (Data == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
Status = mHiiConfigRoutingProtocol->ConfigToBlock (\r
mHiiConfigRoutingProtocol,\r
Configuration,\r
&LastModifiedByteIndex,\r
Progress\r
);\r
-\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
\r
- DataSize = BufferStorageKey->Size;\r
- if (ConfigaAccessInstance->FrameworkFormCallbackProtocol == NULL ||\r
- ConfigaAccessInstance->FrameworkFormCallbackProtocol->NvRead == NULL) {\r
- Status = RouteConfigToUefiVariable (\r
- BufferStorageKey,\r
- Data,\r
- DataSize\r
- );\r
- } else {\r
- Status = RouteConfigToFrameworkFormCallBack (\r
- BufferStorageKey,\r
- ConfigaAccessInstance->FrameworkFormCallbackProtocol,\r
- Data,\r
- DataSize\r
- );\r
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+ if (ConfigAccess->FormCallbackProtocol == NULL ||\r
+ ConfigAccess->FormCallbackProtocol->NvWrite == NULL) {\r
+ Status = gRT->SetVariable (\r
+ BufferStorage->Name,\r
+ &BufferStorage->Guid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ DataSize2,\r
+ Data\r
+ );\r
+ } else {\r
+ Status = ConfigAccess->FormCallbackProtocol->NvWrite (\r
+ ConfigAccess->FormCallbackProtocol, \r
+ BufferStorage->Name,\r
+ &BufferStorage->Guid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
+ DataSize2,\r
+ Data,\r
+ &ResetRequired\r
+ );\r
+ \r
+ }\r
}\r
\r
-Done: \r
- SafeFreePool (Data);\r
+Done: \r
+ if (DataAllocated && (Data != NULL)) {\r
+ FreePool (Data);\r
+ }\r
+ \r
return Status;\r
}\r
\r
+/**\r
+ Build the FRAMEWORK_EFI_IFR_DATA_ARRAY which will be used to pass to \r
+ EFI_FORM_CALLBACK_PROTOCOL.Callback. Check definition of FRAMEWORK_EFI_IFR_DATA_ARRAY\r
+ for details.\r
+\r
+ ASSERT if the Question Type is not EFI_IFR_TYPE_NUM_SIZE_* or EFI_IFR_TYPE_STRING.\r
+ \r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL\r
+ @param QuestionId The Question ID.\r
+ @param Type The Question Type.\r
+ @param Value The Question Value.\r
+ @param NvMapAllocated On output indicates if a buffer is allocated for NvMap.\r
+ \r
+ @return A pointer to FRAMEWORK_EFI_IFR_DATA_ARRAY. The caller must free this buffer allocated.\r
+**/ \r
+FRAMEWORK_EFI_IFR_DATA_ARRAY *\r
+CreateIfrDataArray (\r
+ IN CONFIG_ACCESS_PRIVATE *ConfigAccess,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT BOOLEAN *NvMapAllocated\r
+ )\r
+{\r
+ FRAMEWORK_EFI_IFR_DATA_ARRAY *IfrDataArray;\r
+ FRAMEWORK_EFI_IFR_DATA_ENTRY *IfrDataEntry;\r
+ UINTN BrowserDataSize;\r
+ FORMSET_STORAGE *BufferStorage;\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ UINTN StringSize;\r
+ EFI_STRING String;\r
+\r
+ *NvMapAllocated = FALSE;\r
+\r
+ String = NULL;\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ Size = sizeof (*Value);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_STRING:\r
+ StringSize = 0;\r
+ Status = HiiLibGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, String, &StringSize);\r
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+\r
+ String = AllocateZeroPool (StringSize);\r
+ ASSERT (String != NULL);\r
+\r
+ Status = HiiLibGetString (ConfigAccess->ThunkContext->UefiHiiHandle, Value->string, String, &StringSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Size = StringSize;\r
+ break;\r
+ \r
+ default:\r
+ ASSERT (FALSE);\r
+ Size = 0;\r
+ break;\r
+ }\r
+\r
+ IfrDataArray = AllocateZeroPool (sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY) + sizeof (FRAMEWORK_EFI_IFR_DATA_ENTRY) + Size);\r
+ ASSERT (IfrDataArray != NULL);\r
+\r
+ BufferStorage = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
+\r
+ if (BufferStorage == NULL) {\r
+ //\r
+ // The QuestionId is not associated with a Buffer Storage.\r
+ // Try to get the first Buffer Storage then.\r
+ //\r
+ BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);\r
+ }\r
+ \r
+ if (BufferStorage != NULL) {\r
+ BrowserDataSize = BufferStorage->Size;\r
+\r
+ if (ConfigAccess->ThunkContext->NvMapOverride == NULL) {\r
+ *NvMapAllocated = TRUE;\r
+ IfrDataArray->NvRamMap = AllocateZeroPool (BrowserDataSize);\r
+ } else {\r
+ *NvMapAllocated = FALSE;\r
+ IfrDataArray->NvRamMap = ConfigAccess->ThunkContext->NvMapOverride;\r
+ }\r
+ \r
+ Status = GetBrowserData (&BufferStorage->Guid, BufferStorage->Name, &BrowserDataSize, IfrDataArray->NvRamMap);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ IfrDataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) (IfrDataArray + 1);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ CopyMem (&IfrDataEntry->Data, &(Value->u8), sizeof (*Value));\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_STRING:\r
+ ASSERT (String != NULL);\r
+ StrCpy ((CHAR16 *) &IfrDataEntry->Data, String);\r
+ FreePool (String);\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Need to fiil in the information for the rest of field for FRAMEWORK_EFI_IFR_DATA_ENTRY.\r
+ // It seems that no implementation is found to use other fields. Leave them uninitialized for now.\r
+ //\r
+ //UINT8 OpCode; // Likely a string, numeric, or one-of\r
+ //UINT8 Length; // Length of the FRAMEWORK_EFI_IFR_DATA_ENTRY packet\r
+ //UINT16 Flags; // Flags settings to determine what behavior is desired from the browser after the callback\r
+ //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\r
+ // If the OpCode is a OneOf or Numeric type - Data is a UINT16 value\r
+ // If the OpCode is a String type - Data is a CHAR16[x] type\r
+ // If the OpCode is a Checkbox type - Data is a UINT8 value\r
+ // If the OpCode is a NV Access type - Data is a FRAMEWORK_EFI_IFR_NV_DATA structure\r
+ }\r
+\r
+ return IfrDataArray;\r
+}\r
+\r
+/**\r
+ If a NvMapOverride is passed in to EFI_FORM_BROWSER_PROTOCOL.SendForm, the Form Browser\r
+ needs to be informed when data changed in NvMapOverride. This function will invoke\r
+ SetBrowserData () to set internal data of Form Browser.\r
+\r
+ @param ConfigAccess The Config Access Private Context.\r
+ @param QuestionId The Question Id that invokes the callback.\r
+ \r
+\r
+**/\r
+VOID\r
+SyncBrowserDataForNvMapOverride (\r
+ IN CONST CONFIG_ACCESS_PRIVATE *ConfigAccess,\r
+ IN EFI_QUESTION_ID QuestionId\r
+ )\r
+{\r
+ FORMSET_STORAGE *BufferStorage;\r
+ EFI_STATUS Status;\r
+ UINTN BrowserDataSize;\r
+\r
+ if (ConfigAccess->ThunkContext->NvMapOverride != NULL) {\r
+\r
+ BufferStorage = GetStorageFromQuestionId (ConfigAccess->ThunkContext->FormSet, QuestionId);\r
+\r
+ if (BufferStorage == NULL) {\r
+ //\r
+ // QuestionId is a statement without Storage.\r
+ // 1) It is a Goto. \r
+ // \r
+ //\r
+ BufferStorage = GetFirstStorageOfFormSet (ConfigAccess->ThunkContext->FormSet);\r
+ }\r
+\r
+ //\r
+ // If NvMapOverride is not NULL, this Form must have at least one Buffer Type Variable Storage.\r
+ //\r
+ ASSERT (BufferStorage != NULL);\r
+ \r
+ BrowserDataSize = BufferStorage->Size;\r
+\r
+ Status = SetBrowserData (&BufferStorage->Guid, BufferStorage->Name, BrowserDataSize, ConfigAccess->ThunkContext->NvMapOverride, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Free up resource allocated for a FRAMEWORK_EFI_IFR_DATA_ARRAY by CreateIfrDataArray ().\r
+\r
+ @param Array The FRAMEWORK_EFI_IFR_DATA_ARRAY allocated.\r
+ @param NvMapAllocated If the NvRamMap is allocated for FRAMEWORK_EFI_IFR_DATA_ARRAY.\r
+\r
+**/\r
+VOID\r
+DestroyIfrDataArray (\r
+ IN FRAMEWORK_EFI_IFR_DATA_ARRAY *Array,\r
+ IN BOOLEAN NvMapAllocated\r
+ )\r
+{\r
+ if (Array != NULL) {\r
+ if (NvMapAllocated) {\r
+ FreePool (Array->NvRamMap);\r
+ }\r
+\r
+ FreePool (Array);\r
+ }\r
+}\r
+\r
+/**\r
+ Get the ONE_OF_OPTION_MAP_ENTRY for a QuestionId that invokes the \r
+ EFI_FORM_CALLBACK_PROTOCOL.Callback. The information is needed as\r
+ the callback mechanism for EFI_IFR_ONE_OF_OPTION is changed from \r
+ EFI_IFR_ONE_OF_OPTION in Framework IFR. Check EFI_IFR_GUID_OPTIONKEY\r
+ for detailed information.\r
+\r
+ @param ThunkContext The Thunk Context.\r
+ @param QuestionId The Question Id.\r
+ @param Type The Question Type.\r
+ @param Value The One Of Option's value.\r
+\r
+ @return The ONE_OF_OPTION_MAP_ENTRY found.\r
+ @retval NULL If no entry is found.\r
+**/\r
+ONE_OF_OPTION_MAP_ENTRY *\r
+GetOneOfOptionMapEntry (\r
+ IN HII_THUNK_CONTEXT *ThunkContext,\r
+ IN EFI_QUESTION_ID QuestionId,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *Link2;\r
+ ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
+ ONE_OF_OPTION_MAP *OneOfOptionMap;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+\r
+ FormSet = ThunkContext->FormSet;\r
+\r
+ Link = GetFirstNode (&FormSet->OneOfOptionMapListHead);\r
+\r
+ while (!IsNull (&FormSet->OneOfOptionMapListHead, Link)) {\r
+ OneOfOptionMap = ONE_OF_OPTION_MAP_FROM_LINK(Link);\r
+ if (OneOfOptionMap->QuestionId == QuestionId) {\r
+ ASSERT (OneOfOptionMap->ValueType == Type);\r
+\r
+ Link2 = GetFirstNode (&OneOfOptionMap->OneOfOptionMapEntryListHead);\r
+\r
+ while (!IsNull (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2)) {\r
+ OneOfOptionMapEntry = ONE_OF_OPTION_MAP_ENTRY_FROM_LINK (Link2);\r
+\r
+ if (CompareMem (Value, &OneOfOptionMapEntry->Value, sizeof (EFI_IFR_TYPE_VALUE)) == 0) {\r
+ return OneOfOptionMapEntry;\r
+ }\r
+\r
+ Link2 = GetNextNode (&OneOfOptionMap->OneOfOptionMapEntryListHead, Link2);\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->OneOfOptionMapListHead, Link);\r
+ }\r
+\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Functions which are registered to receive notification of\r
+ database events have this prototype. The actual event is encoded\r
+ in NotifyType. The following table describes how PackageType,\r
+ PackageGuid, Handle, and Package are used for each of the\r
+ notification types.\r
+\r
+ If any Pakcage List in database is updated, mHiiPackageListUpdated\r
+ will be set. If mHiiPackageListUpdated is set, Framework ThunkCallback()\r
+ will force the UEFI Setup Browser to save the uncommitted data. This\r
+ is needed as Framework's Callback function may dynamically update\r
+ opcode in a Package List. UEFI Setup Browser will quit itself and reparse\r
+ the Package List's IFR and display it. UEFI Config Access's implementation\r
+ is required to save the modified (SetBrowserData or directly save the data\r
+ to NV storage). But Framework HII Modules is not aware of this rule. Therefore,\r
+ we will enforce the rule in ThunkCallback (). The side effect of force saving\r
+ of NV data is the NV flag in browser may not flag a update as data has already\r
+ been saved to NV storage.\r
+\r
+ @param PackageType Package type of the notification.\r
+\r
+ @param PackageGuid If PackageType is\r
+ EFI_HII_PACKAGE_TYPE_GUID, then this is\r
+ the pointer to the GUID from the Guid\r
+ field of EFI_HII_PACKAGE_GUID_HEADER.\r
+ Otherwise, it must be NULL.\r
+\r
+ @param Package Points to the package referred to by the\r
+ notification Handle The handle of the package\r
+ list which contains the specified package.\r
+\r
+ @param Handle The HII handle.\r
+\r
+ @param NotifyType The type of change concerning the\r
+ database. See\r
+ EFI_HII_DATABASE_NOTIFY_TYPE.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FormUpdateNotify (\r
+ IN UINT8 PackageType,\r
+ IN CONST EFI_GUID *PackageGuid,\r
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
+ )\r
+{\r
+ mHiiPackageListUpdated = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Wrap the EFI_HII_CONFIG_ACCESS_PROTOCOL.CallBack to EFI_FORM_CALLBACK_PROTOCOL.Callback. Therefor,\r
- the framework HII module willl do no porting (except some porting works needed for callback for EFI_ONE_OF_OPTION opcode)\r
- and still work with a UEFI HII SetupBrowser.\r
+ the framework HII module willl do no porting and work with a UEFI HII SetupBrowser.\r
\r
- @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
- @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action Specifies the type of action taken by the browser. See EFI_BROWSER_ACTION_x.\r
@param QuestionId A unique value which is sent to the original exporting driver so that it can identify the\r
- type of data to expect. The format of the data tends to vary based on the opcode that\r
- generated the callback.\r
- @param Type The type of value for the question. See EFI_IFR_TYPE_x in\r
- EFI_IFR_ONE_OF_OPTION.\r
- @param Value A pointer to the data being sent to the original exporting driver. The type is specified\r
- by Type. Type EFI_IFR_TYPE_VALUE is defined in\r
- EFI_IFR_ONE_OF_OPTION.\r
+ type of data to expect. The format of the data tends to vary based on the opcode that\r
+ generated the callback.\r
+ @param Type The type of value for the question. See EFI_IFR_TYPE_x in\r
+ EFI_IFR_ONE_OF_OPTION.\r
+ @param Value A pointer to the data being sent to the original exporting driver. The type is specified\r
+ by Type. Type EFI_IFR_TYPE_VALUE is defined in\r
+ EFI_IFR_ONE_OF_OPTION.\r
@param ActionRequest On return, points to the action requested by the callback function. Type\r
- EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form\r
- Browser Protocol.\r
+ EFI_BROWSER_ACTION_REQUEST is specified in SendForm() in the Form\r
+ Browser Protocol.\r
\r
- @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under\r
- focuse to be INTERRACTIVE.\r
+ @retval EFI_UNSUPPORTED If the Framework HII module does not register Callback although it specify the opcode under\r
+ focuse to be INTERRACTIVE.\r
@retval EFI_SUCCESS The callback complete successfully.\r
@retval !EFI_SUCCESS The error code returned by EFI_FORM_CALLBACK_PROTOCOL.Callback.\r
\r
)\r
{\r
EFI_STATUS Status;\r
- HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE *ConfigaAccessInstance;\r
- EFI_FORM_CALLBACK_PROTOCOL *FrameworkFormCallbackProtocol;\r
+ CONFIG_ACCESS_PRIVATE *ConfigAccess;\r
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProtocol;\r
EFI_HII_CALLBACK_PACKET *Packet;\r
- FRAMEWORK_EFI_IFR_DATA_ARRAY Data;\r
+ FRAMEWORK_EFI_IFR_DATA_ARRAY *Data;\r
FRAMEWORK_EFI_IFR_DATA_ENTRY *DataEntry;\r
- EFI_FORM_CALLBACK Callback; \r
+ UINT16 KeyValue;\r
+ ONE_OF_OPTION_MAP_ENTRY *OneOfOptionMapEntry;\r
+ EFI_HANDLE NotifyHandle;\r
+ EFI_INPUT_KEY Key; \r
+ BOOLEAN NvMapAllocated;\r
\r
ASSERT (This != NULL);\r
ASSERT (Value != NULL);\r
\r
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
\r
- ConfigaAccessInstance = HII_TRHUNK_CONFIG_ACCESS_PROTOCOL_INSTANCE_FROM_PROTOCOL (This);\r
+ ConfigAccess = CONFIG_ACCESS_PRIVATE_FROM_PROTOCOL (This);\r
\r
- FrameworkFormCallbackProtocol = ConfigaAccessInstance->FrameworkFormCallbackProtocol;\r
- if (FrameworkFormCallbackProtocol == NULL) {\r
+ FormCallbackProtocol = ConfigAccess->FormCallbackProtocol;\r
+ if (FormCallbackProtocol == NULL) {\r
+ ASSERT (FALSE);\r
return EFI_UNSUPPORTED;\r
}\r
- Callback = FrameworkFormCallbackProtocol->Callback;\r
\r
- Status = Callback (\r
- FrameworkFormCallbackProtocol,\r
- QuestionId,\r
- &Data,\r
+ //\r
+ // Check if the QuestionId match a OneOfOption.\r
+ //\r
+ OneOfOptionMapEntry = GetOneOfOptionMapEntry (ConfigAccess->ThunkContext, QuestionId, Type, Value);\r
+\r
+ if (OneOfOptionMapEntry == NULL) {\r
+ //\r
+ // This is not a One-Of-Option opcode. QuestionId is the KeyValue\r
+ //\r
+ KeyValue = QuestionId;\r
+ } else {\r
+ //\r
+ // Otherwise, use the original Key specified in One Of Option in the Framework VFR syntax.\r
+ //\r
+ KeyValue = OneOfOptionMapEntry->FwKey;\r
+ }\r
+\r
+ //\r
+ // Build the FRAMEWORK_EFI_IFR_DATA_ARRAY\r
+ //\r
+ Data = CreateIfrDataArray (ConfigAccess, QuestionId, Type, Value, &NvMapAllocated);\r
+\r
+ Status = mHiiDatabase->RegisterPackageNotify (\r
+ mHiiDatabase,\r
+ EFI_HII_PACKAGE_FORMS,\r
+ NULL,\r
+ FormUpdateNotify,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ &NotifyHandle\r
+ );\r
+ //\r
+ //Call the Framework Callback function.\r
+ //\r
+ Packet = NULL;\r
+ Status = FormCallbackProtocol->Callback (\r
+ FormCallbackProtocol,\r
+ KeyValue,\r
+ Data,\r
&Packet\r
);\r
+ SyncBrowserDataForNvMapOverride (ConfigAccess, QuestionId);\r
\r
//\r
// Callback require browser to perform action\r
//\r
- if (Packet != NULL) {\r
- if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {\r
- DataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY));\r
- switch (DataEntry->Flags) {\r
- case EXIT_REQUIRED:\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
- break;\r
- case SAVE_REQUIRED:\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
- break;\r
- case RESET_REQUIRED:\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET;\r
- break;\r
- default:\r
- *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
- break; \r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ if (Packet != NULL) {\r
+ do {\r
+ IfrLibCreatePopUp (1, &Key, Packet->String);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+ //\r
+ // Error Code in Status is discarded.\r
+ //\r
+ } else {\r
+ if (Packet != NULL) {\r
+ if (Packet->DataArray.EntryCount == 1 && Packet->DataArray.NvRamMap == NULL) {\r
+ DataEntry = (FRAMEWORK_EFI_IFR_DATA_ENTRY *) ((UINT8 *) Packet + sizeof (FRAMEWORK_EFI_IFR_DATA_ARRAY));\r
+ if ((DataEntry->Flags & EXIT_REQUIRED) == EXIT_REQUIRED) {\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ }\r
+\r
+ if ((DataEntry->Flags & SAVE_REQUIRED) == SAVE_REQUIRED) {\r
+ Status = ConfigAccess->ConfigAccessProtocol.RouteConfig (\r
+ &ConfigAccess->ConfigAccessProtocol,\r
+ NULL,\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+ FreePool (Packet);\r
}\r
}\r
+\r
+ //\r
+ // Unregister notify for Form package update\r
+ //\r
+ Status = mHiiDatabase->UnregisterPackageNotify (\r
+ mHiiDatabase,\r
+ NotifyHandle\r
+ );\r
+ //\r
+ // UEFI SetupBrowser behaves differently with Framework SetupBrowser when call back function \r
+ // update any forms in HII database. UEFI SetupBrowser will re-parse the displaying form package and load\r
+ // the values from variable storages. Framework SetupBrowser will only re-parse the displaying form packages.\r
+ // To make sure customer's previous changes is saved and the changing question behaves as expected, we\r
+ // issue a EFI_BROWSER_ACTION_REQUEST_SUBMIT to ask UEFI SetupBrowser to save the changes proceed to re-parse\r
+ // the form and load all the variable storages.\r
+ //\r
+ if (*ActionRequest == EFI_BROWSER_ACTION_REQUEST_NONE && mHiiPackageListUpdated) {\r
+ mHiiPackageListUpdated= FALSE;\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ } else {\r
+ if (ConfigAccess->ThunkContext->FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS ||\r
+ ConfigAccess->ThunkContext->FormSet->SubClass == EFI_SINGLE_USE_SUBCLASS) {\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;\r
+ }\r
+ }\r
+\r
+\r
+ //\r
+ // Clean up.\r
+ //\r
+ DestroyIfrDataArray (Data, NvMapAllocated);\r
\r
return Status;\r
}\r