+\r
+ Offset += PackageHeader.Length;\r
+ }\r
+\r
+ if (Offset >= PackageListLength) {\r
+ //\r
+ // Form package not found in this Package List\r
+ //\r
+ FreePool (HiiPackageList);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (FormSetGuid != NULL) {\r
+ //\r
+ // Return the FormSet GUID\r
+ //\r
+ CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
+ }\r
+\r
+ //\r
+ // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes\r
+ // in this FormSet; So, here just simply copy the data from start of a FormSet to the end\r
+ // of the Form Package.\r
+ //\r
+ *BinaryLength = PackageHeader.Length - Offset2;\r
+ *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);\r
+\r
+ FreePool (HiiPackageList);\r
+\r
+ if (*BinaryData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Initialize the internal data structure of a FormSet.\r
+\r
+ @param Handle PackageList Handle\r
+ @param FormSetGuid On input, GUID or class GUID of a formset. If not\r
+ specified (NULL or zero GUID), take the first\r
+ FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+ found in package list.\r
+ On output, GUID of the formset found(if not NULL).\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_NOT_FOUND The specified FormSet could not be found.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeFormSet (\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN OUT EFI_GUID *FormSetGuid,\r
+ OUT FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE DriverHandle;\r
+\r
+ Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
+ FormSet->HiiHandle = Handle;\r
+ CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+ FormSet->QuestionInited = FALSE;\r
+\r
+ //\r
+ // Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
+ //\r
+ Status = mHiiDatabase->GetPackageListHandle (mHiiDatabase, Handle, &DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ FormSet->DriverHandle = DriverHandle;\r
+ Status = gBS->HandleProtocol (\r
+ DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ (VOID **) &FormSet->ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Configuration Driver don't attach ConfigAccess protocol to its HII package\r
+ // list, then there will be no configuration action required\r
+ //\r
+ FormSet->ConfigAccess = NULL;\r
+ }\r
+\r
+ //\r
+ // Parse the IFR binary OpCodes\r
+ //\r
+ Status = ParseOpCodes (FormSet);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Save globals used by previous call to SendForm(). SendForm() may be called from \r
+ HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
+ So, save globals of previous call to SendForm() and restore them upon exit.\r
+\r
+**/\r
+VOID\r
+SaveBrowserContext (\r
+ VOID\r
+ )\r
+{\r
+ BROWSER_CONTEXT *Context;\r
+ FORM_ENTRY_INFO *MenuList;\r
+\r
+ gBrowserContextCount++;\r
+ if (gBrowserContextCount == 1) {\r
+ //\r
+ // This is not reentry of SendForm(), no context to save\r
+ //\r
+ return;\r
+ }\r
+\r
+ Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
+ ASSERT (Context != NULL);\r
+\r
+ Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
+\r
+ //\r
+ // Save FormBrowser context\r
+ //\r
+ Context->Selection = gCurrentSelection;\r
+ Context->ResetRequired = gResetRequired;\r
+ Context->ExitRequired = gExitRequired;\r
+ Context->HiiHandle = mCurrentHiiHandle;\r
+ Context->FormId = mCurrentFormId;\r
+ CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
+\r
+ //\r
+ // Save the menu history data.\r
+ //\r
+ InitializeListHead(&Context->FormHistoryList);\r
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
+ }\r
+\r
+ //\r
+ // Insert to FormBrowser context list\r
+ //\r
+ InsertHeadList (&gBrowserContextList, &Context->Link);\r
+}\r
+\r
+\r
+/**\r
+ Restore globals used by previous call to SendForm().\r
+\r
+**/\r
+VOID\r
+RestoreBrowserContext (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ BROWSER_CONTEXT *Context;\r
+ FORM_ENTRY_INFO *MenuList;\r
+\r
+ ASSERT (gBrowserContextCount != 0);\r
+ gBrowserContextCount--;\r
+ if (gBrowserContextCount == 0) {\r
+ //\r
+ // This is not reentry of SendForm(), no context to restore\r
+ //\r
+ return;\r
+ }\r
+\r
+ ASSERT (!IsListEmpty (&gBrowserContextList));\r
+\r
+ Link = GetFirstNode (&gBrowserContextList);\r
+ Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+\r
+ //\r
+ // Restore FormBrowser context\r
+ //\r
+ gCurrentSelection = Context->Selection;\r
+ gResetRequired = Context->ResetRequired;\r
+ gExitRequired = Context->ExitRequired;\r
+ mCurrentHiiHandle = Context->HiiHandle;\r
+ mCurrentFormId = Context->FormId;\r
+ CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
+\r
+ //\r
+ // Restore the menu history data.\r
+ //\r
+ while (!IsListEmpty (&Context->FormHistoryList)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
+ }\r
+\r
+ //\r
+ // Remove from FormBrowser context list\r
+ //\r
+ RemoveEntryList (&Context->Link);\r
+ gBS->FreePool (Context);\r
+}\r
+\r
+/**\r
+ Find the matched FormSet context in the backup maintain list based on HiiHandle.\r
+ \r
+ @param Handle The Hii Handle.\r
+ \r
+ @return the found FormSet context. If no found, NULL will return.\r
+\r
+**/\r
+FORM_BROWSER_FORMSET * \r
+GetFormSetFromHiiHandle (\r
+ EFI_HII_HANDLE Handle\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ if (!ValidateFormSet(FormSet)) {\r
+ continue;\r
+ }\r
+ if (FormSet->HiiHandle == Handle) {\r
+ return FormSet;\r
+ }\r
+ }\r
+ \r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Check whether the input HII handle is the FormSet that is being used.\r
+ \r
+ @param Handle The Hii Handle.\r
+ \r
+ @retval TRUE HII handle is being used.\r
+ @retval FALSE HII handle is not being used.\r
+\r
+**/\r
+BOOLEAN\r
+IsHiiHandleInBrowserContext (\r
+ EFI_HII_HANDLE Handle\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ BROWSER_CONTEXT *Context;\r
+\r
+ //\r
+ // HiiHandle is Current FormSet.\r
+ //\r
+ if (mCurrentHiiHandle == Handle) {\r
+ return TRUE;\r
+ }\r
+\r
+ //\r
+ // Check whether HiiHandle is in BrowserContext.\r
+ //\r
+ Link = GetFirstNode (&gBrowserContextList);\r
+ while (!IsNull (&gBrowserContextList, Link)) {\r
+ Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+ if (Context->HiiHandle == Handle) {\r
+ //\r
+ // HiiHandle is in BrowserContext\r
+ //\r
+ return TRUE;\r
+ }\r
+ Link = GetNextNode (&gBrowserContextList, Link);\r
+ }\r
+ \r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Perform Password check. \r
+ Passwork may be encrypted by driver that requires the specific check.\r
+ \r
+ @param Form Form where Password Statement is in.\r
+ @param Statement Password statement\r
+ @param PasswordString Password string to be checked. It may be NULL.\r
+ NULL means to restore password.\r
+ "" string can be used to checked whether old password does exist.\r
+ \r
+ @return Status Status of Password check.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PasswordCheck (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_STRING PasswordString OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_IFR_TYPE_VALUE IfrTypeValue;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
+ Question = GetBrowserStatement(Statement);\r
+ ASSERT (Question != NULL);\r
+\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ if (PasswordString == NULL) {\r
+ return EFI_SUCCESS;\r
+ } \r
+ \r
+ if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_READY;\r
+ }\r